PE-SourceCode-C

ʕ •ᴥ•ʔ ɔ:

常用的数据类型的定义包含在头文件windows.h实际上是winnt.h

0 HeaderFile.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "stdafx.h"                                                                                        
#include<windows.h>
#include <stdlib.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

#define MessageBoxA_Addr 0x7631FD1E
#define ShellCodeLength 0x12

BYTE ShellCode[] = {
0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE9, 0x00, 0x00, 0x00, 0x00
};
//typedef char * LPSTR
LPSTR FILEPATH = "C:/symsrv.dll"; //Using "/" OR "\\"
LPSTR FilePath_Out = "C:/symsrv_addSec.dll";

1 ReadPEFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*****************************************************************************
将文件读入缓冲区pFileBuffer
参数:文件路径
返回值:指向读入的文件缓冲区
*****************************************************************************/
LPVOID ReadPEFile(LPSTR lpszFile)
{
FILE *pFile = NULL;
DWORD fileSize = 0; //typedef unsigned long DWORD
LPVOID pFileBuffer = NULL; //typedef void* LPVOID

//打开文件
pFile = fopen(lpszFile, "rb"); //返回一个指向FILE类型的指针/NULL
if(!pFile)
{
printf(" 无法打开 EXE 文件! ");
return NULL;
}
//读取文件大小
fseek(pFile, 0, SEEK_END);//int fseek(FILE *fp,long offset,int fromwhere);
fileSize = ftell(pFile);//将fp的文件位置指针从fromwhere开始移动offset个字节指示下一个要读取的数据的位置
fseek(pFile, 0, SEEK_SET);//SEEK_SET或0,代表文件开始处;SEEK_CUR或1,代表文件当前位置;SEEK_END或2,代表文件结尾处。
//分配缓冲区
printf("ReadPEFile文件大小:0x%x\n",fileSize);
pFileBuffer = malloc(fileSize);//memset(pFileBuffer,0,fileSize),将filesize大小的空间置为0
// 需使用头文件<memory.h>或<string.h>
if(!pFileBuffer)
{
printf(" 分配空间失败! ");
fclose(pFile);
return NULL;
}
//将文件数据读取到缓冲区
size_t n = fread(pFileBuffer, fileSize, 1, pFile);//将文件pFile读到内存 pFileBuffer,共1个块,每个块的大小filesize
if(!n) //返回实际读到的块数
{ //<stddef.h>-----#typedef unsigned int size_t
printf(" 读取数据失败! ");
free(pFileBuffer);
fclose(pFile);
return NULL;
}
//关闭文件
fclose(pFile);
return pFileBuffer;
}

2 ReadPESize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*****************************************************************************
读取文件大小
参数:文件路径
*****************************************************************************/
DWORD ReadPESize(LPSTR lpszFile)
{
FILE *pFile = NULL;
DWORD fileSize = 0; //typedef unsigned long DWORD
//打开文件
pFile = fopen(lpszFile, "rb"); //返回一个指向FILE类型的指针/NULL
if(!pFile)
{
printf(" 无法打开 EXE 文件! ");
return NULL;
}
//读取文件大小
fseek(pFile, 0, SEEK_END); //int fseek(FILE *fp,long offset,int fromwhere);
fileSize = ftell(pFile); //将fp的文件位置指针从fromwhere开始移动offset个字节指示下一个要读取的数据的位置
fseek(pFile, 0, SEEK_SET); //SEEK_SET或0,代表文件开始处;SEEK_CUR或1,代表文件当前位置;SEEK_END或2,代表文件结尾处。
//关闭文件
fclose(pFile);
return fileSize;
}

3 PrintNTHeaders

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*****************************************************************************
打印PE文件头部信息
*****************************************************************************/
VOID PrintNTHeaders()
{
LPVOID pFileBuffer = NULL;
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;
PDWORD FILESIZE_1 = NULL;

pFileBuffer = ReadPEFile(FILEPATH);
if(!pFileBuffer)
{
printf("文件读取失败\n");
return ;
}

//判断是否是有效的MZ标志
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志\n");
free(pFileBuffer);
return ;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
//打印DOS头
printf("********************DOS头********************\n");
printf("MZ标志:%x\n",pDosHeader->e_magic);
printf("PE偏移:%x\n",pDosHeader->e_lfanew);
//判断是否是有效的PE标志
if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
free(pFileBuffer);
return ;
}
//(DWORD)pFileBuffer---将pFileBuffer指向的地址转化为DWORD型
//两种修改方式:可以将指针的地址转换成BYTE *型(加数字的时候加的大小为去掉一个*后的类型大小)
//或者转换成数字DWORD
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pFileBuffer+pDosHeader->e_lfanew);
//打印NT头
printf("********************NT头********************\n");
printf("NT签名:%x\n",pNTHeader->Signature);
pPEHeader = (PIMAGE_FILE_HEADER)(((BYTE *)pNTHeader) + 4);
printf("********************PE头********************\n");
printf("PE-Machine:%x\n",pPEHeader->Machine);
printf("节的数量:%x\n",pPEHeader->NumberOfSections);
printf("SizeOfOptionalHeader:%x\n",pPEHeader->SizeOfOptionalHeader);
//可选PE头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
printf("********************OPTIOIN_PE头********************\n");
printf("OPTION_PE-Magic:%x\n",pOptionHeader->Magic);

pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
printf("********************节表********************\n");
for(int i=0;i<pPEHeader->NumberOfSections;i++)
{
printf("Name:%s\n",pSectionHeader->Name);
printf("Misc:%x\n",pSectionHeader->Misc);
printf("VirtualAddress:%x\n",pSectionHeader->VirtualAddress);
printf("SizeOfRawData:%x\n",pSectionHeader->SizeOfRawData);
printf("PointerToRawData:%x\n",pSectionHeader->PointerToRawData);
printf("Characteristics:%x\n",pSectionHeader->Characteristics);
printf("\n");
pSectionHeader+=0x1;//这里应该加什么?
}

//printf("%x\n",pSectionHeader);
//printf("%x\n",pSectionHeader+1);
//释放内存
free(pFileBuffer);
}

4 CopyFileBufferToImageBuffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**************************************************************************					将文件从FileBuffer复制到ImageBuffer							
参数说明:
pFileBuffer FileBuffer指针
pImageBuffer ImageBuffer指针
返回值说明:
读取失败返回0 否则返回复制的大小
IN OUT仅做标志用,原型:#define IN,#define IN
**************************************************************************/
DWORD CopyFileBufferToImageBuffer(
IN LPVOID pFileBuffer,
OUT LPVOID *pImageBuffer
){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
LPVOID pTempFileBuffer = NULL;

if(pFileBuffer ==NULL){
printf("pFileBuffer缓冲区指针出错...\n");
return ERROR;
}

//判断是否含有有效MZ和PE标志
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*((PDWORD)((BYTE *)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}

//找到所有PE文件结构的头地址
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pFileBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);

//根据SizeOfImage申请空间哦
pTempFileBuffer = malloc(pOptionHeader->SizeOfImage);
if(!pTempFileBuffer){
printf("pTempFileBuffer空间申请失败...");
return ERROR;
}
memset(pTempFileBuffer, 0, pOptionHeader->SizeOfImage);
memcpy(pTempFileBuffer, pDosHeader, pOptionHeader->SizeOfHeaders);

for(DWORD i = 0; i < pFileHeader->NumberOfSections; i++){
memcpy((PVOID)((BYTE *)pTempFileBuffer + (pSectionHeader + i)->VirtualAddress), (PVOID)((BYTE *)pDosHeader + (pSectionHeader + i)->PointerToRawData), (pSectionHeader + i)->SizeOfRawData);
}

*pImageBuffer = pTempFileBuffer;
pTempFileBuffer = NULL;

return pOptionHeader->SizeOfImage;
}

5 CopyImageBufferToNewFileBuffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**************************************************************************					
将ImageBuffer中的数据复制到新的缓冲区
参数说明:
pImageBuffer ImageBuffer指针
pNewBuffer NewBuffer指针
返回值说明:
读取失败返回0 否则返回复制的大小
**************************************************************************/
DWORD CopyImageBufferToNewFileBuffer(
IN LPVOID pImageBuffer,
OUT LPVOID *pNewFileBuffer
){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;

if(pImageBuffer ==NULL){
printf("pImageBuffer缓冲区指针出错...\n");
return ERROR;
}

//判断是否含有有效MZ和PE标志
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((BYTE *)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}

//找到所有PE文件结构的头地址
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pImageBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);
for(DWORD i = 0; i < pFileHeader->NumberOfSections; i++){
cout << "pSectionHeader->Name = " << (pSectionHeader + i)->Name << endl;
memcpy((PVOID)((BYTE *)pDosHeader + (pSectionHeader + i)->PointerToRawData), (PVOID)((BYTE *)pImageBuffer + (pSectionHeader + i)->VirtualAddress), (pSectionHeader + i)->SizeOfRawData);
}
*pNewFileBuffer = pImageBuffer;
pImageBuffer = NULL;
return pOptionHeader->SizeOfImage;
}

6 NewFileBufferToFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**************************************************************************
将内存中的数据复制到文件
参数说明:
pNewFileBuffer 内存中数据的指针
size 要复制的大小
lpszFile 要存储的文件路径
返回值说明:
读取失败返回0 否则返回复制的大小
**************************************************************************/
BOOL NewFileBufferToFile(
IN LPVOID pNewFileBuffer,
size_t size,
OUT LPSTR lpszFile
){
if(pNewFileBuffer == NULL){
printf("pNewFileBuffer缓冲区出差...\n");
return ERROR;
}
FILE *pFile = NULL;
size_t fileSize = size;
pFile = fopen(lpszFile, "wb");
if(!pFile){
printf("fopen保存EXE文件失败...\n");
return ERROR;
}
size_t n = fwrite(pNewFileBuffer, fileSize, 1, pFile);
if(!n){
printf("fwrite数据写入失败...\n");
fclose(pFile);
return ERROR;
}
fclose(pFile);
printf("存盘成功\n");
return TRUE;
}

7 RVAToFOA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**************************************************************************	
编写一个函数,能够将VA的值转换成FOA
先定位该RVA在哪一个节
VA = FOA - PointerToRawData + VirtualAddress + ImageBase
RVA = VA - ImageBase
FOA = VA - ImageBase - VirtualAddress + PointerToRawData
参数:需要转换的RVA,该文件的FileBuffer
**************************************************************************/
DWORD RVAToFOA(DWORD RVA,PVOID pImageBuffer)
{
// 初始化PE头部结构体
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
DWORD VA = 0;

if(pImageBuffer ==NULL){
printf("pImageBuffer缓冲区指针出错...\n");
return ERROR;
}

//判断是否含有有效MZ和PE标志
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((BYTE *)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}
//找到所有PE文件结构的头地址
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pImageBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);

VA = RVA + pOptionHeader->ImageBase;
for (int i = 0; i<=pFileHeader->NumberOfSections; i++)
{
if (RVA >= (pSectionHeader->VirtualAddress) && RVA < (pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize))
{
return (RVA - pSectionHeader->VirtualAddress) + pSectionHeader->PointerToRawData;
}
pSectionHeader++;
}

}

8 FOAToRVA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/***************************************************************************	
编写一个函数,能够将FOA的值转换成RVA
先定位该FOA在哪一个节
RVA = FOA - PointerToRawData + VirtualAddress
VA = FOA - PointerToRawData + VirtualAddress + ImageBase
RVA = VA - ImageBase
FOA = VA - ImageBase - VirtualAddress + PointerToRawData
参数:需要转换的FOA,该文件的FileBuffer
***************************************************************************/
DWORD FOAToRVA(DWORD FOA,PVOID pImageBuffer)
{
// 初始化PE头部结构体
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;

if(pImageBuffer ==NULL){
printf("pImageBuffer缓冲区指针出错...\n");
return ERROR;
}

//判断是否含有有效MZ和PE标志
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((BYTE *)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}
//找到所有PE文件结构的头地址
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pImageBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);

for (int i = 0; i<=pFileHeader->NumberOfSections; i++)
{
if (FOA >= (pSectionHeader->PointerToRawData) && FOA < (pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData))
{
return FOA - pSectionHeader->PointerToRawData + pSectionHeader->VirtualAddress;
}
pSectionHeader++;
}

}

9 AddCodeToTextSec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**************************************************************************	
AddCodeToTextSec:在代码(.text)空白区添加代码(修改PE文件),然后实现shellcode弹窗MessageBox
程序先执行call MessageBox(E8 0x75357870),执行完之后jmp OEP(E9 OEP)
call(E8)跳转的地址为(DWORD)((DWORD)codeBegin + 0xD)
但是pImageBuffer是动态生成的,下一次调用函数重新申请时值会改变,需要使用pOptionHeader->ImageBase才准确
***************************************************************************/
VOID AddCodeToTextSec(LPVOID pFileBuffer,LPVOID pImageBuffer){
LPVOID pNewFileBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
DWORD size = 0;

if(pFileBuffer == NULL){
printf("pFileBuffer --> 文件缓冲区失败");
return ;
}
if(pImageBuffer == NULL){
printf("pImageBuffer --> 内存缓冲区失败");
free(pFileBuffer);
return ;
}

pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pDosHeader + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);

if(pSectionHeader->SizeOfRawData - pSectionHeader->Misc.VirtualSize < ShellCodeLength){
printf("代码区空闲空间不足...");
free(pFileBuffer);
free(pImageBuffer);
return ;
}

//BYTE* CODEBEGIN = (BYTE*)((DWORD)pDosHeader + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize)
BYTE *codeBegin = (BYTE *)((DWORD)pImageBuffer + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize); // 计算放到哪里
memcpy(codeBegin, ShellCode, ShellCodeLength);
//MessageBoxA_Addr = E8指令的下一条地址 + X
//由于messageBoxAddr是虚拟内存中的值,故需要将callAddr转换成相应的可执行的虚拟地址
DWORD test = (DWORD)pImageBuffer;
DWORD Codee = (DWORD)codeBegin;
printf("pImageBuffer:%x\n",test);
printf("codeBegin:%x\n",Codee);
DWORD callAddr_X = MessageBoxA_Addr - ((DWORD)codeBegin + 0xD - (DWORD)pImageBuffer + pOptionHeader->ImageBase); //从ImageBuffer 到 ImageBase 的过程
*(PDWORD)(codeBegin + 0x09) = callAddr_X;
cout << hex << "callAddr_X = " << callAddr_X << endl;
DWORD jmpAddr_Y = (pOptionHeader->ImageBase + pOptionHeader->AddressOfEntryPoint) - ((DWORD)codeBegin + ShellCodeLength - (DWORD)pImageBuffer + pOptionHeader->ImageBase);
//DWORD jmpAddr = pOptionHeader->AddressOfEntryPoint - ((DWORD)codeBegin - (DWORD)pImageBuffer + shellCodeLength);
cout << hex << "jmpAddr_Y = " << jmpAddr_Y << endl;
*(PDWORD)(codeBegin + 0x0E) = jmpAddr_Y;
//OEP是一个偏移值
pOptionHeader->AddressOfEntryPoint = (DWORD)codeBegin - (DWORD)pImageBuffer ;

