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(); }