自己慢慢写的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