size = CopyImageBufferToNewFileBuffer(pImageBuffer, &pNewFileBuffer);
printf("Sizeofimage:%x\n",size);
NewFileBufferToFile(pNewFileBuffer, size, FilePath_Out);
return ;
}

A Is_64BitOS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*****************************************************************************
判断PE文件是否是64位,IA64(Intel)/x86_64(AMD)/ALPHA64
该出现PE时没出现,就可能是32位,但是检测到machine的数值,就能确定。
*****************************************************************************/
#ifndef IMAGE_FILE_MACHINE_AMD64
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#endif
BOOL Is_64BitOS( IN LPSTR lpszFile)
{
LPVOID pTempBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;

pTempBuffer = ReadPEFile(lpszFile);
pDosHeader = (PIMAGE_DOS_HEADER)pTempBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pTempBuffer + pDosHeader->e_lfanew);
cout << hex << "机器码为:" << pNTHeader->FileHeader.Machine << endl;
if(pNTHeader->Signature != IMAGE_NT_SIGNATURE){
cout << "PE文件版本可能为64位" << endl;
return FALSE;
}

if (pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 || pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ||
pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA64){
cout << "PE文件版本为64位" << endl;
return TRUE;
}else{
cout << "PE文件版本为32位" << endl;
return FALSE;
}
}

B ReturnAllExport

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*****************************************************************************	
输出导出表完整信息
*****************************************************************************/
VOID ReturnAllExport( IN LPVOID pFileBuffer)
{
BOOL Is_64Bit = Is_64BitOS(FILEPATH);
if(Is_64Bit){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS64 pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER64 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS64)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER64)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
/*
PIMAGE_OPTIONAL_HEADER64 pOptionHeader_1 = &pNTHeader->OptionalHeader;
printf("pOptionHeader:%x\n",(DWORD)pOptionHeader);
printf("pOptionHeader_1:%x\n",(DWORD)pOptionHeader_1);
*/
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
if(pDataDirectory[0].VirtualAddress == 0)
{
cout << "不存在导出表..." << endl;
return ;
}
DWORD ExportVirtualAddrRVA = pDataDirectory[0].VirtualAddress;
//ExportVirtualAddrRVA = 0x1060;
DWORD ExportVirtualAddrFOA = RVAToFOA(ExportVirtualAddrRVA, pFileBuffer);
cout << hex << "ExportVirtualAddrFOA = " << ExportVirtualAddrFOA << endl;

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ExportVirtualAddrFOA + (DWORD)pFileBuffer);
cout << hex << "-----------IMAGE_EXPORT_DIRECTORY---------" << endl;
cout << hex << "pDataDirectory[0].VirtualAddress = " << ExportVirtualAddrRVA << endl;
cout << hex << "pDataDirectory[0].Size = " << pDataDirectory[0].Size << endl;
cout << hex << "Characteristics = " << pExportDirectory->Characteristics << endl;
cout << hex << "TimeDateStamp = " << pExportDirectory->TimeDateStamp << endl;
cout << hex << "MajorVersion = " << pExportDirectory->MajorVersion << endl;
cout << hex << "MinorVersion = " << pExportDirectory->MinorVersion << endl;
cout << hex << "Name = " << pExportDirectory->Name << endl;
//RVAToFOA(pExportDirectory->Name, pFileBuffer) 将指向Dll文件名的RVAToFOA
//FOA + (DWORD)pFileBuffer即为Dll文件名的字符串
printf( "Dll文件名 = %s\n", RVAToFOA(pExportDirectory->Name, pFileBuffer) + (DWORD)pFileBuffer);
cout << hex << "Base = " << pExportDirectory->Base << endl;
cout << hex << "NumberOfFunctions = " << pExportDirectory->NumberOfFunctions << endl;
cout << hex << "NumberOfNames = " << pExportDirectory->NumberOfNames << endl;
cout << hex << "AddressOfFunctions = " << pExportDirectory->AddressOfFunctions << endl;
cout << hex << "AddressOfNames = " << pExportDirectory->AddressOfNames << endl;
cout << hex << "AddressOfNameOrdinals = " << pExportDirectory->AddressOfNameOrdinals << endl;
cout << hex << "-FunctionsDetail-------------------------------------------------" << endl;
cout << hex << "-\t\t导出函数序号\t\tRVA\t\tFunctionName" << endl;

DWORD *AddrFunctions = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfFunctions, pFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNames, pFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNameOrdinals, pFileBuffer));
DWORD i, j;
//导出函数的序号 = AddressOfNameOrdinals中的值 + Base
//Base = 导出函数的序号最小值
//AddressOfNameOrdinals中的值 = AddressOfFunctions下标
//i为地址表下标,j为序号表的下标(AddrOrdinals[j]值为地址表下标)
for(i = 0; i < pExportDirectory->NumberOfFunctions; i++){
//先检索函数地址表,因为所有的函数地址都在里面,包括用序号导出的和用函数名导出的。然后拿着某个函数的下标再到AddrOrdinals去检索,若匹配不到,说明该函数不
//是以函数名导出的。
//地址表中可能存在无用的值(就是为0的值)
if(AddrFunctions[i] == 0){
continue;
}
for(j = 0; j < pExportDirectory->NumberOfNames; j++){
//判断是否在序号表中
//printf("函数名文件偏移:%x\n",RVAToFOA(AddrName[j], pFileBuffer));该地址为字符串起始地址
if(AddrOrdinals[j] == i){
printf("-\t\t%04x\t\t%08x\t%s\n", pExportDirectory->Base + i, AddrFunctions[i], RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer);
break;
}
}

if(j != pExportDirectory->NumberOfNames){
continue;
}
else{
printf("-\t\t%04x\t\t%08x\t%s\n", pExportDirectory->Base + i, AddrFunctions[i],"------NONAME函数------");
}

}
}else{

PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS32)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
//pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
//pOptionHeader = &pNTHeader->OptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
if(pDataDirectory[0].VirtualAddress == 0){
cout << "不存在导出表..." << endl;
return ;
}
DWORD ExportVirtualAddrRVA = pDataDirectory[0].VirtualAddress;
//ExportVirtualAddrRVA = 0x1060;
DWORD ExportVirtualAddrFOA = RVAToFOA(ExportVirtualAddrRVA, pFileBuffer);
cout << hex << "ExportVirtualAddrFOA = " << ExportVirtualAddrFOA << endl;

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ExportVirtualAddrFOA + (DWORD)pFileBuffer);
cout << hex << "-----------IMAGE_EXPORT_DIRECTORY---------" << endl;
cout << hex << "pDataDirectory[0].VirtualAddress = " << ExportVirtualAddrRVA << endl;
cout << hex << "pDataDirectory[0].Size = " << pDataDirectory[0].Size << endl;
cout << hex << "Characteristics = " << pExportDirectory->Characteristics << endl;
cout << hex << "TimeDateStamp = " << pExportDirectory->TimeDateStamp << endl;
cout << hex << "MajorVersion = " << pExportDirectory->MajorVersion << endl;
cout << hex << "MinorVersion = " << pExportDirectory->MinorVersion << endl;
cout << hex << "Name = " << pExportDirectory->Name << endl;
//RVAToFOA(pExportDirectory->Name, pFileBuffer) 将指向Dll文件名的RVAToFOA
//FOA + (DWORD)pFileBuffer即为Dll文件名的字符串
//printf("%s",FOA + (DWORD)pFileBuffer) 等给于PDWORD TEST = (PDWORD)(FOA+ (DWORD)pFileBuffer);printf("%s",TEST)
/*
PDWORD TEST = (PDWORD)((RVAToFOA(pExportDirectory->Name, pFileBuffer)+ (DWORD)pFileBuffer));
printf("%s\n",TEST) ;
*/
printf( "Dll文件名 = %s\n", RVAToFOA(pExportDirectory->Name, pFileBuffer) + (DWORD)pFileBuffer);
cout << hex << "Base = " << pExportDirectory->Base << endl;
cout << hex << "NumberOfFunctions = " << pExportDirectory->NumberOfFunctions << endl;
cout << hex << "NumberOfNames = " << pExportDirectory->NumberOfNames << endl;
cout << hex << "AddressOfFunctions = " << pExportDirectory->AddressOfFunctions << endl;
cout << hex << "AddressOfNames = " << pExportDirectory->AddressOfNames << endl;
cout << hex << "AddressOfNameOrdinals = " << pExportDirectory->AddressOfNameOrdinals << endl;
cout << hex << "-FunctionsDetail-------------------------------------------------" << endl;
cout << hex << "-\t\t导出函数序号\t\tRVA\t\tFunctionName" << endl;

