最近正在学习PE文件结构,就想着自己试着实现添加一个新的节,因本人比较菜
,所以无法添加成功。现在把代码贴出来,希望哪位大神帮忙看一下哪里出错了
#define FILEIN "C:\\Windows\\notepad.exe"
#define FILEOUT "C:\\notepad.exe"
#define SHELLCODELENGTH 0x12
#define MESSAGEBOXADDR 0x77D507EA
BYTE shellCode[] =
{
0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE9, 0x00, 0x00, 0x00, 0x00
};
//判断是否为PE文件
BOOL IsPEFile(LPVOID ImageBase)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeader = NULL;
if (!ImageBase)
{
return FALSE;
}
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return FALSE;
}
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
return FALSE;
}
return TRUE;
}
//得到NTHeader
PIMAGE_NT_HEADERS GetNtHeader(LPVOID ImageBase)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeader = NULL;
if (!IsPEFile(ImageBase))
{
return NULL;
}
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
return pNtHeader;
}
//得到FileHeader
PIMAGE_FILE_HEADER GetFileHeader(LPVOID ImageBase)
{
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
pNtHeader = GetNtHeader(ImageBase);
if (!pNtHeader)
{
return NULL;
}
pFileHeader = &pNtHeader->FileHeader;
return pFileHeader;
}
//得到OptionalHeader
PIMAGE_OPTIONAL_HEADER GetOptionalHeader(LPVOID ImageBase)
{
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pNtHeader = GetNtHeader(ImageBase);
if (!pNtHeader)
{
return NULL;
}
pOptionHeader = &pNtHeader->OptionalHeader;
return pOptionHeader;
}
//得到第一个节表
PIMAGE_SECTION_HEADER GetFirstSectionHeader(LPVOID ImageBase)
{
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pNtHeader = GetNtHeader(ImageBase);
if (!pNtHeader)
{
return NULL;
}
pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
return pSectionHeader;
}
//FileBuffer到ImageBuffer
DWORD FileBufferToImageBuffer(LPVOID pFileBuffer, LPVOID* pImageBuffer)
{
DWORD numberSection = 0;
LPVOID pTempImageBuffer = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if (!IsPEFile(pFileBuffer))
{
printf("不是标准的PE文件!\n");
return 0;
}
pFileHeader = GetFileHeader(pFileBuffer);
pOptionHeader = GetOptionalHeader(pFileBuffer);
pSectionHeader = GetFirstSectionHeader(pFileBuffer);
if (!pFileHeader || !pOptionHeader || !pSectionHeader)
{
return 0;
}
//获取节数、分配ImageBuffer
numberSection = pFileHeader->NumberOfSections;
pTempImageBuffer = malloc(pOptionHeader->SizeOfImage);
if (!pTempImageBuffer)
{
printf("分配内存失败!\n");
return 0;
}
//初始化为0
memset(pTempImageBuffer, 0, pOptionHeader->SizeOfImage);
//拷贝PE头
memcpy(pTempImageBuffer, pFileBuffer, pOptionHeader->SizeOfHeaders);
//拷贝节
for (DWORD i=0; i<numberSection; i++, pSectionHeader++)
{
memcpy((LPVOID)((DWORD)pTempImageBuffer+pSectionHeader->VirtualAddress),
(LPVOID)((DWORD)pFileBuffer+pSectionHeader->PointerToRawData),
pSectionHeader->SizeOfRawData);
}
//收尾处理
*pImageBuffer = pTempImageBuffer;
pTempImageBuffer = NULL;
return pOptionHeader->SizeOfImage;
}
//ImageBuffer到NewBuffer
DWORD ImageBufferToNewBuffer(LPVOID pImageBuffer, LPVOID* pNewBuffer)
{
DWORD numberSection = 0;
LPVOID pTempNewBuffer = NULL;
DWORD dwFileSize = 0;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if (!IsPEFile(pImageBuffer))
{
printf("不是标准的PE文件!\n");
return 0;
}
pFileHeader = GetFileHeader(pImageBuffer);
pOptionHeader = GetOptionalHeader(pImageBuffer);
pSectionHeader = GetFirstSectionHeader(pImageBuffer);
if (!pFileHeader || !pOptionHeader || !pSectionHeader)
{
return 0;
}
//获取节数、分配ImageBuffer
numberSection = pFileHeader->NumberOfSections;
dwFileSize = pSectionHeader[numberSection-1].PointerToRawData+pSectionHeader[numberSection-1].SizeOfRawData;
pTempNewBuffer = malloc(dwFileSize);
//初始化
memset(pTempNewBuffer, 0, dwFileSize);
//拷贝头
memcpy(pTempNewBuffer, pImageBuffer, pOptionHeader->SizeOfHeaders);
for (DWORD i=0; i<numberSection; i++, pSectionHeader++)
{
memcpy((LPVOID)((DWORD)pTempNewBuffer+pSectionHeader->PointerToRawData),
(LPVOID)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress),
pSectionHeader->SizeOfRawData);
}
*pNewBuffer = pTempNewBuffer;
pTempNewBuffer = NULL;
return dwFileSize;
}
//写入文件
BOOLEAN Write(LPVOID pMemBuffer, DWORD size, LPSTR lpszFile)
{
FILE* pFile = NULL;
pFile = fopen(lpszFile, "wb+");
if (!pFile)
{
return FALSE;
}
fwrite(pMemBuffer, 1, size, pFile);
fclose(pFile);
return TRUE;
}
//任意节添加代码
VOID AddCodeInAnySection(DWORD index)
{
DWORD dwFileSize = 0;
PBYTE codeBegin = NULL;
BOOL isOk = FALSE;
DWORD numberSection = 0;
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
Read(FILEIN, &pFileBuffer);
if (!pFileBuffer)
{
printf("读取文件到FileBuffer失败!\n");
return;
}
FileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
if (!pImageBuffer)
{
printf("从FileBuffer到ImageBuffer失败!\n");
free(pFileBuffer);
return;
}
pFileHeader = GetFileHeader(pImageBuffer);
pOptionHeader = GetOptionalHeader(pImageBuffer);
pSectionHeader = GetFirstSectionHeader(pImageBuffer);
numberSection = pFileHeader->NumberOfSections;
if (index >= numberSection)
{
printf("代码区空闲空间不够!\n");
free(pFileBuffer);
free(pImageBuffer);
return;
}
pSectionHeader = pSectionHeader + index;
//写入数据
codeBegin = (PBYTE)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress+pSectionHeader->Misc.VirtualSize);
memcpy(codeBegin, shellCode, SHELLCODELENGTH);
//修正E8
DWORD callAddr = MESSAGEBOXADDR - (pOptionHeader->ImageBase+((DWORD)(codeBegin+0xD)-(DWORD)pImageBuffer));
*(PDWORD)(codeBegin+9) = callAddr;
//修复E9
DWORD jmpAddr = (pOptionHeader->ImageBase+pOptionHeader->AddressOfEntryPoint)- (pOptionHeader->ImageBase+ ((DWORD)(codeBegin+0x12)-(DWORD)pImageBuffer));
*(PDWORD)(codeBegin+0xE) = jmpAddr;
//修复OEP
pOptionHeader->AddressOfEntryPoint = (DWORD)codeBegin - (DWORD)pImageBuffer;
//拷贝属性
DWORD x = (pSectionHeader-index)->Characteristics;
DWORD y = (pSectionHeader)->Characteristics;
pSectionHeader->Characteristics = x | y;
//ImageBuffer到NewBuffer
dwFileSize = ImageBufferToNewBuffer(pImageBuffer, &pNewBuffer);
if (dwFileSize==0 || !pNewBuffer)
{
printf("从ImageBuffer到NewBuffer失败!\n");
free(pFileBuffer);
free(pImageBuffer);
return;
}
//存盘
isOk = Write(pNewBuffer, dwFileSize, FILEOUT);
if (isOk)
{
printf("存盘成功!\n");
return;
}
//释放内存
free(pFileBuffer);
free(pImageBuffer);
free(pNewBuffer);
}
//添加新节
VOID AddNewSection()
{
BOOL isOk = FALSE;
DWORD dwFileSize = 0;
DWORD numberSection = 0;
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
LPVOID pNewImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
Read(FILEIN, &pFileBuffer);
if (!pFileBuffer)
{
printf("读取文件到FileBuffer失败!\n");
return;
}
FileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
if (!pImageBuffer)
{
printf("从FileBuffer到ImageBuffer失败!\n");
free(pFileBuffer);
return;
}
pFileHeader = GetFileHeader(pImageBuffer);
pOptionHeader = GetOptionalHeader(pImageBuffer);
pSectionHeader = GetFirstSectionHeader(pImageBuffer);
numberSection = pFileHeader->NumberOfSections;
pNewImageBuffer = malloc(pOptionHeader->SizeOfImage+0x1000);
if (!pNewImageBuffer)
{
printf("新增空间失败!\n");
free(pFileBuffer);
free(pImageBuffer);
return;
}
if ((pOptionHeader->SizeOfHeaders-((DWORD)pSectionHeader+IMAGE_SIZEOF_SECTION_HEADER*numberSection)) < IMAGE_SIZEOF_SECTION_HEADER*2)
{
printf("空闲空间不够!\n");
free(pFileBuffer);
free(pImageBuffer);
return;
}
memcpy(pNewImageBuffer, pImageBuffer, pOptionHeader->SizeOfImage);
pDosHeader = (PIMAGE_DOS_HEADER)pNewImageBuffer;
pOptionHeader = GetOptionalHeader(pNewImageBuffer);
pSectionHeader = GetFirstSectionHeader(pNewImageBuffer);
memcpy((PVOID)((DWORD)pNewImageBuffer+sizeof(IMAGE_DOS_HEADER)),
(PVOID)((DWORD)pNewImageBuffer+pDosHeader->e_lfanew),
IMAGE_SIZEOF_FILE_HEADER+pFileHeader->SizeOfOptionalHeader+IMAGE_SIZEOF_SECTION_HEADER*numberSection+4);
pDosHeader->e_lfanew = (DWORD)pImageBuffer+sizeof(IMAGE_DOS_HEADER);
memcpy(pSectionHeader+numberSection, pSectionHeader, IMAGE_SIZEOF_SECTION_HEADER);
memset(pSectionHeader+numberSection+1, 0, IMAGE_SIZEOF_SECTION_HEADER);
//设置属性
strcpy((char*)(pSectionHeader+numberSection), "NewSec");
(pSectionHeader+numberSection)->Misc.VirtualSize = 0x1000;
(pSectionHeader+numberSection)->SizeOfRawData = 0x1000;
(pSectionHeader+numberSection)->VirtualAddress = (pSectionHeader+numberSection-1)->SizeOfRawData>(pSectionHeader+numberSection-1)->Misc.VirtualSize?(pSectionHeader+numberSection-1)->SizeOfRawData:(pSectionHeader+numberSection-1)->Misc.VirtualSize;
(pSectionHeader+numberSection)->PointerToRawData = (pSectionHeader+numberSection-1)->PointerToRawData+(pSectionHeader+numberSection-1)->SizeOfRawData;
pOptionHeader->SizeOfImage += 0x1000;
pFileHeader->NumberOfSections += 1;
//ImageBuffer到NewBuffer
dwFileSize = ImageBufferToNewBuffer(pNewImageBuffer, &pNewBuffer);
if (dwFileSize==0 || !pNewBuffer)
{
printf("从ImageBuffer到NewBuffer失败!\n");
free(pFileBuffer);
free(pImageBuffer);
return;
}
//存盘
isOk = Write(pNewBuffer, dwFileSize, FILEOUT);
if (isOk)
{
printf("存盘成功!\n");
}
//释放内存
free(pFileBuffer);
free(pImageBuffer);
free(pNewBuffer);
free(pNewImageBuffer);
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)