Я делаю самораспаковывающуюся программу, которая по сути получает указатель на извлекаемые данные (жестко запрограммированные) и добавляет их в буфер, из которого я буду выполнять операции,
Тем не менее, я столкнулся с проблемой, я, кажется, получаю ошибку переполнения буфера от моей функции memcpy, я пробовал memcpy_s, но возникает та же проблема:
Я не могу понять, почему функция не работает, так как я перемещаю данные в выделенную область в памяти с правильным размером,
LPVOID ExtractPayload(HINSTANCE _hInstance)
{
DWORD m_ptr = NULL;
PIMAGE_NT_HEADERS m_pntHeader;
PIMAGE_DOS_HEADER m_pdosHeader;
PIMAGE_SECTION_HEADER m_psectionHeader;
m_pdosHeader = (PIMAGE_DOS_HEADER)_hInstance; // we don't need to make checks
m_pntHeader = (PIMAGE_NT_HEADERS)((DWORD)m_pdosHeader + m_pdosHeader->e_lfanew);
m_psectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)m_pntHeader + sizeof(IMAGE_NT_HEADERS) + (40 * 4)); // pointing to desired section header
LPVOID m_pvFileBuffer = NULL;
SYSTEM_INFO si;
GetSystemInfo(&si);
printf("Virtual size %d\n",m_psectionHeader->Misc.VirtualSize);
int m_pageNumber = (m_psectionHeader->Misc.VirtualSize / si.dwPageSize);
if ((m_psectionHeader->Misc.VirtualSize % si.dwPageSize) > 0)
{
m_pageNumber++;
printf("pages : %i\n",m_pageNumber);
printf("page size: %i\n", si.dwPageSize);
}
m_pvFileBuffer = VirtualAlloc(NULL, (si.dwPageSize*m_pageNumber), MEM_RESERVE, PAGE_NOACCESS);
for (unsigned int i = 0; i < m_pageNumber*si.dwPageSize; i += si.dwPageSize)
{
// we need a char* to pointer arithmetic with
char* p = reinterpret_cast<char*>(m_pvFileBuffer);
// reserve the ith page
VirtualAlloc(p + i, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE);
}
printf("lpvoid : %d",m_pvFileBuffer);
m_ptr = Rva2Offset(m_psectionHeader->VirtualAddress,m_psectionHeader,m_pntHeader->FileHeader.NumberOfSections);
memcpy(m_pvFileBuffer,(DWORD*)m_ptr,m_psectionHeader->Misc.VirtualSize);
//memcpy(&m_pvFileBuffer,&m_ptr,m_psectionHeader->Misc.VirtualSize); // buffer over-run here
//VirtualFree(m_pvFileBuffer,m_psectionHeader->Misc.VirtualSize,MEM_RELEASE);
cin.get();
return m_pvFileBuffer;
}
Вот ошибка:
First-chance exception at 0x002f16f3 in Stub.exe: 0xC0000005: Access violation reading location 0x00002a00. A buffer overrun has occurred in Stub.exe which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program. For more details please see Help topic 'How to debug Buffer Overrun Issues'.
Кроме того, код ломается и идет сюда:
У меня есть подозрение, что я пытаюсь прочитать нечитаемую память (данные раздела), однако я не уверен,
Спасибо за ваше время.
int m_pageNumber = (m_psectionHeader->Misc.VirtualSize / si.dwPageSize);
Это округляет размер до количества страниц, возможно, минус один. Вы уверены, что VirtualSize является кратным dwPageSize? потому что позже вы делаете:
memcpy(m_pvFileBuffer,(DWORD*)m_ptr,m_psectionHeader->Misc.VirtualSize);
и если VirtualSize не является кратным dwPageSize, то вы переходите далеко в memcpy ().
Я не знаю API достаточно хорошо, чтобы знать, правильно ли VirtualAlloc () распределяет все страницы, но другая проблема может заключаться в том, что функция не выполняет то, что вы думаете, поэтому запись на этих страницах приводит к нарушению памяти.
На всякий случай деление должно быть таким, если VirtualSize не может быть кратным dwPageSize ():
int m_pageNumber = ((m_psectionHeader->Misc.VirtualSize + si.dwPageSize - 1) / si.dwPageSize);
Других решений пока нет …