0%

PE加载过程

前面对PE结构都有了一定的了解,现在就到了对PE应用的阶段了

一个EXE文件中可能会有多个PE结构,而当文件在被打开的时候,是经过了一系列的操作才运行的,这里就来说一下PE的加载过程,只有对PE的加载过程足够的了解,才能在里面进行一系列的操作。

PE加载过程

首先会将PE文件的全部内容拷到一个内存中,可以将它称为文件缓冲区FileBuffer,此时内容跟文件原本的内容是完全一致的,接着会对它进行一个拉伸的操作,此时文件对其方式就改变了,内容大部分都是一样的,有一部分内容是会被更改的,但是对齐方式是完全改变了的,可以将它称为文件映像ImageBuffer,这样的情况下也还是不能运行的,只是更加接近运行时候的状态了。

此次的练习就是模拟这个过程,然后再将ImageBuffer转会到FileBuffer,再进行存盘,因为在后面我们可以对其中的内容进行修改,就需要进行这样的操作。

实现代码

代码:GitHub

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
#include <stdio.h>
#include <Windows.h>

int GetSize(FILE* ptFile) {
fseek(ptFile, 0, SEEK_END);
int size = ftell(ptFile);
fseek(ptFile, 0, SEEK_SET);
return size;
}

int FileBufferTOImageBuffer(LPSTR pFileBuffer, int FileSize) {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)(pFileBuffer + (DWORD)pDosHeader->e_lfanew + 4);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + sizeof(_IMAGE_FILE_HEADER));
int ImageSize = pOptionalHeader->SizeOfImage;
char* ImageBuffer = (char*)malloc(ImageSize);
memset(ImageBuffer, 0, ImageSize);
memcpy(ImageBuffer, pFileBuffer, pOptionalHeader->SizeOfHeaders);

PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);
for (int i = 0; i < pFileHeader->NumberOfSections; i++) {
memcpy(ImageBuffer + pSectionHeader->VirtualAddress, pFileBuffer + pSectionHeader->PointerToRawData, (pSectionHeader->SizeOfRawData));
pSectionHeader++;
}

char* NewFileBuffer = (char*)malloc(FileSize);
memset(NewFileBuffer, 0, FileSize);

PIMAGE_DOS_HEADER ImageDosHeader = (PIMAGE_DOS_HEADER)ImageBuffer;
PIMAGE_FILE_HEADER ImageFileHeader = (PIMAGE_FILE_HEADER)(ImageBuffer + (DWORD)ImageDosHeader->e_lfanew + 4);
PIMAGE_OPTIONAL_HEADER ImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)ImageFileHeader + sizeof(_IMAGE_FILE_HEADER));
PIMAGE_SECTION_HEADER ImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)ImageOptionalHeader + ImageFileHeader->SizeOfOptionalHeader);

memcpy(NewFileBuffer, ImageBuffer, ImageOptionalHeader->SizeOfHeaders);

for (int i = 0; i < ImageFileHeader->NumberOfSections; i++) {
memcpy(NewFileBuffer + ImageSectionHeader->PointerToRawData, ImageBuffer + ImageSectionHeader->VirtualAddress, ImageSectionHeader->SizeOfRawData);
ImageSectionHeader++;
}

FILE* NewFile = fopen("C:\\Users\\veselwuxin\\Desktop\\wtest1.exe", "wb");
fwrite(NewFileBuffer, 1, FileSize, NewFile);

free(ImageBuffer);
ImageBuffer = NULL;
free(NewFileBuffer);
NewFileBuffer = NULL;
NewFile = NULL;
return 0;
}

int main(int argc, char* argv[]) {
FILE* tFile = fopen("C:\\Users\\veselwuxin\\Desktop\\wtest.exe", "rb");
if (tFile == NULL) {
printf("file open failed\n");
return 0;
}
int FileSize = GetSize(tFile);
char* FileBuffer = (char*)malloc(sizeof(char) * FileSize);
if (!FileBuffer) {
printf("Alloc FileBuffer Failed\n");
return 0;
}
memset(FileBuffer, 0, sizeof(char) * FileSize);

int FreadSize = fread(FileBuffer, 1, sizeof(char) * FileSize, tFile);
if (FreadSize != sizeof(char) * FileSize) {
printf("FileBuffer Write Failed\n");
return 0;
}

printf("FileBuffer address:%p\n", FileBuffer);

FileBufferTOImageBuffer(FileBuffer, FileSize);

free(FileBuffer);
FileBuffer = NULL;
tFile = NULL;

return 0;
}

虽然整体代码不够精炼,也已经达到了学习阶段对过程的理解