DWORD *AddrFunctions = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfFunctions, pFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNames, pFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNameOrdinals, pFileBuffer));
DWORD i, j;
//导出函数的序号 = AddressOfNameOrdinals中的值 + Base
//Base = 导出函数的序号最小值
//AddressOfNameOrdinals中的值 = AddressOfFunctions下标
//i为地址表下标,j为序号表的下标(AddrOrdinals[j]值为地址表下标)
for(i = 0; i < pExportDirectory->NumberOfFunctions; i++){
//地址表中可能存在无用的值(就是为0的值)
if(AddrFunctions[i] == 0){
continue;
}
for(j = 0; j < pExportDirectory->NumberOfNames; j++){
//判断是否在序号表中
//printf("函数名文件偏移:%x\n",RVAToFOA(AddrName[j], pFileBuffer));
if(AddrOrdinals[j] == i){
printf("-\t\t%04x\t\t%08x\t%s\n", pExportDirectory->Base + i, AddrFunctions[i], RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer);
break;
}
}

if(j != pExportDirectory->NumberOfNames){
continue;
}
else{
printf("-\t\t%04x\t\t%08x\t%s\n", pExportDirectory->Base + i, AddrFunctions[i],"------NONAME函数------");
}

}
}
}

C GetFunctionAddrByOrdinals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*****************************************************************************
根据导出函数序号,得到导出函数RVA
参数:该文件的FileBuffer,导出函数的序号
*****************************************************************************/
#define test 0
PDWORD GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD Ordinal)
{
BOOL Is_64Bit = Is_64BitOS(FILEPATH);
if(Is_64Bit)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS64 pNTHeader = NULL;
PIMAGE_OPTIONAL_HEADER64 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS64)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER64)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
//pOptionHeader = &pNTHeader->OptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
if(pDataDirectory[0].VirtualAddress == 0){
cout << "不存在导出表..." << endl;
return NULL;
}
DWORD ExportVirtualAddrRVA = pDataDirectory[0].VirtualAddress;
//ExportVirtualAddrRVA = 0x1060;
DWORD ExportVirtualAddrFOA = RVAToFOA(ExportVirtualAddrRVA, pFileBuffer);
cout << hex << "ExportVirtualAddrFOA = " << ExportVirtualAddrFOA << endl;

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ExportVirtualAddrFOA + (DWORD)pFileBuffer);
cout << hex << "-----------IMAGE_EXPORT_DIRECTORY---------" << endl;
cout << hex << "pDataDirectory[0].VirtualAddress = " << ExportVirtualAddrRVA << endl;
cout << hex << "pDataDirectory[0].Size = " << pDataDirectory[0].Size << endl;
cout << hex << "Characteristics = " << pExportDirectory->Characteristics << endl;
cout << hex << "TimeDateStamp = " << pExportDirectory->TimeDateStamp << endl;
cout << hex << "MajorVersion = " << pExportDirectory->MajorVersion << endl;
cout << hex << "MinorVersion = " << pExportDirectory->MinorVersion << endl;
cout << hex << "Name = " << pExportDirectory->Name << endl;
//RVAToFOA(pExportDirectory->Name, pFileBuffer) 将指向Dll文件名的RVAToFOA
//FOA + (DWORD)pFileBuffer即为Dll文件名的字符串
printf( "Dll文件名 = %s\n", RVAToFOA(pExportDirectory->Name, pFileBuffer) + (DWORD)pFileBuffer);
cout << hex << "Base = " << pExportDirectory->Base << endl;
cout << hex << "NumberOfFunctions = " << pExportDirectory->NumberOfFunctions << endl;
cout << hex << "NumberOfNames = " << pExportDirectory->NumberOfNames << endl;
cout << hex << "AddressOfFunctions = " << pExportDirectory->AddressOfFunctions << endl;
cout << hex << "AddressOfNames = " << pExportDirectory->AddressOfNames << endl;
cout << hex << "AddressOfNameOrdinals = " << pExportDirectory->AddressOfNameOrdinals << endl;
cout << hex << "-FunctionsDetail-------------------------------------------------" << endl;
cout << hex << "-\t\t导出函数序号\t\tRVA\t\tFunctionName" << endl;

