天天看點

PE 移動導出表

移動各種表的原因:

PE 移動導出表

void MoveExportTable(PVOID pFileBuffer,PDWORD OldBufferSize,PVOID* pNewBuffer){
	PIMAGE_DOS_HEADER pImageDosHeader = NULL;
	PIMAGE_FILE_HEADER pImageFileHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pImageOptionalHeader = NULL;
	PIMAGE_SECTION_HEADER pImageSectionHeaderGroup = NULL;
	PIMAGE_SECTION_HEADER NewSec = NULL;

	PIMAGE_EXPORT_DIRECTORY EXPORT_TABLE = NULL;
	PIMAGE_EXPORT_DIRECTORY EXPORT_TABLE_NewBuffer = NULL;

	PDWORD AddressFunctionName;
	DWORD RVA = 0;
	DWORD FOA = 0;
	PDWORD pTempAddress;

	int FunNameLen = 0;

	char FunName[10] = {0};

	int i = 0;
	int j = 0;
	DWORD all_num = 0;


	DWORD isOk;
	DWORD NewLength=0;
	PVOID LastSection = NULL;
	PVOID CodeSection = NULL;

	pImageDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4);
	pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER));
	pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader);
	
	/*
	第一步:新增節
	*/

	//判斷是否可以容納相應的節表
	isOk = (DWORD)pImageOptionalHeader->SizeOfHeaders - ((DWORD)pImageDosHeader->e_lfanew + IMAGE_SIZEOF_FILE_HEADER + pImageFileHeader->SizeOfOptionalHeader + 40*pImageFileHeader->NumberOfSections);
	if(isOk < 80){
		printf("空間太小 無法進行添加!");
		return;
	}

	//申請對應的記憶體大小的空間
	NewLength += *OldBufferSize + 0x1000;
	*pNewBuffer = (PVOID)malloc(NewLength);
	ZeroMemory(*pNewBuffer,NewLength);

	//拷貝之前記憶體空間 到 目前新生成的記憶體空間
	memcpy(*pNewBuffer,pFileBuffer,*OldBufferSize);

	//擷取新的空間中的PE結構體
	pImageDosHeader = (PIMAGE_DOS_HEADER)(*pNewBuffer);
	pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4);
	pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER));
	pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader);
	
	// pImageFileHeader->NumberOfSections修改
	pImageFileHeader->NumberOfSections = pImageFileHeader->NumberOfSections + 1;
	
	// pImageOptionalHeader->SizeOfImage修改
	pImageOptionalHeader->SizeOfImage = (DWORD)pImageOptionalHeader->SizeOfImage + 0x1000;
	
	// 複制代碼段的節資料到 目前最後一個節資料後面
	CodeSection = (PVOID)(&pImageSectionHeaderGroup[0]);
	LastSection = (PVOID)(DWORD)(&pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1]);
	memcpy(LastSection,CodeSection,40);
	
	//修正相關屬性
 	NewSec = (PIMAGE_SECTION_HEADER)LastSection;
	strcpy(NewSec,".NewSec");
	NewSec->Misc.VirtualSize = 0x1000;
	NewSec->SizeOfRawData = 0x1000;
	
	NewSec->VirtualAddress = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].VirtualAddress 
		+ pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].SizeOfRawData;
	
	NewSec->PointerToRawData = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].PointerToRawData 
		+ pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].SizeOfRawData;

	//修改大小長度
	*OldBufferSize = NewLength;

	//擷取導出表的位址
	RVA_TO_FOA(*pNewBuffer,pImageOptionalHeader->DataDirectory[0].VirtualAddress,&FOA);
	EXPORT_TABLE = (PIMAGE_EXPORT_DIRECTORY)((DWORD)*pNewBuffer + (DWORD)FOA);

	/*
	第二步:複制AddressOfFunctions
	長度:NumberOfFunctions*4		
	*/
	printf("AddressOfFunctions個數: %d 每個占4位元組\n", EXPORT_TABLE->NumberOfFunctions);
	RVA_TO_FOA(*pNewBuffer,EXPORT_TABLE->AddressOfFunctions,&FOA);
	memcpy((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData,
		(PVOID)((DWORD)*pNewBuffer + FOA),
		((DWORD)EXPORT_TABLE->NumberOfFunctions)*4);

	/*
	第三步:複制AddressOfNameOrdinals				
	長度:NumberOfNames*2			
	*/
	printf("AddressOfNameOrdinals個數: %d 每個占2位元組\n", EXPORT_TABLE->NumberOfNames);

	RVA_TO_FOA(*pNewBuffer, EXPORT_TABLE->AddressOfNameOrdinals,&FOA);
	memcpy((PVOID)((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4),
		(PVOID)((DWORD)*pNewBuffer + FOA),
		((DWORD)EXPORT_TABLE->NumberOfNames)*2);

	/*
	第四步:複制AddressOfNames
	長度:NumberOfNames*4		
	*/
	printf("AddressOfNames個數: %d 每個占4位元組\n", EXPORT_TABLE->NumberOfNames);
	RVA_TO_FOA(*pNewBuffer, EXPORT_TABLE->AddressOfNames,&FOA);

	memcpy((PVOID)((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 + ((DWORD)EXPORT_TABLE->NumberOfNames)*2),
		(PVOID)((DWORD)*pNewBuffer + FOA),
		(DWORD)EXPORT_TABLE->NumberOfNames*4);

	/*
	第五步:複制所有的函數名
	長度不确定,複制時直接修複AddressOfNames
	*/

	for(j=0;j<EXPORT_TABLE->NumberOfNames;j++){
		//獲得函數名稱表的RVA,将其轉換為FOA
		printf("%x\n", EXPORT_TABLE->AddressOfNames);
		RVA_TO_FOA(*pNewBuffer, EXPORT_TABLE->AddressOfNames,&FOA);

		// 每個函數的RVA轉換為FOA
		RVA_TO_FOA(*pNewBuffer, *(PDWORD)((DWORD)*pNewBuffer + (DWORD)FOA), &FOA);
		
		//擷取目前函數名稱的偏移位址,将目前的函數名稱的偏移位址 + pNewBuffer 得到對應的記憶體位址
		AddressFunctionName = (PDWORD)(*(PDWORD)((DWORD)*pNewBuffer + (DWORD)FOA + (DWORD)all_num));
		printf("%d\n",all_num);
		//printf("%x",AddressFunctionName);

		//通過strcpy來擷取目前位址儲存的函數名稱
		strcpy(FunName,&AddressFunctionName);
		//printf("%s",FunName);

		//得到目前函數名稱的長度
		FunNameLen = strlen(FunName) + 1; //最後結尾需要+1,原因\0 空位元組
		
		//拿到函數的長度和名稱之後需要進行複制
		memcpy((PVOID)((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData
			+ ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 
			+ ((DWORD)EXPORT_TABLE->NumberOfNames)*2 
			+ ((DWORD)EXPORT_TABLE->NumberOfNames)*4 
			+ (DWORD)all_num) //這裡到時候加循環來進行偏移複制
			
			,((PVOID)&AddressFunctionName)
			,FunNameLen);
		
		//接下來需要進行修複

		//過程:每次複制完 還需要修複下之前剛複制AddressOfNames中的對應的位址 讓它裡面的值 儲存為目前複制的函數位址
		
		//通過all_num來進行偏移 進而獲得目前的位址是指向第j個函數的位址
		pTempAddress = (PDWORD)((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 + ((DWORD)EXPORT_TABLE->NumberOfNames)*2 + (DWORD)all_num);

		//上面獲得的位址是VA 還需要減去pNewBuffer變成FOA 然後再轉換為RVA 最後存儲到新複制的函數名稱表對應的位址當中
		FOA_TO_RVA(*pNewBuffer
			,((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 + ((DWORD)EXPORT_TABLE->NumberOfNames)*2 + ((DWORD)EXPORT_TABLE->NumberOfNames)*4 + (DWORD)all_num) -(DWORD)*pNewBuffer
			,&RVA);

		printf("%d\n", ((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 + ((DWORD)EXPORT_TABLE->NumberOfNames)*2 + ((DWORD)EXPORT_TABLE->NumberOfNames)*4 + (DWORD)all_num) -(DWORD)*pNewBuffer);


		
		//修改目前pTempAddress指向的位址中的值,修改為之前每個函數名稱的的位址
		*pTempAddress = RVA;
		
		// all_num用來儲存複制函數名稱的時候一共用了多少個位元組
		all_num += FunNameLen;
	}

	/*
	第六步:複制IMAGE_EXPORT_DIRECTORY結構				
	*/
	memcpy((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 + ((DWORD)EXPORT_TABLE->NumberOfNames)*2 + ((DWORD)EXPORT_TABLE->NumberOfNames)*4 + (DWORD)all_num
		,EXPORT_TABLE
		,40
		);

	
	/*
	第七步:修複IMAGE_EXPORT_DIRECTORY結構中的

	AddressOfFunctions					
	AddressOfNameOrdinals										
	AddressOfNames					
	*/
	EXPORT_TABLE_NewBuffer = (PIMAGE_EXPORT_DIRECTORY)((DWORD)*pNewBuffer + (DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 
		+ ((DWORD)EXPORT_TABLE->NumberOfNames)*2 
		+ ((DWORD)EXPORT_TABLE->NumberOfNames)*4 
		+ (DWORD)all_num);
	
	//将新的緩沖區中的三個表中存儲的位址都進行修改為上面移動好的位置
	FOA_TO_RVA(*pNewBuffer,(DWORD)NewSec->PointerToRawData,&RVA);
	EXPORT_TABLE_NewBuffer->AddressOfFunctions = RVA;
	FOA_TO_RVA(*pNewBuffer,(DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4,&RVA);
	EXPORT_TABLE_NewBuffer->AddressOfNameOrdinals = RVA;
	FOA_TO_RVA(*pNewBuffer,(DWORD)NewSec->PointerToRawData + ((DWORD)EXPORT_TABLE->NumberOfFunctions)*4 + ((DWORD)EXPORT_TABLE->NumberOfNames)*2,&RVA);
	EXPORT_TABLE_NewBuffer->AddressOfNames = RVA;
	
	/*
	第八步:修複目錄項中的值,指向新的IMAGE_EXPORT_DIRECTORY						
	*/
	
	FOA_TO_RVA(*pNewBuffer,(DWORD)EXPORT_TABLE_NewBuffer - (DWORD)*pNewBuffer,&RVA);
	pImageOptionalHeader->DataDirectory[0].VirtualAddress = RVA;
}