前段时间学习PE写了一个添加节区的小工具,拿计算器测试了一下,可以添加90多个节区.
先介绍一下手动添加节区的方法
方法一:(适用于最后一个节区头部与第一个节区数据之间有0x28字节的空间)
方法二:重新编辑PE头(适用于最后一个节区头部与第一个节区数据之间没有0x28字节的空间)
方法三:扩充PE头
以下是部分代码
参考资料:http://bbs.pediy.com/showthread.php?t=103092
先介绍一下手动添加节区的方法
方法一:(适用于最后一个节区头部与第一个节区数据之间有0x28字节的空间)
代码:
1.添加节区数据(文件对齐值) 2.修改节数量 3.添加IMAGE_SECTION_HEADER 4.修改SizeOfImage
代码:
1.把NT头 + 节区头部 复制粘贴到Dos Stub 2.修改DOS头的e_lfanew偏移为原Dos Stub位置 3.调用方法1
代码:
1.PE头部后面添加一个文件对齐值的大小(0x200) 2.修改SizeOfHeaders 3.修正所有节区的文件偏移 4.调用方法1
代码:
IMAGE_SECTION_HEADER CMyPEFile::AddSection(CString strSectionName, DWORD dwSectionSize) { DWORD dwSectionOffset = GetSectionOffset(0); WORD wNumberOfSections = GetNumberOfSections(); dwSectionOffset += wNumberOfSections * sizeof(IMAGE_SECTION_HEADER); DWORD dwSizeOfHeader = GetSizeOfHeaders(); IMAGE_SECTION_HEADER AddSectionHeader = {0}; DWORD dwFreeLen = dwSizeOfHeader - dwSectionOffset; if(dwFreeLen >= sizeof(IMAGE_SECTION_HEADER)) { /* 方法一:(适用于最后一个节区头部与第一个节区数据之间有0x28字节的空间) 1.添加节区数据(文件对齐值) 2.修改节数量 3.添加IMAGE_SECTION_HEADER 4.修改SizeOfImage */ SetNumberOfSections(wNumberOfSections + 1); m_NtHeaders.FileHeader.NumberOfSections += 1; DWORD SectionAlignment = CheckSectionAlignment(dwSectionSize); DWORD dwSizeofImage = GetSizeOfImage(); SetSizeOfImage(dwSizeofImage + SectionAlignment); IMAGE_SECTION_HEADER SectionHeader = {0}; GetSectionHeader(&SectionHeader, wNumberOfSections - 1); ZeroMemory(&AddSectionHeader, sizeof(IMAGE_SECTION_HEADER)); memcpy(AddSectionHeader.Name, strSectionName, strSectionName.GetLength() > 8 ? 8: strSectionName.GetLength()); AddSectionHeader.Misc.VirtualSize = (DWORD)dwSectionSize; AddSectionHeader.VirtualAddress = CheckSectionAlignment(SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize); AddSectionHeader.SizeOfRawData = CheckFileAlignment(dwSectionSize); AddSectionHeader.PointerToRawData =SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData; AddSectionHeader.Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; SetSectionHeader(AddSectionHeader, wNumberOfSections); SeekToEnd(); TCHAR* lpBuf = new TCHAR[AddSectionHeader.SizeOfRawData]; if (lpBuf) { ZeroMemory(lpBuf, AddSectionHeader.SizeOfRawData); Write(lpBuf, AddSectionHeader.SizeOfRawData); delete[] lpBuf; lpBuf = NULL; if (GetNumberOfRvaAndSizes() > IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT) { ZeroBoundImportDataDir(); } } } else if (dwFreeLen < sizeof(IMAGE_SECTION_HEADER)) { DWORD dwStubLen = m_DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER); if ((dwFreeLen + dwStubLen) >= sizeof(IMAGE_SECTION_HEADER)) { /* 方法二:重新编辑PE头(适用于最后一个节区头部与第一个节区数据之间没有0x28字节的空间) 1.把NT头 + 节区头部 复制粘贴到Dos Stub 2.修改DOS头的e_lfanew偏移为原Dos Stub位置 3.调用方法1 */ DWORD dwNumOfReads = dwSectionOffset - m_DosHeader.e_lfanew; Seek(m_DosHeader.e_lfanew, CFile::begin); char* lpBuffer = new char[dwNumOfReads]; if (lpBuffer) { Read(lpBuffer, dwNumOfReads); DWORD dwlfamew = sizeof(IMAGE_DOS_HEADER); Seek(dwlfamew, CFile::begin); Write(lpBuffer, dwNumOfReads); SetEe_lfanew(dwlfamew); AddSection(strSectionName, dwSectionSize); delete[] lpBuffer; lpBuffer = NULL; } } else { /* 方法三:扩充PE头 1.PE头部后面添加一个文件对齐值的大小(0x200) 2.修改SizeOfHeaders 3.修正所有节区的文件偏移 4.调用方法1 */ DWORD dwSizeOfHeader = GetSizeOfHeaders(); DWORD dwAddSize = GetFileAlignment(); DWORD dwBufLen = GetPeFileSize() - dwSizeOfHeader; char* lpBuffer = new char[dwBufLen]; if (lpBuffer) { Seek(dwSizeOfHeader, CFile::begin); UINT nRet = Read(lpBuffer, dwBufLen); Seek(dwSizeOfHeader, CFile::begin); char* lpSectionBuf = new char[dwAddSize]; ZeroMemory(lpSectionBuf, dwAddSize); if (lpSectionBuf) { Write(lpSectionBuf, dwAddSize); Write(lpBuffer, dwBufLen); SetSizeOfHeaders(dwSizeOfHeader + dwAddSize); AddAllSectionPointerOfRawData(dwAddSize); AddSection(strSectionName, dwSectionSize); delete[] lpSectionBuf; lpSectionBuf = NULL; } delete[] lpBuffer; lpBuffer = NULL; } } } ReadAllHeader(); return AddSectionHeader; }