DWORD *AddrFunctions = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfFunctions, pFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNames, pFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNameOrdinals, pFileBuffer));
DWORD i = Ordinal - pExportDirectory->Base;
DWORD j = 0;
for(j = 0; j < pExportDirectory->NumberOfNames; j++)
{
if(AddrOrdinals[j] == i)
{
printf("导出序号 %x 对应的导出函数名为 %s ,该函数RVA为:%x\n",Ordinal,RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer,AddrFunctions[i]);
}
}
return (PDWORD)AddrFunctions[i];
}//end if(Is_64Bit){
else {
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNTHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS32)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
//pOptionHeader = &pNTHeader->OptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
if(pDataDirectory[0].VirtualAddress == 0){
cout << "不存在导出表..." << endl;
return NULL;
}
DWORD ExportVirtualAddrRVA = pDataDirectory[0].VirtualAddress;
//ExportVirtualAddrRVA = 0x1060;
DWORD ExportVirtualAddrFOA = RVAToFOA(ExportVirtualAddrRVA, pFileBuffer);
cout << hex << "ExportVirtualAddrFOA = " << ExportVirtualAddrFOA << endl;

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ExportVirtualAddrFOA + (DWORD)pFileBuffer);
cout << hex << "-----------IMAGE_EXPORT_DIRECTORY---------" << endl;
cout << hex << "pDataDirectory[0].VirtualAddress = " << ExportVirtualAddrRVA << endl;
cout << hex << "pDataDirectory[0].Size = " << pDataDirectory[0].Size << endl;
cout << hex << "Characteristics = " << pExportDirectory->Characteristics << endl;
cout << hex << "TimeDateStamp = " << pExportDirectory->TimeDateStamp << endl;
cout << hex << "MajorVersion = " << pExportDirectory->MajorVersion << endl;
cout << hex << "MinorVersion = " << pExportDirectory->MinorVersion << endl;
cout << hex << "Name = " << pExportDirectory->Name << endl;
//RVAToFOA(pExportDirectory->Name, pFileBuffer) 将指向Dll文件名的RVAToFOA
//FOA + (DWORD)pFileBuffer即为Dll文件名的字符串
printf( "Dll文件名 = %s\n", RVAToFOA(pExportDirectory->Name, pFileBuffer) + (DWORD)pFileBuffer);
cout << hex << "Base = " << pExportDirectory->Base << endl;
cout << hex << "NumberOfFunctions = " << pExportDirectory->NumberOfFunctions << endl;
cout << hex << "NumberOfNames = " << pExportDirectory->NumberOfNames << endl;
cout << hex << "AddressOfFunctions = " << pExportDirectory->AddressOfFunctions << endl;
cout << hex << "AddressOfNames = " << pExportDirectory->AddressOfNames << endl;
cout << hex << "AddressOfNameOrdinals = " << pExportDirectory->AddressOfNameOrdinals << endl;
cout << hex << "-FunctionsDetail-------------------------------------------------" << endl;
cout << hex << "-\t\t导出函数序号\t\tRVA\t\tFunctionName" << endl;

DWORD *AddrFunctions = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfFunctions, pFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNames, pFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNameOrdinals, pFileBuffer));
DWORD i = Ordinal - pExportDirectory->Base;
DWORD j = 0;
for(j = 0; j < pExportDirectory->NumberOfNames; j++)
{
if(AddrOrdinals[j] == i)
{
printf("导出序号 %x 对应的导出函数名为 %s ,该函数RVA为:%x\n",Ordinal,RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer,AddrFunctions[i]);
}
}
return (PDWORD)AddrFunctions[i];
}//end else {

}//end GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD Ordinal)

D GetFunctionAddrByName

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*****************************************************************************
根据导出函数名称,得到导出函数RVA
参数:该文件的FileBuffer,导出函数的名称
*****************************************************************************/
PDWORD GetFunctionAddrByName(PVOID pFileBuffer, LPSTR Fun_Name)
{
BOOL Is_64Bit = Is_64BitOS(FILEPATH);
if(Is_64Bit)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS64 pNTHeader = NULL;
PIMAGE_OPTIONAL_HEADER64 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS64)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER64)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
//pOptionHeader = &pNTHeader->OptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
if(pDataDirectory[0].VirtualAddress == 0){
cout << "不存在导出表..." << endl;
return NULL;
}
DWORD ExportVirtualAddrRVA = pDataDirectory[0].VirtualAddress;
//ExportVirtualAddrRVA = 0x1060;
DWORD ExportVirtualAddrFOA = RVAToFOA(ExportVirtualAddrRVA, pFileBuffer);
cout << hex << "ExportVirtualAddrFOA = " << ExportVirtualAddrFOA << endl;

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ExportVirtualAddrFOA + (DWORD)pFileBuffer);
cout << hex << "-----------IMAGE_EXPORT_DIRECTORY---------" << endl;
cout << hex << "pDataDirectory[0].VirtualAddress = " << ExportVirtualAddrRVA << endl;
cout << hex << "pDataDirectory[0].Size = " << pDataDirectory[0].Size << endl;
cout << hex << "Characteristics = " << pExportDirectory->Characteristics << endl;
cout << hex << "TimeDateStamp = " << pExportDirectory->TimeDateStamp << endl;
cout << hex << "MajorVersion = " << pExportDirectory->MajorVersion << endl;
cout << hex << "MinorVersion = " << pExportDirectory->MinorVersion << endl;
cout << hex << "Name = " << pExportDirectory->Name << endl;
//RVAToFOA(pExportDirectory->Name, pFileBuffer) 将指向Dll文件名的RVAToFOA
//FOA + (DWORD)pFileBuffer即为Dll文件名的字符串
printf( "Dll文件名 = %s\n", RVAToFOA(pExportDirectory->Name, pFileBuffer) + (DWORD)pFileBuffer);
cout << hex << "Base = " << pExportDirectory->Base << endl;
cout << hex << "NumberOfFunctions = " << pExportDirectory->NumberOfFunctions << endl;
cout << hex << "NumberOfNames = " << pExportDirectory->NumberOfNames << endl;
cout << hex << "AddressOfFunctions = " << pExportDirectory->AddressOfFunctions << endl;
cout << hex << "AddressOfNames = " << pExportDirectory->AddressOfNames << endl;
cout << hex << "AddressOfNameOrdinals = " << pExportDirectory->AddressOfNameOrdinals << endl;
cout << hex << "-FunctionsDetail-------------------------------------------------" << endl;
cout << hex << "-\t\t导出函数序号\t\tRVA\t\tFunctionName" << endl;

