Win32 C ++ - Memcpy函数 - 访问冲突错误

时间:2013-05-26 01:42:11

标签: c++ winapi memory memcpy portable-executable

我正在制作一个自解压程序,它实际上获取了一个指向所提取数据的指针(硬编码)并将其添加到缓冲区,我将从中执行操作,

但是,我遇到了一个问题,我似乎从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'.

此外,代码中断并转到此处:

Code break

我怀疑我试图读取不可读的内存(部分数据),但我不确定,

感谢您的时间。

1 个答案:

答案 0 :(得分:0)

int m_pageNumber = (m_psectionHeader->Misc.VirtualSize / si.dwPageSize);

这会将大小缩小到可能减去1的页数。你确定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);