流沙团
重定位表的移动
2017-11-17 流沙团


很笨的方法



(写过才能知道,哪些地方,需要注意,开始想的很简单,就三部,写了 一个多小时!!)



void TestMoveRelocDirectory(LPSTR lpszFile)
{
/*
1 新增一个节
2 把重定位的表 移动到那个节中
3 更改标志位
*/
LPVOID pFileBuffer = NULL;
pFileBuffer= ReadPEFile(lpszFile);
if(!pFileBuffer)
{
printf("文件读取失败\n");
return;
}

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;
PIMAGE_SECTION_HEADER pSectionHeader_ADD = NULL;
PIMAGE_DATA_DIRECTORY DataDirectory=NULL;

//Header信息
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+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);
pSectionHeader_ADD = pSectionHeader;

//1 判断能否添加节
DWORD Header_size = pDosHeader->e_lfanew + 4 + 20 + pPEHeader->SizeOfOptionalHeader + pPEHeader->NumberOfSections*40;
if(pOptionHeader->SizeOfHeaders-Header_size<80)
{
printf("没有可用空间填充节表\n");
free(pFileBuffer);
return;
}

printf("空间:%d\n",pOptionHeader->SizeOfHeaders-Header_size);


//添加一个节
//确定参数
PIMAGE_SECTION_HEADER pSectionHeader_LAST = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);
pSectionHeader_ADD=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader_ADD+(pPEHeader->NumberOfSections)*40);
//="NewSec";
strcpy((char*)pSectionHeader_ADD->Name,"NewSec");
pSectionHeader_ADD->Misc.VirtualSize = 0x2000;
pSectionHeader_ADD->VirtualAddress = pOptionHeader->SizeOfImage;
pSectionHeader_ADD->SizeOfRawData = 0x2000;
pSectionHeader_ADD->PointerToRawData = pSectionHeader_LAST->PointerToRawData+pSectionHeader_LAST->SizeOfRawData;
pSectionHeader_ADD->Characteristics = pSectionHeader->Characteristics;

//填充0
LPVOID pSectionEND = (LPVOID)((DWORD)pSectionHeader_ADD+40);
memset(pSectionEND,0,IMAGE_SIZEOF_SECTION_HEADER);


//修改PE头信息
pPEHeader->NumberOfSections = pPEHeader->NumberOfSections +1;
pOptionHeader->SizeOfImage = pOptionHeader->SizeOfImage+0x2000;

//写入到文件
FILE *pOutFile = NULL;
//打开文件
pOutFile = fopen("C://addSec.dll","a+b");

if(!pOutFile)
{
printf("无法打开文件EXE文件");
return;
}
//写出第一部分
printf("length: %x \n ",pSectionHeader_ADD->PointerToRawData+pSectionHeader_ADD->SizeOfRawData);

size_t writeSize = fwrite(pFileBuffer,pSectionHeader_ADD->PointerToRawData,1,pOutFile);
printf("WirteSize:%d\n",writeSize);
//写出第二部分
LPVOID pNewBuffer=(LPVOID)malloc(0x2000);
if(pNewBuffer==NULL)
{
printf("pNewBuffer分配空间失败\n");
return;
}
memset(pNewBuffer,0,0x2000);
writeSize = fwrite(pNewBuffer,0x2000,1,pOutFile);
//关闭文件
fclose(pOutFile);
free(pFileBuffer);
free(pNewBuffer);

//读入添加好节的文件
pFileBuffer= ReadPEFile("C://addSec.dll");

//将重定位表的信息,放到最后一个节中
//Header信息
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+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);
//最后一个节
pSectionHeader_ADD=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);

//定位Directory_Data;
DataDirectory = pOptionHeader->DataDirectory;

//重定位表

printf("IMAGE_DIRECTORY_ENTRY_BASERELOC: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);

//DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva)
DWORD FoA = RVAToFileOffset(pFileBuffer,0x2df10);

DWORD BaseReloc_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
DWORD BaseReloc_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
FoA = RVAToFileOffset(pFileBuffer,BaseReloc_Directory_Address);


//定位到第一个重定位块
PIMAGE_BASE_RELOCATION pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA);
PIMAGE_BASE_RELOCATION pRelocData_Start = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA);

DWORD sizeOfRelocDirectory = 0;
//计算重定位表的大小
while(pRelocData->VirtualAddress||pRelocData->SizeOfBlock)
{
DWORD RelocVirtualAddress = pRelocData->VirtualAddress;
DWORD RelocSize = pRelocData->SizeOfBlock;

sizeOfRelocDirectory = sizeOfRelocDirectory + RelocSize;

pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocData + RelocSize);
}

//起始位置pRelocData


//移动
PDWORD myRelocLoc = (PDWORD)pSectionHeader_ADD->PointerToRawData;
printf("Reloc: %x , Size: %x \n",pRelocData,sizeOfRelocDirectory);


//memcpy(myRelocLoc,pRelocData,sizeOfRelocDirectory);
LPVOID destStart = (LPVOID)((DWORD)pFileBuffer + (DWORD)myRelocLoc);

printf("pFileBuffer:%x, myRelocLoc: %x \n",pFileBuffer,destStart);

LPVOID srcStart = (LPVOID)(pRelocData_Start);

memcpy(destStart,srcStart,sizeOfRelocDirectory);


//修改重定位表的参数
DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = FileOffsetToRVA(pFileBuffer,pSectionHeader_ADD->PointerToRawData);

//写出到dll中
DWORD FileSize = pSectionHeader_ADD->PointerToRawData + pSectionHeader_ADD->SizeOfRawData;

WirteToFile(pFileBuffer,FileSize,"C://addNewSec.dll");

}


 

发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容