DWORD *AddrFunctions = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfFunctions, pFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNames, pFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNameOrdinals, pFileBuffer));
DWORD i = 0;
DWORD j = 0;
/*
DWORD a = (DWORD)Fun_Name;
LPSTR* c = &Fun_Name;
DWORD b = RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer;
printf("Fun_Name地址:%x\n",Fun_Name);//输出Fun_Name中的值,即字符串的地址
printf("Fun_Name地址:%p\n",Fun_Name);//输出Fun_Name中的值,而非Fun_Name地址,即字符串的地址
printf("Fun_Name地址:%p\n",c);
printf("Fun_Name地址:%x\n",b);
printf("Fun_Name地址:%s\n",b);//将b的整数作为地址去找该地址指向的内容
printf("Fun_Name地址:%s\n",Fun_Name);//输出同上一行
*/
for(j = 0; j < pExportDirectory->NumberOfNames; j++)
{
if(!strcmp((LPSTR)RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer,Fun_Name))
{
i = AddrOrdinals[j];
printf("导出序号0x%x 对应的导出函数名为 %s ,该函数RVA为:%x\n",AddrOrdinals[j] + pExportDirectory->Base,RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer,AddrFunctions[i]);
return (PDWORD)AddrFunctions[i];
}
}
printf("不存在该导出函数\n");
//return (PDWORD)AddrFunctions[i];
}//end if(Is_64Bit){
else
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNTHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS32)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
//pOptionHeader = &pNTHeader->OptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
if(pDataDirectory[0].VirtualAddress == 0){
cout << "不存在导出表..." << endl;
return NULL;
}
DWORD ExportVirtualAddrRVA = pDataDirectory[0].VirtualAddress;
//ExportVirtualAddrRVA = 0x1060;
DWORD ExportVirtualAddrFOA = RVAToFOA(ExportVirtualAddrRVA, pFileBuffer);
cout << hex << "ExportVirtualAddrFOA = " << ExportVirtualAddrFOA << endl;

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ExportVirtualAddrFOA + (DWORD)pFileBuffer);
cout << hex << "-----------IMAGE_EXPORT_DIRECTORY---------" << endl;
cout << hex << "pDataDirectory[0].VirtualAddress = " << ExportVirtualAddrRVA << endl;
cout << hex << "pDataDirectory[0].Size = " << pDataDirectory[0].Size << endl;
cout << hex << "Characteristics = " << pExportDirectory->Characteristics << endl;
cout << hex << "TimeDateStamp = " << pExportDirectory->TimeDateStamp << endl;
cout << hex << "MajorVersion = " << pExportDirectory->MajorVersion << endl;
cout << hex << "MinorVersion = " << pExportDirectory->MinorVersion << endl;
cout << hex << "Name = " << pExportDirectory->Name << endl;
//RVAToFOA(pExportDirectory->Name, pFileBuffer) 将指向Dll文件名的RVAToFOA
//FOA + (DWORD)pFileBuffer即为Dll文件名的字符串
printf( "Dll文件名 = %s\n", RVAToFOA(pExportDirectory->Name, pFileBuffer) + (DWORD)pFileBuffer);
cout << hex << "Base = " << pExportDirectory->Base << endl;
cout << hex << "NumberOfFunctions = " << pExportDirectory->NumberOfFunctions << endl;
cout << hex << "NumberOfNames = " << pExportDirectory->NumberOfNames << endl;
cout << hex << "AddressOfFunctions = " << pExportDirectory->AddressOfFunctions << endl;
cout << hex << "AddressOfNames = " << pExportDirectory->AddressOfNames << endl;
cout << hex << "AddressOfNameOrdinals = " << pExportDirectory->AddressOfNameOrdinals << endl;
cout << hex << "-FunctionsDetail-------------------------------------------------" << endl;
cout << hex << "-\t\t导出函数序号\t\tRVA\t\tFunctionName" << endl;

DWORD *AddrFunctions = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfFunctions, pFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNames, pFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pFileBuffer + RVAToFOA(pExportDirectory->AddressOfNameOrdinals, pFileBuffer));
DWORD i = 0;
DWORD j = 0;
/*
DWORD a = (DWORD)Fun_Name;
LPSTR* c = &Fun_Name;
DWORD b = RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer;
printf("Fun_Name地址:%x\n",Fun_Name);//输出Fun_Name中的值,即字符串的地址
printf("Fun_Name地址:%p\n",Fun_Name);//输出Fun_Name中的值,而非Fun_Name地址,即字符串的地址
printf("Fun_Name地址:%p\n",c);
printf("Fun_Name地址:%x\n",b);
printf("Fun_Name地址:%s\n",b);//将b的整数作为地址去找该地址指向的内容
printf("Fun_Name地址:%s\n",Fun_Name);//输出同上一行
*/
for(j = 0; j < pExportDirectory->NumberOfNames; j++)
{
if(!strcmp((LPSTR)RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer,Fun_Name))
{
i = AddrOrdinals[j];
printf("导出序号0x%x 对应的导出函数名为 %s ,该函数RVA为:%x\n",AddrOrdinals[j] + pExportDirectory->Base,RVAToFOA(AddrName[j], pFileBuffer) + (DWORD)pFileBuffer,AddrFunctions[i]);
return (PDWORD)AddrFunctions[i];
}
}
printf("不存在该导出函数\n");
//return (PDWORD)AddrFunctions[i];

}//end else{

}//end GetFunctionAddrByName(PVOID pFileBuffer, LPSTR fun_name)

E AddNewSection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*****************************************************************************
函数功能:在原PE文件中新增一个节,步骤:
1. 判断SizeOFHeader能否放下多余两个节区(一个新增节区,一个全0节区代表区块结束),分三种情况:
(1)已有节表后直接可以放下两个节表 (2)条件满足(1),但是最后一个节表后面的数据非0x00则执行(3);
(3)节表后放不下,但是dos头后pe前可放下;(4)前两种情况都不行,需扩大最后一个节把代码填进去

2. 本函数讨论第一种情况
1) 修改PE头中节的数量(NumberOfSections)
2) 修改sizeOfImage的大小
3) 修正新增节表的所有属性
4) 添加一个新的节表(可以copy一份然后修改)
5) 在新增节表后面填充一个节表大小的0x00
6)在原有数据的最后,新增一个节的数据(内存对齐的整数倍).

参数1:新增节的大小。参数2:新增节的NewSection_FileBuffer。参数3:新增节的名字
*****************************************************************************/
//参数为新增节的大小
#ifndef IMAGE_SIZEOF_SECTION_HEADER
#define IMAGE_SIZEOF_SECTION_HEADER 40
#endif
VOID AddNewSection(DWORD Add_Section_Length,LPVOID* NewSection_FileBuffer,LPSTR Add_Section_Name)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
LPVOID pFileBuffer = NULL;
LPVOID pTempFileBuffer = NULL;//新的FileBuffer,之后再写入新文件

pFileBuffer = ReadPEFile(FILEPATH);
DWORD fileSize = ReadPESize(FILEPATH);
printf("AddNewSection文件大小为:0x%x\n",fileSize);
if(pFileBuffer == NULL){
printf("文件 --> 文件缓冲区失败");
return ;
}

pTempFileBuffer = malloc(fileSize + Add_Section_Length);
if(pTempFileBuffer == NULL){
printf("临时文件缓冲区申请失败");
free(pFileBuffer);
return ;
}
memset(pTempFileBuffer, 0, fileSize + Add_Section_Length);
memcpy(pTempFileBuffer, pFileBuffer, fileSize);//全部拷进去

pDosHeader = (PIMAGE_DOS_HEADER)pTempFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS32)((BYTE *)pDosHeader + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);

pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);
//保存text节的属性后面复制给新增节的属性
PIMAGE_SECTION_HEADER pText_Section = pSectionHeader;

//判断SizeOfHeaders - 已使用的头的大小 >= 2*IMAGE_SIZEOF_SECTION_HEADER
//#define IMAGE_SIZEOF_SECTION_HEADER 40
//已使用的头的大小 = DOS(0x3C + 0x4) + 垃圾数据 + PE标记(0x4) + 标准PE头(0x14) + 可选PE头
//(pFileHeader->SizeOfOptionalHeader) + 已存在节表(pFileHeader->NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER)
//已使用的头的大小 = (DWORD)pSectionHeader - (DWORD)PIMAGE_DOS_HEADER + pFileHeader->NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER

