#include<stdio.h>
#include<windows.h>
DWORD toLoardPE(PVOID* pFileBuffer, PSTR file_path){
FILE *fp;
DWORD FileSize;
PVOID pFileBufferTemp;
fp = fopen(file_path, "rb");
if(!fp){
printf("读取文件失败!\n");
return 0;
}
fseek(fp, 0, SEEK_END);
FileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
pFileBufferTemp = malloc(FileSize);
if(!pFileBufferTemp){
printf("读取文件开辟内存失败\n");
return 0;
}
DWORD n = fread(pFileBufferTemp, FileSize, 1, fp);
*pFileBuffer = pFileBufferTemp;
pFileBufferTemp = NULL;
fclose(fp);
return FileSize;
}
DWORD Align(int add, int alignment){
if(add % alignment == 0){
return add;
}
return ((add / alignment) + 1) * alignment;
}
DWORD Rva2Foa(PVOID pFileBuffer, DWORD dwRva){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if(!pFileBuffer){
printf("从磁盘读取文件为空!\n");
return 0;
}
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
printf("(Rva2Foa)没有MZ标志!\n");
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*(PDWORD)((DWORD)pDosHeader + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE){
printf("(Rva2Foa)没有PE标志!\n");
return 0;
}
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
PIMAGE_SECTION_HEADER pNextSectionHeaderTemp = pSectionHeader + 1;
if(dwRva <= pOptionHeader->SizeOfHeaders){
return dwRva;
}else{
for(int n=1; n < pPEHeader->NumberOfSections; n++, pSectionHeaderTemp++, pNextSectionHeaderTemp++){
if((dwRva >= pSectionHeaderTemp->VirtualAddress) && (dwRva < (pNextSectionHeaderTemp->VirtualAddress)))
return dwRva - pSectionHeaderTemp->VirtualAddress + pSectionHeaderTemp->PointerToRawData;
}
}
if (dwRva >= pSectionHeaderTemp->VirtualAddress && dwRva < pOptionHeader->SizeOfImage)
{
return pSectionHeaderTemp->PointerToRawData + dwRva - pSectionHeaderTemp->VirtualAddress;
}
printf("RVA TO FOA Failed!\n");
return 0;
}
DWORD AddSection(PSTR file_path, PVOID* pFileBuffer, DWORD FileSize, PVOID* pNewFileBuffer){
int isUpHeader = 0;
//DWORD FileSize = toLordPE(file_path, pFileBuffer);
DWORD FileTotal = FileSize + 0x1000;
printf("%x\n",*pFileBuffer);
*pNewFileBuffer = malloc(FileTotal);
printf("%x\n",pNewFileBuffer);
printf("%x\n",*pNewFileBuffer);
if(!pNewFileBuffer){
printf("新增节内存分配失败!\n");
return 0;
}
memset(*pNewFileBuffer, 0, FileTotal);
memcpy(*pNewFileBuffer, *pFileBuffer, FileSize);
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
//printf("1\n");
printf("%x\n",*((PWORD)*pNewFileBuffer));
if (*((PWORD)*pNewFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("没有MZ标志!\n");
//free(*pNewFileBuffer);
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)*pNewFileBuffer;
if (*((PDWORD)((DWORD)(*pNewFileBuffer) + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
//printf("%x\n",pDosHeader->e_lfanew);
//printf("%x\n",*((PDWORD)((DWORD)(*pNewFileBuffer) + pDosHeader->e_lfanew)));
printf("没有PE标志!\n");
//free(*pNewFileBuffer);
return 0;
}
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)(*pNewFileBuffer) + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
for (DWORD i = 0; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
{
// for结束后,pSectionHeaderTemp指向最后一个节表的后面
//printf("%x\n",i);
}
// pLastSectionHeaderTemp 指向最后一个节表
PIMAGE_SECTION_HEADER pLastSectionHeaderTemp = pSectionHeaderTemp-1;
/*
PBYTE Temp = (PBYTE)pSectionHeaderTemp;
printf("%x\n",*(Temp+0));
printf("%x\n",*(Temp+1));
printf("%x\n",*(Temp+2));
printf("%x\n",*(Temp+3));
*/
// 节表后有没有多余空间
// 多余空间是不是0
if((DWORD)pSectionHeaderTemp + IMAGE_SIZEOF_SECTION_HEADER * 2 <= (pOptionHeader->SizeOfHeaders + (DWORD)(*pNewFileBuffer))){
PBYTE pSTemp = (PBYTE)pSectionHeaderTemp;
for(i = 0; i < (IMAGE_SIZEOF_SECTION_HEADER * 2); i++, pSTemp++){
if(*pSTemp){
// printf("%x\n",*(pSTemp+0));
printf("节表后面有数据,不能插入节表,尝试头抬升!\n");
// UpHeader(&pFileBuffer, &pNewFileBuffer);
isUpHeader = 1;
break;
}
}
printf("节表后有足够空间,且数据为0\n");
}else{
printf("节表后没有多余空间,尝试头抬升!\n");
isUpHeader = 1;
// UpHeader();
}
if(isUpHeader){
if((DWORD)pNTHeader - (DWORD)*pNewFileBuffer - sizeof(IMAGE_DOS_HEADER) >= IMAGE_SIZEOF_SECTION_HEADER * 2){
printf("抬升头\n");
memcpy((PVOID)((DWORD)*pNewFileBuffer + sizeof(IMAGE_DOS_HEADER)), pNTHeader, (DWORD)pSectionHeaderTemp - (DWORD)pNTHeader);
pDosHeader->e_lfanew = sizeof(IMAGE_DOS_HEADER);
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)(*pNewFileBuffer) + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
pSectionHeaderTemp = pSectionHeader;
for (DWORD i = 0; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
{
// for结束后,pSectionHeaderTemp指向最后一个节表的后面
//printf("%x\n",i);
}
// pLastSectionHeaderTemp 指向最后一个节表
pLastSectionHeaderTemp = pSectionHeaderTemp-1;
if (*((PDWORD)((DWORD)(*pNewFileBuffer) + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("(抬升后)没有PE标志!\n");
return 0;
}
printf("抬升成功\n");
memset(pSectionHeaderTemp, 0, IMAGE_SIZEOF_SECTION_HEADER * 2);
}else{
printf("(DOS Sub)没有足够的空间插入节表,不可以头抬升!\n");
return 0;
}
}
printf("插入节表\n");
memcpy(pSectionHeaderTemp, ".tttt", 8);
pSectionHeaderTemp->Misc.VirtualSize = 0x1000;
// pSectionHeaderTemp->VirtualAddress = pOptionHeader->SizeOfImage;
DWORD z = pLastSectionHeaderTemp->Misc.VirtualSize > pLastSectionHeaderTemp->SizeOfRawData ? pLastSectionHeaderTemp->Misc.VirtualSize : pLastSectionHeaderTemp->SizeOfRawData;
pSectionHeaderTemp->VirtualAddress = pLastSectionHeaderTemp->VirtualAddress + Align(z, pOptionHeader->SectionAlignment);
pSectionHeaderTemp->SizeOfRawData = Align(0x1000, pOptionHeader->FileAlignment);
pSectionHeaderTemp->PointerToRawData = pLastSectionHeaderTemp->PointerToRawData + pLastSectionHeaderTemp->SizeOfRawData;
pSectionHeaderTemp->Characteristics = 0x60000020;
// 修改节表数量
pPEHeader->NumberOfSections++;
// 修改SizeOfImage(按内存对齐)
pOptionHeader->SizeOfImage += Align(0x1000, pOptionHeader->SectionAlignment);
return FileTotal;
}
BOOL Memory2File(PVOID pNewFileBuffer, DWORD size, PSTR write_path){
FILE *fp;
fp = fopen(write_path, "wb");
if(!fp){
printf("(MemoryToFile)写入失败!\n");
return 0;
}
printf("mtf :%x\n", pNewFileBuffer);
fwrite(pNewFileBuffer, size, 1, fp);
fclose(fp);
return 1;
}
DWORD movRelocation(PVOID pNewFileBuffer){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER64 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_BASE_RELOCATION pRelocationTable = NULL;
PIMAGE_BASE_RELOCATION pRelocationTableTemp = NULL;
PIMAGE_BASE_RELOCATION pRelocationTableTemp2 = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)pNewFileBuffer;
pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNewFileBuffer + pDosHeader->e_lfanew + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER64)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pFileHeader->SizeOfOptionalHeader);
pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pNewFileBuffer + Rva2Foa(pNewFileBuffer, pOptionHeader->DataDirectory[5].VirtualAddress));
pRelocationTableTemp = pRelocationTable;
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
for(size_t i=1; i < pFileHeader->NumberOfSections; i++, pSectionHeaderTemp++){
// 循环结束后pSectionHeaderTemp指向最后一个节表
}
DWORD sizeOfRelocationTable = 0; // 记录重定位表的大小
printf("移动前\n");
while(pRelocationTableTemp->VirtualAddress && pRelocationTableTemp->SizeOfBlock){
printf("重定位表的VirtualAddress:%#x\n", pRelocationTableTemp->VirtualAddress);
printf("重定位表的SizeOfBlock:%#x\n", pRelocationTableTemp->SizeOfBlock);
printf("重定位表一共有多个要处理的地址:%#x\n", (pRelocationTableTemp->SizeOfBlock - 8) /2);
sizeOfRelocationTable += pRelocationTableTemp->SizeOfBlock;
pRelocationTableTemp = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocationTableTemp + pRelocationTableTemp->SizeOfBlock);
}
sizeOfRelocationTable += 8; // 加上重定位表末尾全零的八字节
printf("重定位表的大小:%#x\n",sizeOfRelocationTable);
memcpy((PVOID)((DWORD)pNewFileBuffer + pSectionHeaderTemp->PointerToRawData), pRelocationTable, sizeOfRelocationTable);
pOptionHeader->DataDirectory[5].VirtualAddress = pSectionHeaderTemp->VirtualAddress;
printf("修改目录项的重定位:%#x\n", pOptionHeader->DataDirectory[5].VirtualAddress);
// 测试移动后的结果
pRelocationTableTemp2 = (PIMAGE_BASE_RELOCATION)((DWORD)pNewFileBuffer + Rva2Foa(pNewFileBuffer, pOptionHeader->DataDirectory[5].VirtualAddress));
printf("移动后的重定位表的FOA:%#x\n",Rva2Foa(pNewFileBuffer, pOptionHeader->DataDirectory[5].VirtualAddress));
while(pRelocationTableTemp2->VirtualAddress && pRelocationTableTemp2->SizeOfBlock){
printf("重定位表的VirtualAddress:%#x\n", pRelocationTableTemp2->VirtualAddress);
printf("重定位表的SizeOfBlock:%#x\n", pRelocationTableTemp2->SizeOfBlock);
printf("重定位表一共有多个要处理的地址:%#x\n", (pRelocationTableTemp2->SizeOfBlock - 8) /2);
pRelocationTableTemp2 = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocationTableTemp2 + pRelocationTableTemp2->SizeOfBlock);
}
return 0;
}
int main(){
PSTR file_path = "C:\\Users\\lolol\\Desktop\\notepad.exe";
PSTR write_path = "C:\\Users\\lolol\\Desktop\\notepad3.exe";
PVOID pFileBuffer = NULL;
PVOID pNewFileBuffer = NULL;
DWORD FileSize = toLoardPE(&pFileBuffer, file_path);
printf("文件在磁盘上的大小:%x\n", FileSize);
DWORD FileTotal = AddSection(file_path, &pFileBuffer, FileSize, &pNewFileBuffer);
printf("新增节后的大小:%x\n",FileTotal);
printf("===========移动重定位表============\n");
movRelocation(pNewFileBuffer);
Memory2File(pNewFileBuffer, FileTotal, write_path);
return 0;
}
PE_移动重定位表
最新推荐文章于 2024-05-22 18:20:08 发布