前段时间学习PE写了一个添加节区的小工具,拿计算器测试了一下,可以添加90多个节区.
先介绍一下手动添加节区的方法
方法一:(适用于最后一个节区头部与第一个节区数据之间有0x28字节的空间)
方法二:重新编辑PE头(适用于最后一个节区头部与第一个节区数据之间没有0x28字节的空间)
方法三:扩充PE头
以下是部分代码
参考资料:http://bbs.pediy.com/showthread.php?t=103092
工具下载:附件 81344
先介绍一下手动添加节区的方法
方法一:(适用于最后一个节区头部与第一个节区数据之间有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;
}
工具下载:附件 81344