//已有节表后剩余的空间大小
DWORD Test = pOptionHeader->SizeOfHeaders - ((DWORD)pSectionHeader - (DWORD)pDosHeader + pFileHeader->NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER);
printf("已有节表后剩余的空间大小:%d\n",Test);
if(pOptionHeader->SizeOfHeaders - ((DWORD)pSectionHeader - (DWORD)pDosHeader + pFileHeader->NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER) >= 2*IMAGE_SIZEOF_SECTION_HEADER)
{ //应该还有一个判断条件就是最后一个节表后面的数据是否是0x00?
//1) 修改PE头中节的数量(NumberOfSections)
pFileHeader->NumberOfSections = pFileHeader->NumberOfSections + 1;
//2) 修改sizeOfImage的大小
pOptionHeader->SizeOfImage = pOptionHeader->SizeOfImage + Add_Section_Length;
//将指针指向新增节表的首地址
pSectionHeader += pFileHeader->NumberOfSections - 1;

DWORD SizeOfData = 0;
DWORD MaxSize = 0;

//3)修正新增节表属性1--Name(总共9个属性)
strcpy((char *)pSectionHeader->Name, Add_Section_Name);
//3)属性2--Misc.VirtualSize
pSectionHeader->Misc.VirtualSize = Add_Section_Length;
//3)属性3--VirtualAddress,取Misc.VirtualSize与SizeOfRawData的最大值,且为pOptionHeader->SectionAlignment的倍数
MaxSize = (pSectionHeader - 1)->Misc.VirtualSize > (pSectionHeader - 1)->SizeOfRawData?(pSectionHeader - 1)->Misc.VirtualSize:(pSectionHeader - 1)->SizeOfRawData;
if(MaxSize % pOptionHeader->SectionAlignment == 0){
SizeOfData = MaxSize / pOptionHeader->SectionAlignment * pOptionHeader->SectionAlignment;//不够一个块的取一个块的大小(如0x112/0x1000) + 0x1000 = 0x1000
}else{
SizeOfData = MaxSize / pOptionHeader->SectionAlignment * pOptionHeader->SectionAlignment + pOptionHeader->SectionAlignment;
}
//由于新增节数据是在已有的最后一个节后加的,故起始地址为上一个节的大小
pSectionHeader->VirtualAddress = (pSectionHeader - 1)->VirtualAddress + SizeOfData;
//3)属性4--SizeOfRawData
pSectionHeader->SizeOfRawData = Add_Section_Length;
//3)属性5--PointerToRawData
pSectionHeader->PointerToRawData = (pSectionHeader - 1)->PointerToRawData + (pSectionHeader - 1)->SizeOfRawData;
//3)属性6--Characteristics
pSectionHeader->Characteristics = pText_Section->Characteristics;//text节的属性,其余属性为0

NewFileBufferToFile(pTempFileBuffer,fileSize + Add_Section_Length,FilePath_Out);
}
*NewSection_FileBuffer = pTempFileBuffer;
}

F Print_Relocation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*****************************************************************************	
打印重定位表
*****************************************************************************/
BOOL Print_Relocation( LPVOID pFileBuffer )
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNtHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_BASE_RELOCATION pBaseRelocation = NULL;

DWORD Size = 0;
DWORD i = 0;
DWORD FOA=0;
DWORD RVA=0;
DWORD NumberOfRelocationAddress = 0;
//注意是两字节型的指针
PWORD pRelocation = NULL;//指向重定位表中需要重定位的地址的指针

