• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

Magc,e,e,Py

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

自己慢慢写的PeTool,有点乱,但是函数功能和参数注释应该还挺全的吧?

  1 #include "stdafx.h"
  2 #include "pe.h"
  3 #include <stdlib.h>
  4 #include "stdafx.h"
  5 #include <iostream>
  6 #include <iomanip>
  7 #include <fstream>
  8 #include <string>
  9 #include <windows.h>
 10 #include <malloc.h>
 11 
 12 using namespace std;
 13 #define MessageBox_Add 0x74D61E80
 14 
 15 //功能:通过文件路径获得文件指针,并返回其指针地址
 16 //参数:一个指针类型的返回的pFileBuffer指针地址
 17 int Return_FileBuffer_File_sizeAndpFileBuffer(OUT LPVOID* pFileBuffer, IN char* FilePath)
 18 {
 19 
 20 FILE* File = ReadFile(FilePath, "rb");
 21 int File_size = compute_file_len(File);
 22 *pFileBuffer = File_to_FileBuffer(File_size, File);
 23 fclose(File);
 24 return File_size;
 25 }
 26 
 27  
 28 
 29 //功能:打印PE信息
 30 void Print_Pe(IN char* FilePath)
 31 {
 32 FILE* File_Address;
 33 File_Address = ReadFile(FilePath, "rb");
 34 int file_size = compute_file_len(File_Address);
 35 char* FileBuffer = (char*)File_to_FileBuffer(file_size, File_Address);
 36 Read_Pe_info(FileBuffer);
 37 }
 38 
 39 //读取文件,并返回文件流
 40 //参数1:文件路径
 41 //参数2:读取类型
 42 FILE* ReadFile(LPSTR FilePath, char* Type)
 43 
 44 {
 45 FILE* FileAddress;//定义文件流
 46 if (!(FileAddress = fopen(FilePath, Type)))
 47 {
 48 printf("没有读取文件失败,错误01");
 49 fclose(FileAddress);
 50 return 0;
 51 }
 52 return FileAddress;
 53 }
 54 
 55 //获得读取的文件流大小,返回文件流大小
 56 //参数:文件流地址
 57 int SizeOfFile(FILE* FileAddress)
 58 {
 59 int size;
 60 //定位到文件末尾
 61 fseek(FileAddress, NULL, SEEK_END);
 62 //得到大小
 63 size = ftell(FileAddress);
 64 //重定位文件头到最开始的位置
 65 fseek(FileAddress, NULL, SEEK_SET);
 66 return size;
 67 }
 68 
 69 
 70 //申请动态内存,从文件流读取数据,并返回动态内存的文件指针
 71 //参数1:文件流大小,字节
 72 //参数2:文件流指针
 73 //返回值:动态内存的文件指针
 74 LPVOID File_to_FileBuffer(int size, FILE* FileAddress)
 75 {
 76 if (!size)
 77 {
 78 printf("没有获得需要申请的内存大小");
 79 fclose(FileAddress);
 80 return 0;
 81 }
 82 LPVOID MalcMem = NULL;
 83 MalcMem = (char*)malloc(size);
 84 memset(MalcMem, 0, size);
 85 fread(MalcMem, 1, size, FileAddress);
 86 return MalcMem;
 87 }
 88 
 89 
 90 //把文件数据写内存中
 91 //参数1:文件流地址,
 92 //参数2:申请的Filebuffer动态内存地址,
 93 //参数3:Filebuffer大小
 94 LPVOID ReadFileMem(FILE* File_address, LPVOID pFilebuffer, int pFilebuffer_size)
 95 {
 96 if (!(fread(pFilebuffer, 1, pFilebuffer_size, File_address)))
 97 {
 98 printf("错误,请查看代码1000");
 99 return 0;
100 }
101 return pFilebuffer;
102 }
103 
104 //动态分配内存,并刷新分配的内存空间
105 //参数1:文件大小
106 char* Malloc(int buffer_size)
107 {
108 char* buffer_address = (char*)malloc(buffer_size);
109 if (!buffer_address)
110 {
111 printf("内存分配失败,检查代码1001");
112 return 0;
113 }
114 memset(buffer_address, 0, buffer_size);
115 return buffer_address;
116 }
117 
118 
119 //读取Filebuffer的信息,并打印出来
120 //参数1:buffer地址
121 void Read_Pe_info(IN LPVOID buffer_address)
122 {
123 
124 PIMAGE_DOS_HEADER pDosHeader = NULL;
125 PIMAGE_NT_HEADERS pNTHeader = NULL;
126 PIMAGE_FILE_HEADER pPEHeader = NULL;
127 PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
128 PIMAGE_SECTION_HEADER pSectionHeader = NULL;
129 
130 pDosHeader = (PIMAGE_DOS_HEADER)buffer_address;
131 // 获取PE头部偏移
132 if (*((PDWORD)((DWORD)pDosHeader + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
133 {
134 printf("不是有效的PE标志!\n");
135 free(buffer_address);
136 
137 }
138 printf("pDosHeader:%x\n", pDosHeader->e_magic);
139 pNTHeader = PIMAGE_NT_HEADERS((DWORD)pDosHeader + pDosHeader->e_lfanew);
140 printf("=====================开始查找NT头中信息=============================\n\n");
141 printf("pNTHeader:%08x\n", pNTHeader->Signature);
142 
143 //强制类型转化,指向标准PE头
144 pPEHeader = PIMAGE_FILE_HEADER((DWORD)pNTHeader + 4);
145 printf("=====================开始查找标准PE头中信息=========================\n");
146 printf("pPEHeader:%x\n", pPEHeader->Machine);
147 printf("节的数量:%d\n", pPEHeader->NumberOfSections);
148 printf("SizeOfOptionalHeader(可选PE头的大小):%x\n", pPEHeader->SizeOfOptionalHeader);
149 int NumberOfSections = pPEHeader->NumberOfSections;
150 
151 // 强制类型转换,指向可选PE头
152 pOptionHeader = PIMAGE_OPTIONAL_HEADER32((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
153 printf("====================开始查找可选PE头中信息==========================\n");
154 printf("SizeOfImage:%x\n", pOptionHeader->SizeOfImage);
155 printf("SizeOfHeaders:%x\n", pOptionHeader->SizeOfHeaders);
156 printf("SectionAlignment:%x\n", pOptionHeader->SectionAlignment);
157 DWORD SizeOfHeaders = pOptionHeader->SizeOfHeaders;
158 DWORD SizeOfImage = pOptionHeader->SizeOfImage;
159 DWORD SectionAlignment = pOptionHeader->SectionAlignment;
160 // 强制类型转换,指向节表中的信息
161 printf("====================查找到节表中信息%d个==========================\n", pPEHeader->NumberOfSections);
162 pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
163 
164 for (int i = 0; i<NumberOfSections; i++, pSectionHeader++)
165 {
166 printf("Section_Name:%s\n", pSectionHeader->Name);
167 printf("VirtualAddress:%08X\n", pSectionHeader->VirtualAddress);
168 printf("SizeOfRawData:%08X\n", pSectionHeader->SizeOfRawData);
169 printf("PointerToRawData:%08X\n", pSectionHeader->PointerToRawData);
170 printf("==============================================\n");
171 //info_Address[i] = pSectionHeader->VirtualAddress;
172 //info_RawData[i] = pSectionHeader->SizeOfRawData;
173 //info_PointerToRawData[i] = pSectionHeader->PointerToRawData;
174 }
175 printf("打印PE信息结束!!\n");
176 
177  
178 
179 }
180 
181  
182 
183 //FileBuffer拉伸到Imagebuffer
184 //参数1:FileBuffer指针
185 void FileBufferToImagebuffer(IN LPVOID* pFileBuffer, OUT LPVOID* pImagebuffer)
186 {
187 LPVOID pTempImageBuffer = NULL;
188 if (!pFileBuffer)
189 {
190 printf("没有获取到FileBuffer指针,请检查代码");
191 
192 }
193 
194 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)*pFileBuffer;
195 if (*(PWORD)pDos != IMAGE_DOS_SIGNATURE)
196 {
197 printf("不是有效的MZ标志,请检查代码或者是否为EXE程序");
198 
199 }
200 PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD)pDos + pDos->e_lfanew);
201 if (*(PWORD)pNt != IMAGE_NT_SIGNATURE)
202 {
203 printf("不是有效的PE标志,请检查代码或者是否为EXE程序");
204 
205 }
206 PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pNt + 4);
207 PIMAGE_OPTIONAL_HEADER pOption = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER);
208 PIMAGE_SECTION_HEADER pSetion = (PIMAGE_SECTION_HEADER)((DWORD)pOption + pFile->SizeOfOptionalHeader);
209 
210 //将sizeofimage的值扩展为SectionAlignment的整数倍(在内存中一般是0x1000的整数倍)
211 int Sizeofimage_Alignment = pOption->SizeOfImage;
212 int iTemp = pOption->SizeOfImage % pOption->SectionAlignment;
213 
214 if (iTemp != 0)
215 {
216 Sizeofimage_Alignment = pOption->SizeOfImage + pOption->SectionAlignment - iTemp;
217 pOption->SizeOfImage = (DWORD)Sizeofimage_Alignment;
218 }
219 
220 
221 //申请动态内存
222 pTempImageBuffer = (LPVOID)malloc(Sizeofimage_Alignment);
223 //刷新内存
224 memset(pTempImageBuffer, 0, pOption->SizeOfImage);
225 //复制头到动态内存
226 if (!pTempImageBuffer)
227 {
228 printf("内存分配失败,代码0009");
229 }
230 memcpy(pTempImageBuffer, *pFileBuffer, pOption->SizeOfHeaders);
231 //复制节表
232 int CountSection = pFile->NumberOfSections;
233 for (int i = 0; i < CountSection; i++, pSetion++)
234 {
235 memcpy((LPVOID)((DWORD)pTempImageBuffer + pSetion->VirtualAddress), (LPVOID)((DWORD)pDos + pSetion->PointerToRawData), pSetion->SizeOfRawData);
236 }
237 *pImagebuffer = pTempImageBuffer;
238 
239 }
240 
241  
242 
243 //保存内存缓存为文件
244 //参数1:pNewFileBuffer指针
245 //参数2:缓存大小
246 //参数3:文件保存路径,建议使用#define 进行定义,例如:#define NewFilePath "D:\\XXXXX.exe";
247 void Save_pNewFileBufferTo_EXE(IN LPVOID* pNewFileBuffer, IN char* NewFilePath, int pFileSize)
248 {
249 
250 FILE* Save_file = fopen(NewFilePath, "wb+");
251 fwrite(*pNewFileBuffer, pFileSize, 1, Save_file);
252 if (!Save_file)
253 {
254 printf("拷贝失败了,错误代码22\n");
255 fclose(Save_file);
256 return;
257 }
258 fclose(Save_file);
259 return;
260 }
261 
262  
263 
264 //功能:在代码节空白区添加代码
265 //参数1:一个指针类型的pImgeBuffer指针地址
266 //参数2:一个指针类型的pNewImageBuffer指针地址(添加代码后的内存映像)
267 //参数3,:返回被插入代码后的sizeofimage大小
268 void CodeSection_InsertCode(IN LPVOID* pImageBuffer, OUT LPVOID* pNewImageBuffer, DWORD* SizeOfImage)
269 {
270 char ShellCode[] =
271 {
272 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,//MessgeBoxA(0,0,0,0) 四个参数,在堆中压如堆栈,
273 0xE8, 0x00, 0x00, 0x00, 0x00,//E8 就是call
274 0xE9, 0x00, 0x00, 0x00, 0x00 //E9 就是JMP
275 };
276 
277 PIMAGE_DOS_HEADER pNewDos = (PIMAGE_DOS_HEADER)*pImageBuffer;
278 PIMAGE_NT_HEADERS pNewNt = (PIMAGE_NT_HEADERS)((DWORD)pNewDos + (DWORD)(pNewDos->e_lfanew));
279 PIMAGE_FILE_HEADER pNewFile = (PIMAGE_FILE_HEADER)((DWORD)pNewNt + 4);
280 PIMAGE_OPTIONAL_HEADER pNewOptional = (PIMAGE_OPTIONAL_HEADER)((DWORD)pNewFile + IMAGE_SIZEOF_FILE_HEADER);
281 PIMAGE_SECTION_HEADER pNewSection = (PIMAGE_SECTION_HEADER)((DWORD)pNewOptional + pNewFile->SizeOfOptionalHeader);
282 
283 if (!(pNewSection->SizeOfRawData - pNewSection->Misc.VirtualSize > 18))
284 {
285 printf("第一个节区内存空间不够,请查看SizeOfRawData和Misc.VirtualSize");
286 free(*pImageBuffer);
287 }
288 
289 //计算从第一节的哪个位置开始添加代码
290 DWORD ImageBase_ = pNewOptional->ImageBase;
291 char* InsertCode_Pos = (char*)(DWORD)*pImageBuffer + pNewSection->VirtualAddress + pNewSection->Misc.VirtualSize;
292 //把ShellCode复制到InsertCode_Pos
293 memcpy(InsertCode_Pos, ShellCode, sizeof(ShellCode));
294 int E8_Code = MessageBox_Add - (DWORD)(ImageBase_ + ((DWORD)InsertCode_Pos + 0xd - (DWORD)*pImageBuffer));
295 *(PDWORD)(InsertCode_Pos + 0x9) = E8_Code;
296 int E9_Code = (ImageBase_ + pNewOptional->AddressOfEntryPoint) - (DWORD)(ImageBase_ + ((DWORD)InsertCode_Pos + 0x12 - (DWORD)*pImageBuffer));
297 *(PDWORD)(InsertCode_Pos + 0xe) = E9_Code;
298 
299 pNewOptional->AddressOfEntryPoint = (DWORD)InsertCode_Pos - (DWORD)*pImageBuffer;//重新定位程序入口处
300 
301 //pNewOptional->SizeOfImage = pNewOptional->SizeOfImage + sizeof(ShellCode);//把Shellcode代码大小添加进SizeofImage
302 //*SizeOfImage = pNewOptional->SizeOfImage;
303 //申请一块动态内存,大小为加了18个字节后的sizeofimage
304 *pNewImageBuffer = malloc(pNewOptional->SizeOfImage);
305 //把pImageBuffer复制到pNewImagebuffer
306 
307 int Sizeofimage_Alignment = pNewOptional->SizeOfImage;
308 int iTemp = pNewOptional->SizeOfImage % pNewOptional->SectionAlignment;
309 
310 if (iTemp != 0)
311 {
312 Sizeofimage_Alignment = pNewOptional->SizeOfImage + pNewOptional->SectionAlignment - iTemp;
313 pNewOptional->SizeOfImage = Sizeofimage_Alignment;
314 }
315 
316 memcpy(*pNewImageBuffer, *pImageBuffer, pNewOptional->SizeOfImage);
317 *SizeOfImage = pNewOptional->SizeOfImage;
318 
319 }
320 
321  
322 
323 //ImageBuffer压缩到FileBuffer
324 //参数1:ImageBuffer指针
325 //参数2:pNewFileBuffer指针
326 void ImageBufferToFileBuffer(IN LPVOID* pImageBuffer, IN LPVOID* TempFileBuffer2, OUT LPVOID* pNewFileBuffer)
327 {
328 if (!TempFileBuffer2)
329 {
330 printf("临时指针TempFileBuffer没有被分配地址");
331 }
332 if (!*pImageBuffer)
333 {
334 printf("没有获取到FileBuffer指针,请检查代码");
335 
336 }
337 
338 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)*pImageBuffer;
339 if (*(PWORD)pDos != IMAGE_DOS_SIGNATURE)
340 {
341 printf("不是有效的MZ标志,请检查代码或者是否为EXE程序");
342 
343 }
344 PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD)pDos + pDos->e_lfanew);
345 if (*(PWORD)pNt != IMAGE_NT_SIGNATURE)
346 {
347 printf("不是有效的PE标志,请检查代码或者是否为EXE程序");
348 
349 }
350 PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pNt + 4);
351 PIMAGE_OPTIONAL_HEADER pOption = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER);
352 PIMAGE_SECTION_HEADER pSetion = (PIMAGE_SECTION_HEADER)((DWORD)pOption + pFile->SizeOfOptionalHeader);
353 
354 //将sizeofimage的值扩展为SectionAlignment的整数倍(在内存中一般是0x1000的整数倍)
355 int Sizeofimage_Alignment = pOption->SizeOfImage;
356 int iTemp = pOption->SizeOfImage % pOption->SectionAlignment;
357 
358 if (iTemp != 0)
359 {
360 Sizeofimage_Alignment = pOption->SizeOfImage + pOption->SectionAlignment - iTemp;
361 pOption->SizeOfImage = Sizeofimage_Alignment;
362 }
363 
364 
365 //申请动态内存
366 *TempFileBuffer2 = malloc(pOption->SizeOfImage);///////这里有问题,应该是前面的程序出现了内存越界访问造成的。
367 
368 //刷新内存
369 memset(*TempFileBuffer2, 0, pOption->SizeOfImage);
370 //复制头到动态内存
371 if (!*TempFileBuffer2)
372 {
373 printf("内存分配失败,代码0009");
374 }
375 memcpy(*TempFileBuffer2, *pImageBuffer, pOption->SizeOfHeaders);
376 //复制节表
377 int CountSection = pFile->NumberOfSections;
378 
379 for (int i = 0; i < CountSection; i++, pSetion++)
380 {
381 memcpy((LPVOID)((DWORD)*TempFileBuffer2 + pSetion->PointerToRawData), (LPVOID)((DWORD)pDos + pSetion->VirtualAddress), pSetion->SizeOfRawData);
382 }
383 *pNewFileBuffer = *TempFileBuffer2;
384 //free(*TempFileBuffer2);
385 }
386 
387 
388 //计算文件大小
389 //参数:文件指针
390 //int返回值:文件大小
391 int compute_file_len(FILE* pfile)
392 {
393 int len = 0;
394 fseek(pfile, 0, SEEK_END);
395 len = ftell(pfile);
396 fseek(pfile, 0, SEEK_SET);
397 return len;
398 }
399 
400  
401 
402 
403 //功能:给ImageBuffer新增节
404 //参数1:传入拉伸后的ImageBuffer指针地址
405 //参数2:传入添加节后的ImageBuffer指针地址
406 //该函数没有返回值
407 void Add_Seciton(IN LPVOID* ImageBuffer, OUT int* pFileSize)
408 {
409 //众头归位
410 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)*ImageBuffer;
411 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + (DWORD)Temp_dos->e_lfanew);
412 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
413 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
414 PIMAGE_SECTION_HEADER Temp_sec = PIMAGE_SECTION_HEADER((DWORD)Temp_option + Temp_file->SizeOfOptionalHeader);
415 
416 //判断SizeofHeader够不够插入一个节表目录,以及够不够一个空白区,这两个一共80个字节。
417 if (((DWORD)Temp_dos + (DWORD)Temp_option->SizeOfHeaders) - ((DWORD)Temp_dos + ((DWORD)Temp_sec + Temp_file->NumberOfSections * 40)) < 80)
418 {
419 printf("这个程序的SizeofHeader不够,无法插入新的节表目录");
420 free(*ImageBuffer);
421 return;
422 }
423 
424 printf("%c%c%c%c", Temp_sec->Name[0], Temp_sec->Name[1], Temp_sec->Name[2], Temp_sec->Name[3], Temp_sec->Name[4]);
425 //拿到最后节表的最后位置
426 PIMAGE_SECTION_HEADER temp_sec_endPos = (PIMAGE_SECTION_HEADER)((DWORD)Temp_sec + Temp_file->NumberOfSections * 40);
427 //复制最后一个节表到temp_sec_endPos
428 memcpy(temp_sec_endPos,
429 (PIMAGE_SECTION_HEADER)((DWORD)Temp_sec +
430 (Temp_file->NumberOfSections - 1) * 40),
431 40);
432 //将新的最后一个节表temp_sec_end后的40个字节刷新为0
433 memset((temp_sec_endPos + 1), 0, 40);
434 //修改最后一个表的名字
435 temp_sec_endPos->Name[0] = 'P'; temp_sec_endPos->Name[1] = 'K';
436 //修改新增节表在内存中的开始地址
437 temp_sec_endPos->VirtualAddress = temp_sec_endPos->VirtualAddress +
438 (temp_sec_endPos->SizeOfRawData > temp_sec_endPos->Misc.VirtualSize ? temp_sec_endPos->SizeOfRawData : temp_sec_endPos->Misc.VirtualSize);
439 //修改新增节表在文件中的开始地址
440 temp_sec_endPos->PointerToRawData = temp_sec_endPos->PointerToRawData +
441 (temp_sec_endPos->SizeOfRawData > temp_sec_endPos->Misc.VirtualSize ? temp_sec_endPos->SizeOfRawData : temp_sec_endPos->Misc.VirtualSize);
442 //修改在文件中的大小
443 temp_sec_endPos->SizeOfRawData = 0x1000;
444 //修改在内存中的大小
445 temp_sec_endPos->Misc.VirtualSize = 0x1000;
446 
447 //修改节表属性为可读可写可执行,这里我没写
448 
449 //修改节表数量
450 Temp_file->NumberOfSections += 1;
451 
452 //扩大sizeofimage
453 Temp_option->SizeOfImage += 0x1000;
454 
455 *pFileSize = Temp_option->SizeOfImage;
456 
457 }
458 
459 //功能:扩大最后一个节
460 //参数1:拉伸后的ImageBuffer
461 //参数2:需要把最后一个节扩大多少
462 //参数3:扩大后的NewImageBuffer
463 //参数4:传出扩大后的SizeofImage
464 void Expand_Section(IN PVOID* ImageBuffer, DWORD Add_Byte, OUT PVOID* NewImageBuffer, OUT int* Sizeofimage)
465 {
466 //众头归位
467 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)*ImageBuffer;
468 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + (DWORD)Temp_dos->e_lfanew);
469 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
470 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
471 PIMAGE_SECTION_HEADER Temp_sec = PIMAGE_SECTION_HEADER((DWORD)Temp_option + Temp_file->SizeOfOptionalHeader);
472 
473 //拿到节数量
474 int Section_num = Temp_file->NumberOfSections;
475 ////拿到最后一个节的位置
476 PIMAGE_SECTION_HEADER End_Sec = Temp_sec + (Section_num - 1);
477 //拿到扩大后的大小 ADD_Byte为添加的大小字节
478 DWORD Final_SecSize = Add_Byte + (End_Sec->SizeOfRawData > End_Sec->Misc.VirtualSize ? End_Sec->SizeOfRawData : End_Sec->Misc.VirtualSize);
479 //调整节大小
480 End_Sec->Misc.VirtualSize = Final_SecSize;
481 End_Sec->SizeOfRawData = Final_SecSize;
482 //改SizeofImage
483 Temp_option->SizeOfImage += Add_Byte;
484 *Sizeofimage = Temp_option->SizeOfImage;
485 
486 *NewImageBuffer = *ImageBuffer;
487 }
488 
489 //功能:把所有节合并为一个节
490 //参数1:拉伸后的ImageBuffer
491 //参数2:传出合并后的ImageBuffer
492 void Comb_Section(IN LPVOID* ImageBuffer, OUT LPVOID* NewImageBuffer, OUT int* SizeofImage)
493 {
494 //众头归位
495 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)*ImageBuffer;
496 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + (DWORD)Temp_dos->e_lfanew);
497 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
498 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
499 PIMAGE_SECTION_HEADER Temp_sec = PIMAGE_SECTION_HEADER((DWORD)Temp_option + Temp_file->SizeOfOptionalHeader);
500 
501 //得到所有节的总大小
502 DWORD All_Section = Temp_option->SizeOfImage - Temp_sec->VirtualAddress;
503 //改变第一个节在文件中和内存中的总大小
504 Temp_sec->Misc.VirtualSize = All_Section;
505 Temp_sec->SizeOfRawData = All_Section;
506 
507 
508 //把节的属性全部组合**********这里比较重要********************这里比较重要********************这里比较重要**********
509 DWORD numSection = 1;
510 while (numSection <= Temp_file->NumberOfSections)
511 {
512 //属性修改为每个节表的属性组合 **********这里比较重要**********
513 Temp_sec->Characteristics |= (Temp_sec + numSection)->Characteristics;
514 //void ZeroMemory( PVOID Destination,SIZE_T Length );
515 // Destination :指向一块准备用0来填充的内存区域的开始地址。,Length :准备用0来填充的内存区域的大小,按字节来计算。
516 ZeroMemory((char*)Temp_sec + sizeof(IMAGE_SECTION_HEADER)*numSection, sizeof(IMAGE_SECTION_HEADER));
517 numSection++;
518 }
519 //改节的个数
520 Temp_file->NumberOfSections = 1;
521 *SizeofImage = Temp_option->SizeOfImage;
522 *NewImageBuffer = *ImageBuffer;
523 }
524 
525 //功能:打印出所有数据目录表的地址和大小
526 //参数:ImageBuffer地址
527 void PrintDirectory(PVOID* ImageBuffer)
528 {
529 //众头归位
530 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)*ImageBuffer;
531 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + (DWORD)Temp_dos->e_lfanew);
532 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
533 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
534 //PIMAGE_SECTION_HEADER Temp_sec = PIMAGE_SECTION_HEADER((DWORD)Temp_option + Temp_file->SizeOfOptionalHeader);
535 
536 PIMAGE_DATA_DIRECTORY pDir;
537 pDir = (PIMAGE_DATA_DIRECTORY)(&Temp_option->NumberOfRvaAndSizes + 1);
538 //这里为什么要用&Temp_option->NumberOfRvaAndSizes呢? 
539 //因为要找得是Temp_option->NumberOfRvaAndSizes的地址,然后加上一个该地址的长度就等于PIMAGE_DATA_DIRECTORY(数据目录表的地址了)
540 for (int i = 0; i < 16; i++, pDir++)
541 {
542 printf("======第%d个数据目录表=====:\n 0x%08x\n 0x%08x\n", i + 1, pDir->VirtualAddress, pDir->Size);
543 //printf("0x%08x\n",pDir->VirtualAddress);
544 }
545 getchar();
546 
547 }
548 
549 //功能:Rva转Foa
550 //参数1:FileBuffer
551 //参数2:dwRva,需要转换的Rva地址
552 
553 DWORD RvaToFileOffset(IN LPVOID pFileBuffer, IN DWORD dwRva)
554 {
555 //定义文件头
556 PIMAGE_DOS_HEADER dosHeader = NULL; //dos头指针
557 PIMAGE_NT_HEADERS ntHeader = NULL; //nt头指针
558 PIMAGE_FILE_HEADER peHeader = NULL; //pe头指针
559 PIMAGE_OPTIONAL_HEADER32 opHeader = NULL; //可选pe头指针
560 PIMAGE_SECTION_HEADER sectionHeader = NULL; //节表指针
561 
562 //找到文件头
563 dosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
564 ntHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + dosHeader->e_lfanew);
565 peHeader = (PIMAGE_FILE_HEADER)((DWORD)ntHeader + 4);
566 opHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)peHeader + IMAGE_SIZEOF_FILE_HEADER);
567 sectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)opHeader + peHeader->SizeOfOptionalHeader);
568 
569 //1.判断是哪个节
570 int sec = -1;
571 for (int i = 0; i<peHeader->NumberOfSections; i++) {
572 DWORD va = (sectionHeader + i)->VirtualAddress;
573 DWORD size = (sectionHeader + i)->Misc.VirtualSize;
574 if (dwRva >= va && dwRva <= (va + size)) {
575 sec = i;
576 //printf("在第%d个节\n", sec);
577 break;
578 }
579 }
580 if (sec<0) {
581 printf("内存偏移不在任何一个节\n");
582 return 0;
583 }
584 
585 //2.转换
586 DWORD secOffset = dwRva - (sectionHeader + sec)->VirtualAddress;
587 DWORD foa = (sectionHeader + sec)->PointerToRawData + secOffset;
588 
589 return foa;
590 }
591 
592 
593 //功能:打印导出表信息 Print_Export
594 //参数1:FileBuffer
595 
596 void Print_Export(LPVOID Filebuffer)
597 {
598 //众头归位
599 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)Filebuffer;
600 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + (DWORD)Temp_dos->e_lfanew);
601 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
602 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
603 
604 //数据目录指针 Data
605 PIMAGE_DATA_DIRECTORY Data = Temp_option->DataDirectory;
606 //定位导出表FOA地址
607 PIMAGE_EXPORT_DIRECTORY Export_Foa = (PIMAGE_EXPORT_DIRECTORY)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Data[0].VirtualAddress));
608 //判断导出表是否找到
609 if (!Export_Foa) { printf("导出表FOA没有找到"); free(Filebuffer); return; }
610 //打印导出表信息
611 
612 
613 printf("\n=======导出表--Name:%s=======\n", (LPSTR)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Export_Foa->Name)));
614 printf("=======导出表起始序号--Base:%d=======\n", Export_Foa->Base);
615 printf("=======导出表--函数总数--NumberofFuction:%d=======\n", Export_Foa->NumberOfFunctions);
616 printf("=======导出表--名称导出的函数总数--NumberofName:%d=======\n", Export_Foa->NumberOfNames);
617 printf("=======导出表--函数的内存地址表地址(Rva)--AddressOfFuction:%x=======\n", Export_Foa->AddressOfFunctions);
618 printf("=======导出表--函数名称的内存地址表地址(Rva)--AddressOfNames:%x=======\n", Export_Foa->AddressOfNames);
619 printf("=======导出表--函数序号的内存地址表地址(Rva)--AddressOfNameOradinals:%x=======\n", Export_Foa->AddressOfNameOrdinals);
620 printf("=======================函数地址=======================\n\n");
621 PDWORD Foa_Address_Fuctions = (PDWORD)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Export_Foa->AddressOfFunctions));
622 for (int i = 0; i < Export_Foa->NumberOfFunctions; i++)
623 {
624 printf("第%d个函数的地址(Rva):%x\n", i, Foa_Address_Fuctions[i]);
625 }
626 PDWORD _Fuc_NameAddress = (PDWORD)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Export_Foa->AddressOfNames));
627 printf("=======================函数名字地址和名称:=======================\n\n");
628 for (int i = 0; i < Export_Foa->NumberOfNames; i++)
629 {
630 printf("第%d个函数名字的地址(Rva):%#x---函数名字:%s\n", i, _Fuc_NameAddress[i], \
631 (PDWORD)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, _Fuc_NameAddress[i])));
632 
633 //这里需要注意的是_Fuc_NameAddress是指向了函数名称地址表,这个表里面的地址全是Rva,所以\
634 还需要把_Fuc_NameAddress所指向的地址表中的地址(Rva)转为Foa才能识别出名称。同样的,如果要拿到函数地址的Foa\
635 也需要把_Fuc_NameAddress[i]也转为Foa。另外:NumberOfNames函数名称个数跟如何导出有关,我一共导出了四个函数\
636 Mul、Plus、Div、@NONAME,,这个@NONAME就是函数Sub,因为使用了def文件的@NONAME,所以有一个没名字的函数,这里就没有显示出来
637 }
638 printf("=======================函数序号地址(Rva)和序号:=======================\n\n");
639 
640 PWORD Ordinal_Address = (PWORD)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Export_Foa->AddressOfNameOrdinals));
641 for (int i = 0; i < Export_Foa->NumberOfNames; i++)
642 {
643 printf("函数序号地址(Foa):%#x---序号表序号:%d--导出序号:%d\n", Ordinal_Address + i, Ordinal_Address[i], Ordinal_Address[i]+Export_Foa->Base);
644 }
645 
646 }
647 
648 //功能:根据函数名,找到这个函数的地址
649 //参数1:OUT FileBuffer
650 //参数2:需要找的函数名指针。
651 //返回值:函数地址(Rva)
652 DWORD GetFuctionAddrByName(LPVOID Filebuffer, LPSTR pFuctionName)
653 {
654 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)Filebuffer;
655 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + Temp_dos->e_lfanew);
656 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
657 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
658 
659 //数据目录指针 Data
660 PIMAGE_DATA_DIRECTORY Data = Temp_option->DataDirectory;
661 //定位导出表FOA地址
662 PIMAGE_EXPORT_DIRECTORY Export_Foa = (PIMAGE_EXPORT_DIRECTORY)\
663 ((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Data[0].VirtualAddress));
664 //判断导出表是否找到,没有找到就退出
665 if (!Export_Foa) { printf("导出表FOA没有找到"); free(Filebuffer); return 0; }
666 //遍历exe或Dll中存在的函数名字
667 PDWORD FuctionName = (PDWORD)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Export_Foa->AddressOfNames));
668 for (int i = 0; i < (int)Export_Foa->NumberOfNames; i++)
669 {
670 //printf("函数:%s", (LPSTR)((DWORD)Filebuffer+(DWORD)(RvaToFileOffset(Filebuffer, FuctionName[i]))));
671 //这里使用了STRCMP函数进行字符串比较,如果遍历的函数名称与我们提供的一模一样,\
672 那么久会返回函数名称和地址(Rva)
673 if (strcmp((char*)(PDWORD)pFuctionName, \
674 (char*)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, FuctionName[i])))==0) 
675 {
676 printf("让我猜猜,你要找的这个函数的名称是:%s\n\n函数地址为(Rva):%#x\n\n", \
677 (char*)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, FuctionName[i])),FuctionName[i]);
678 return (DWORD)FuctionName[i];
679 }
680 }
681 return 0;
682 
683 }
684 
685 //功能:根据导出序号找到函数地址
686 //参数1:Filebuffer指针
687 //参数2:导出序号的指针
688 //返回值:函数地址(Rva)
689 DWORD GetFuctionAddrbyOrinal(LPVOID Filebuffer, int* Orinal)
690 {
691 PIMAGE_DOS_HEADER Temp_dos = (PIMAGE_DOS_HEADER)Filebuffer;
692 PIMAGE_NT_HEADERS Temp_nt = (PIMAGE_NT_HEADERS)((DWORD)Temp_dos + Temp_dos->e_lfanew);
693 PIMAGE_FILE_HEADER Temp_file = (PIMAGE_FILE_HEADER)((DWORD)Temp_nt + 4);
694 PIMAGE_OPTIONAL_HEADER Temp_option = PIMAGE_OPTIONAL_HEADER((DWORD)Temp_file + IMAGE_SIZEOF_FILE_HEADER);
695 
696 //数据目录指针 Data
697 PIMAGE_DATA_DIRECTORY Data = Temp_option->DataDirectory;
698 //定位导出表FOA地址
699 PIMAGE_EXPORT_DIRECTORY Export_Foa = (PIMAGE_EXPORT_DIRECTORY)\
700 ((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Data[0].VirtualAddress));
701 //判断导出表是否找到,没有找到就退出
702 if (!Export_Foa) { printf("导出表FOA没有找到"); free(Filebuffer); return 0; }
703 //1、根据有函数名字就有函数序号的原理,遍历出序号\
704 2、根据函数地址序号=导出序号-Base
705 PWORD    Foa_Orinal = (PWORD)((DWORD)Filebuffer + RvaToFileOffset(Filebuffer, Export_Foa->AddressOfNameOrdinals));
706 for (int i = 0; i < Export_Foa->NumberOfNames; i++)
707 {
708 if ((int)(Foa_Orinal[i]+Export_Foa->Base) == *Orinal)
709 {
710 printf("已根据导出序号找到函数\n\nBase:%d\n\n这个函数地址的序号为:%d\n\n这个函数的导出序号为:%d\n\n这个函数的地址为(Rva):%#x", \
711 Export_Foa->Base,*Orinal - (int)(Export_Foa->Base), *Orinal, &Foa_Orinal[i]);
712 return (DWORD)(Foa_Orinal+i);
713 }
714 }
715 printf("没有根据你的导出序号找到相关函数");
716 return 0;
717 
718 }
719 
720 //功能:打印重定位表
721 //参数:pFileBuffer指针
722 
723 void Pt_Relocation(PVOID pFileBuffer)
724 {
725 
726 }
727 
728  

 

posted on 2020-07-13 23:48  小小枝枝  阅读(113)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3