1)- 实现如下功能
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
BYTE* bufferApply = nullptr;//将磁盘文件复制到内存中后, 使用bufferApply指向该空间
DWORD fileSize = 0;//将磁盘文件复制到内存时使用需要申请空间, 使用fileSize设置申请空间的大小
BYTE* bufferMem = nullptr;//将内存中文件进行拉伸时需要申请新的空间, 使用bufferMem指向该空间
BYTE* bufferNewMem = nullptr;//将内存中拉伸后的文件拉回到新的空间, 使用bufferNewMem指向该空间
WORD section_num = 0;//代表文件中节的个数
LPVOID pFileBuffer = NULL;
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;
char str[9] = { 0 };//用于存储节表中的节表名称字符串
void LoadToMemory() {
char* road = "D:\\Ddisk\\goodThing\\fg.exe";//设置文件路径
FILE *note = NULL;
fopen_s(¬e, road, "rb");//打开文件
fseek(note, 0, SEEK_END);//将文件指针移到末端
fileSize = ftell(note);//获取文件指针位置得知文件大小
fseek(note, 0, SEEK_SET);//将文件指针移到开始位置
bufferApply = (BYTE*)malloc(fileSize);//根据文件大小分配内存
fread(bufferApply, 1, fileSize, note);//将文件指针指向的内容读取到内存中
fclose(note);//关闭文件指针
}
void SetHeader() {//设置各个PE文件头的参数
pDosHeader = (PIMAGE_DOS_HEADER)bufferApply;
pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + (DWORD)bufferApply);
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
WORD optional_size = pPEHeader->SizeOfOptionalHeader;
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + optional_size);
section_num = pPEHeader->NumberOfSections;
}
void ReleaseMem() {
free(bufferApply);
free(bufferMem);
free(bufferNewMem);
}
void File_To_Image() {//将内存中的文件拉伸到新的空间
bufferMem = (BYTE*)calloc(pOptionHeader->SizeOfImage, sizeof(char));
memcpy(bufferMem, bufferApply, pOptionHeader->SizeOfHeaders);
PIMAGE_SECTION_HEADER SectionHeader = pSectionHeader;
for (int i = 0; i < section_num; i++) {
memcpy((void*)((DWORD)bufferMem + SectionHeader->VirtualAddress),
(void*)((DWORD)bufferApply + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData);
SectionHeader++;
}
}
void Image_To_Mem() {//将内存中的文件拉回到新的空间
bufferNewMem = (BYTE*)malloc(fileSize);
memcpy(bufferNewMem, bufferMem, pOptionHeader->SizeOfHeaders);
PIMAGE_SECTION_HEADER SectionHeader = pSectionHeader;
for (int i = 0; i < section_num; i++) {
memcpy((void*)((DWORD)bufferNewMem + SectionHeader->PointerToRawData),
(void*)((DWORD)bufferMem + SectionHeader->VirtualAddress), SectionHeader->SizeOfRawData);
SectionHeader++;
}
}
int main() {
LoadToMemory();
SetHeader();
File_To_Image();
Image_To_Mem();
char* road = "D:\\Ddisk\\goodThing\\hello.exe";
FILE *bomb = NULL;
fopen_s(&bomb, road, "wb");
size_t written = fwrite(bufferNewMem, 1, fileSize, bomb);
fclose(bomb);
ReleaseMem();
}
2)- 编写一个函数,能够将RVA的值转换成FOA.
RVA (Relative Virtual Address):PE文件加载到内存中时相对于ImageBase的偏移量
FOA (File Offset Address):PE 文件中的数据相对于文件开始的偏移量
#include<stdio.h> #include<stdlib.h> #include<windows.h> BYTE* bufferApply = nullptr;//将磁盘文件复制到内存中后, 使用bufferApply指向该空间 DWORD fileSize = 0;//将磁盘文件复制到内存时使用需要申请空间, 使用fileSize设置申请空间的大小 WORD section_num = 0;//代表文件中节的个数 LPVOID pFileBuffer = NULL; 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; void LoadToMemory() { char* road = "D:\\Ddisk\\goodThing\\fg.exe";//设置文件路径 FILE *note = NULL; fopen_s(¬e, road, "rb");//打开文件 fseek(note, 0, SEEK_END);//将文件指针移到末端 fileSize = ftell(note);//获取文件指针位置得知文件大小 fseek(note, 0, SEEK_SET);//将文件指针移到开始位置 bufferApply = (BYTE*)malloc(fileSize);//根据文件大小分配内存 fread(bufferApply, 1, fileSize, note);//将文件指针指向的内容读取到内存中 fclose(note);//关闭文件指针 } void SetHeader(BYTE* buffer) {//设置各个PE文件头的参数 pDosHeader = (PIMAGE_DOS_HEADER)buffer; pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + (DWORD)buffer); pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20); WORD optional_size = pPEHeader->SizeOfOptionalHeader; pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + optional_size); section_num = pPEHeader->NumberOfSections; } void ReleaseMem() { free(bufferApply); } DWORD RVA_To_FOA(BYTE* addr, BYTE* buffer) { BYTE* tem_buffer = (BYTE*)pDosHeader;//存储原来pDosHeader的数据, 因为下面要对数据进行修改 SetHeader(buffer);//改变pDosHeader中的数据 PIMAGE_SECTION_HEADER SectionHeader = pSectionHeader; DWORD offset = (DWORD)addr - (DWORD)buffer;//得到相对于起始位置的偏移地址 for (int i = 0; i < section_num; i++) {//判断地址属于哪个节并做相应转换 if (offset > SectionHeader->VirtualAddress && (offset < (SectionHeader->VirtualAddress+SectionHeader->Misc.VirtualSize) || offset < (SectionHeader->VirtualAddress+SectionHeader->SizeOfRawData))) { offset = offset - SectionHeader->VirtualAddress; DWORD file_off = (SectionHeader->PointerToRawData) + offset; SetHeader(tem_buffer); return file_off; } SectionHeader++; } SetHeader(tem_buffer); return -1; } int main() { LoadToMemory(); SetHeader(bufferApply); ReleaseMem(); }