if(pFileBuffer ==NULL)
{
printf("pFileBuffer缓冲区指针出错...\n");
return ERROR;
}
//判断是否含有有效MZ和PE标志
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*((PDWORD)((BYTE *)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}

pNtHeader = (PIMAGE_NT_HEADERS32)( (DWORD)pDosHeader + pDosHeader->e_lfanew );
pFileHeader = (PIMAGE_FILE_HEADER)( (DWORD)pNtHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)( (DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER );

//pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pDataDirectory[5];
//pBaseRelocation = (PIMAGE_BASE_RELOCATION)( (DWORD)pDosHeader +
//ConvertRvaToFoa(pDataDirectory->VirtualAddress , pFileBuffer));

pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory ;
if(pDataDirectory[5].VirtualAddress == 0)
{
cout << "不存在基址重定位表..." << endl;
return NULL;
}

pBaseRelocation = (PIMAGE_BASE_RELOCATION)( (DWORD)pDosHeader + RVAToFOA( (&pDataDirectory[5])->VirtualAddress , pFileBuffer ) );//第6个目录表(重定位表的目录)的地址,

while(pBaseRelocation->VirtualAddress && pBaseRelocation->SizeOfBlock)
{
pRelocation = (PWORD)( (DWORD)pBaseRelocation + 2 * sizeof(DWORD) );//指向重定位表中的地址表,#define IMAGE_SIZEOF_BASE_RELOCATION 8
printf("***************************************************************************************\n");
printf("VirtualAddress :%-10x",pBaseRelocation->VirtualAddress );
printf("SizeOfBlock :%-10X",pBaseRelocation->SizeOfBlock );
NumberOfRelocationAddress = (pBaseRelocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION)/2 ;
printf("NumberOfRelocationAddress :%-10X\n", NumberOfRelocationAddress );
printf("***************************************************************************************\n");
printf(" Index RVA Type Items\n");

DWORD j = 0;
DWORD x = 0;
DWORD y = 0;
for(j = 0 ; j<NumberOfRelocationAddress ;j++)//pRelocation++遍历重定位表中的地址表
{

x = (DWORD)pRelocation[j]&0xfff;
y = pBaseRelocation->VirtualAddress;
//printf("%x ",x);
//printf("%x ",y);
RVA = x + y;
//最后一项如果为0,仅做对齐用
if(x == 0)
{
printf("%d ", j + 1 );
printf("- ");
printf("%x ", (pRelocation[j]&0xf000)>>12 );
printf("%d ", NumberOfRelocationAddress );
printf("\n");
}
else
{

//RVA = (DWORD)(pRelocation[j]&0xfff + pBaseRelocation->VirtualAddress);
printf("%d ", j + 1 );
printf("%x ",RVA);
printf("%x ", (pRelocation[j]&0xf000)>>12 );
printf("%d ", NumberOfRelocationAddress );
printf("\n");
}
}
Size +=pBaseRelocation->SizeOfBlock;

pBaseRelocation = (PIMAGE_BASE_RELOCATION)( (DWORD)pBaseRelocation + pBaseRelocation->SizeOfBlock );//遍历重定位表
printf("\n");

}

printf("%x\n",Size);
printf("%x\n",(&pDataDirectory[5])->Size );

free(pFileBuffer);
}

10 Move_Export_Table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*****************************************************************************
移动导出表
*****************************************************************************/
PDWORD Move_Export_Table(LPVOID pFileBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
LPSTR New_File_Name = "C:/Move_Export_Table.dll";

pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS32)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
//pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((BYTE *)pNTHeader + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD));
//pOptionHeader = &pNTHeader->OptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pFileHeader->SizeOfOptionalHeader);

pDataDirectory = pOptionHeader->DataDirectory;
cout << "DataDirectory[0].VirtualAddress:" << hex << pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress << endl;
printf("文件偏移为:%x\n",RVAToFOA(pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress,pFileBuffer));
if(pDataDirectory[0].VirtualAddress == 0)
{
cout << "不存在导出表..." << endl;
return ERROR;
}

//1)若在源文件上新增一个节并存放移动的导出表数据,该操作失败的话会导致源文件丢失
//故新建一个TempFileBuffer来使用,包括移动后的导出表也在里面,且不会改变源文件
//新建文件的大小 = 源文件大小 + 新增节的大小
//新增节的大小:可由需要被移动节的大小计算得到。本例子指定为0x1000
DWORD Add_Section_Length = 0x1000;
LPVOID pTempFileBuffer = NULL;
//2)新增一个节表和全0x00的节数据
//节的名字为.In7ect
LPSTR Section_Name = ".In7ect";
AddNewSection(Add_Section_Length,&pTempFileBuffer,Section_Name);

PIMAGE_DOS_HEADER pDosHeader_Temp = NULL;
PIMAGE_NT_HEADERS pNTHeader_Temp = NULL;
PIMAGE_FILE_HEADER pPEHeader_Temp = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader_Temp = NULL;
PIMAGE_SECTION_HEADER pSectionHeader_Temp = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory_Temp = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory_Temp = NULL;
if (!pTempFileBuffer)
{
printf("(MoveExportTable)Can't open file!\n");
return ERROR;
}

if (*((PWORD)pTempFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("(MoveExportTable)No MZ flag, not exe file!\n");
free(pTempFileBuffer);
return ERROR;
}
pDosHeader_Temp = (PIMAGE_DOS_HEADER)pTempFileBuffer;

if (*((PDWORD)((DWORD)pTempFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("(MoveExportTable)Not a valid PE flag!\n");
free(pTempFileBuffer);
return ERROR;
}

pNTHeader_Temp = (PIMAGE_NT_HEADERS32)((DWORD)pTempFileBuffer + pDosHeader_Temp->e_lfanew);
pPEHeader_Temp = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader_Temp) + sizeof(DWORD));
pOptionHeader_Temp = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader_Temp + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader_Temp = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader_Temp + pPEHeader_Temp->SizeOfOptionalHeader);
pDataDirectory_Temp = (PIMAGE_DATA_DIRECTORY)pOptionHeader_Temp->DataDirectory;
pExportDirectory_Temp = (PIMAGE_EXPORT_DIRECTORY)(RVAToFOA(pDataDirectory_Temp[0].VirtualAddress, pTempFileBuffer) + (DWORD)pTempFileBuffer);

cout << "DataDirectory[0].VirtualAddresscccccTTTT:" << hex << pExportDirectory_Temp->AddressOfFunctions << endl;
//3)先定位到导出表的三个地址表
DWORD *AddrFunctions = (DWORD *)((DWORD)pTempFileBuffer + RVAToFOA(pExportDirectory_Temp->AddressOfFunctions, pTempFileBuffer));
DWORD *AddrName = (DWORD *)((DWORD)pTempFileBuffer + RVAToFOA(pExportDirectory_Temp->AddressOfNames, pTempFileBuffer));
WORD *AddrOrdinals = (WORD *)((DWORD)pTempFileBuffer + RVAToFOA(pExportDirectory_Temp->AddressOfNameOrdinals, pTempFileBuffer));

//4)移动AddressOfFuncitons
//计算addressOfFunctions的起始位置,在最后的一个节中
//定位到新增节填充数据的起始位置
DWORD FileSize_Source = ReadPESize(FILEPATH);
pSectionHeader_Temp = pSectionHeader_Temp + pPEHeader_Temp->NumberOfSections - 1;
PDWORD StartAddressofFunctions_Temp = (PDWORD)((DWORD)pTempFileBuffer+pSectionHeader_Temp->PointerToRawData);
//PDWORD StartAddressofFunctions_Temp = (PDWORD)((DWORD)pTempFileBuffer + FileSize_Source);
memcpy(StartAddressofFunctions_Temp, AddrFunctions, pExportDirectory_Temp->NumberOfFunctions * 4);

//5)移动AddressofNameOrdianls,移动的位置紧跟是紧跟addressOfFunctions后
//修正新的起始位置
PWORD StartAddressofOrdianls_Temp = (PWORD)((DWORD)StartAddressofFunctions_Temp + pExportDirectory_Temp->NumberOfFunctions * 4);
//printf("StartAddressofOrdianls_TempFOA:%x\n",(DWORD)StartAddressofOrdianls_Temp - (DWORD)pTempFileBuffer);
memcpy(StartAddressofOrdianls_Temp, AddrOrdinals, pExportDirectory_Temp->NumberOfNames * 2);

//6)移动AddressofNames,移动的位置紧跟addressofOrdianls
//修正新的起始位置
PDWORD StartAddressofNames_Temp = (PDWORD)((DWORD)StartAddressofOrdianls_Temp + pExportDirectory_Temp->NumberOfNames * 2);
//printf("StartAddressofNames_TempFOA:%x\n",(DWORD)StartAddressofNames_Temp - (DWORD)pTempFileBuffer);
memcpy(StartAddressofNames_Temp, AddrName, pExportDirectory_Temp->NumberOfNames * 4);

//7)拷贝函数名称,并修复新的AddressofNames中的地址
//修正新的起始位置
PDWORD Start_Name_Address_Temp = (PDWORD)((DWORD)StartAddressofNames_Temp + pExportDirectory_Temp->NumberOfNames * 4);
PDWORD NameAddress_Temp = Start_Name_Address_Temp;
for (DWORD i = 0; i < pExportDirectory_Temp->NumberOfNames; i++)
{
//获取原来的地址
DWORD NameofFOA = RVAToFOA(*(AddrName + i), pTempFileBuffer);
//拷贝
memcpy( NameAddress_Temp, (PDWORD)((DWORD)pTempFileBuffer + NameofFOA), strlen((LPSTR)((DWORD)pTempFileBuffer + NameofFOA)) + 1);
//修复AddressofName_Temp的每一项的值,让PE文件解析的时候到该处来取函数名
*(StartAddressofNames_Temp + i) = FOAToRVA((DWORD)NameAddress_Temp - (DWORD)pTempFileBuffer,pTempFileBuffer);
//计算拷贝到新地址的起始位置
printf("%x: %s\n", strlen((LPSTR)((DWORD)pTempFileBuffer + NameofFOA)), (PDWORD)((DWORD)pTempFileBuffer + NameofFOA));
NameAddress_Temp = (PDWORD)((DWORD)NameAddress_Temp + strlen((LPSTR)((DWORD)pTempFileBuffer + NameofFOA))+1);
}
Start_Name_Address_Temp = NameAddress_Temp;

//8)修改pExportDirectory_Temp三个地址表的值,使其指向新的起点
pExportDirectory_Temp->AddressOfFunctions = FOAToRVA((DWORD)StartAddressofFunctions_Temp - (DWORD)pTempFileBuffer,pTempFileBuffer);
pExportDirectory_Temp->AddressOfNames = FOAToRVA((DWORD)StartAddressofNames_Temp - (DWORD)pTempFileBuffer,pTempFileBuffer);
pExportDirectory_Temp->AddressOfNameOrdinals = FOAToRVA((DWORD)StartAddressofOrdianls_Temp - (DWORD)pTempFileBuffer,pTempFileBuffer);

//9)将导出表拷贝到新节中
//修正新的起始地址
//printf("新导出表的起始地址:%x\n",FOAToRVA((DWORD)Start_Name_Address_Temp - (DWORD)pTempFileBuffer,pTempFileBuffer));
memcpy(Start_Name_Address_Temp, pExportDirectory_Temp, sizeof(IMAGE_EXPORT_DIRECTORY));

//10)将数据目录项中导出表指向新的位置
pDataDirectory_Temp[0].VirtualAddress = FOAToRVA((DWORD)Start_Name_Address_Temp - (DWORD)pTempFileBuffer,pTempFileBuffer);

//11)存盘
NewFileBufferToFile(pTempFileBuffer, FileSize_Source + Add_Section_Length, New_File_Name);
//*pFileBuffer_ExportTable = pTempFileBuffer;
return NULL;
}