PEFile.cpp
上传用户:shouhua
上传日期:2014-12-06
资源大小:5685k
文件大小:14k
源码类别:

杀毒

开发平台:

Visual C++

  1. // PEFile.cpp: implementation of the CPEFile class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include <Imagehlp.h>
  6. //#include "PETools.h"
  7. #include "PEFile.h"
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. //////////////////////////////////////////////////////////////////////
  14. // Construction/Destruction
  15. //////////////////////////////////////////////////////////////////////
  16. CPEFile::CPEFile(HWND hwnd/* = NULL*/)
  17. {
  18. m_hwnd = hwnd;
  19. strcpy(m_filename, "");
  20. m_buffer = 0;
  21. m_size = 0;
  22. m_dosstub_size = 0;
  23. m_pe_header = 0;
  24. m_std_header = 0;
  25. m_nt_header = 0;
  26. m_rom_header = 0;
  27. m_directories = 0;
  28. m_sections = 0;
  29. }
  30. CPEFile::~CPEFile()
  31. {
  32. if (m_buffer)
  33. {
  34. delete m_buffer;
  35. m_buffer = 0;
  36. }
  37. }
  38. BOOL CheckPe(FILE* pFile)
  39. {
  40. fseek(pFile,0,SEEK_SET);
  41. BOOL bFlags=FALSE;
  42. WORD IsMZ;
  43. DWORD IsPE,pNT;
  44. fread(&IsMZ,sizeof(WORD),1,pFile);
  45. if(IsMZ==0x5A4D)
  46. {
  47. fseek(pFile,0x3c,SEEK_SET);
  48. fread(&pNT,sizeof(DWORD),1,pFile);
  49. fseek(pFile,pNT,SEEK_SET);
  50. fread(&IsPE,sizeof(DWORD),1,pFile);
  51. if(IsPE==0X00004550)
  52. bFlags=TRUE;
  53. else
  54. bFlags=FALSE;
  55. }
  56. else
  57. bFlags=FALSE;
  58. fseek(pFile,0,SEEK_SET);
  59. return bFlags;
  60. }
  61. // LoadExecutable
  62. //
  63. // - Load the executable in memory and parse the pe header
  64. //==============================================================================================
  65. bool CPEFile::LoadExecutable(char *filename)
  66. {
  67. bool result;
  68. FILE *f;
  69.     //IMAGE_DOS_HEADER     DosHeader;
  70. // Delete all previous buffer
  71. if (m_buffer)
  72. {
  73. delete m_buffer;
  74. m_buffer = 0;
  75. }
  76. // Load the file into memory
  77. f = fopen(filename, "rb");
  78. if (!f)
  79. {
  80. //MessageBox(m_hwnd, CString("Can't open for reading the file ") + CString(filename), "Open error", 0);
  81. return (false);
  82. }
  83. //fseek(f,0,SEEK_SET);
  84. //fread(&DosHeader,sizeof(IMAGE_DOS_HEADER),1,f);
  85. //if(DosHeader.e_magic!=IMAGE_DOS_SIGNATURE)
  86. //{
  87. //return  false;
  88. //}
  89. if(!CheckPe(f))
  90. {
  91. return  false;
  92. }
  93. fseek(f, 0, SEEK_END);
  94. m_size = ftell(f);
  95. fseek(f, 0, SEEK_SET);
  96. m_buffer = new unsigned char[m_size];
  97. if (fread(m_buffer, sizeof(unsigned char), m_size, f) != (size_t)m_size)
  98. {
  99. MessageBox(m_hwnd, CString("Can't read the whole file ") + CString(filename), "Open error", 0);
  100. fclose(f);
  101. if (m_buffer)
  102. {
  103. delete m_buffer;
  104. m_buffer = 0;
  105. }
  106. return (false);
  107. }
  108. fclose (f);
  109. // Update all variables
  110. result = UpdatePEVars(false);
  111. if (result)
  112. {
  113. strcpy(m_filename, filename);
  114. }
  115. return (result);
  116. }
  117. // UpdatePEVars
  118. //
  119. // - Parse all pe headers into our variables
  120. //==============================================================================================
  121. bool CPEFile::UpdatePEVars(bool fix_sections/* = false*/)
  122. {
  123. unsigned int i;
  124. unsigned short dos_stub;
  125. unsigned int pe_offset, pe_signature;
  126. unsigned int current_pos;
  127. // DEBUG
  128. fix_sections = true;
  129. // Executable not yet loaded!!!!
  130. if (!m_buffer)
  131. {
  132. //MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  133. return (false);
  134. }
  135. // Check DosStub infos
  136. dos_stub = ((unsigned short*)m_buffer)[0];
  137. if (dos_stub != 0x5a4d)
  138. {
  139. //MessageBox(m_hwnd, "Not a windows executable", "Format error", 0);
  140. return (false);
  141. }
  142. pe_offset = *((unsigned int*)(m_buffer + 0x3c));
  143. // Check PE Format signature
  144. pe_signature = *((unsigned int*)(m_buffer + pe_offset));
  145. if (pe_signature != 0x00004550)
  146. {
  147. //MessageBox(m_hwnd, "Not a PE format executable", "Format error", 0);
  148. //return (false);
  149. }
  150. // Get PE Infos
  151. current_pos = pe_offset + 4;
  152. m_dosstub_size = current_pos;
  153. m_pe_header = (PEHeader*)(m_buffer + current_pos);
  154. current_pos += sizeof(PEHeader);
  155. m_nt_header = (NTOptionalHeader*)(m_buffer + current_pos);
  156. current_pos += sizeof(NTOptionalHeader);
  157. m_directories = (DataDirectory*)(m_buffer + current_pos);
  158. current_pos += sizeof(DataDirectory) * m_nt_header->numDataDirectories;
  159. m_sections = (Section*)(m_buffer + current_pos);
  160. current_pos += sizeof(Section) * m_pe_header->numSections;
  161. // Do we need to fix all Raw Infos for each section? (Especially for a dumped task)
  162. if (fix_sections)
  163. {
  164. for (i=0; i<m_pe_header->numSections; i++)
  165. {
  166. m_sections[i].dataOffset = m_sections[i].RVA;
  167. m_sections[i].dataAlignSize = m_sections[i].misc.virtualSize;
  168. }
  169. }
  170. return (true);
  171. }
  172. // WriteInfos
  173. //
  174. // - Write pe infos into a txt file
  175. //==============================================================================================
  176. bool CPEFile::WriteInfos(char *filename)
  177. {
  178. unsigned int i;
  179. char buffer[9];
  180. FILE *fd;
  181. // Executable not yet loaded!!!!
  182. if (!m_buffer)
  183. {
  184. MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  185. return (false);
  186. }
  187. fd = fopen(filename, "w");
  188. if (!fd)
  189. {
  190. MessageBox(m_hwnd, CString("Can't open for writing the file ") + CString(filename), "Open error", 0);
  191. return (false);
  192. }
  193. // pe header
  194. fprintf(fd, "---==== PE Infos ====---nn");
  195. fprintf(fd, "tdosStubSize 0x%xn", m_dosstub_size);
  196. fprintf(fd, "nPEHeadern");
  197. fprintf(fd, "tcpuType 0x%xn", m_pe_header->cpuType);
  198. fprintf(fd, "tnumSections 0x%xn", m_pe_header->numSections);
  199. fprintf(fd, "tdateStamp 0x%xn", m_pe_header->dateStamp);
  200. fprintf(fd, "tsymbolTable 0x%xn", m_pe_header->symbolTable);
  201. fprintf(fd, "tnumSymbols 0x%xn", m_pe_header->numSymbols);
  202. fprintf(fd, "toptionalHeaderSize 0x%xn", m_pe_header->optionalHeaderSize);
  203. fprintf(fd, "tflags 0x%xn", m_pe_header->flags);
  204. // pe optional header
  205. fprintf(fd, "nNTOptionalHeadern");
  206. fprintf(fd, "tmagic 0x%xn", m_nt_header->magic);
  207. fprintf(fd, "tlinkerMajor 0x%xn", m_nt_header->linkerMajor);
  208. fprintf(fd, "tlinkerMinor 0x%xn", m_nt_header->linkerMinor);
  209. fprintf(fd, "tcodeSize 0x%xn", m_nt_header->codeSize);
  210. fprintf(fd, "tinitDataSize 0x%xn", m_nt_header->initDataSize);
  211. fprintf(fd, "tuninitDataSize 0x%xn", m_nt_header->uninitDataSize);
  212. fprintf(fd, "tentryPoint 0x%xn", m_nt_header->entryPoint);
  213. fprintf(fd, "tcodeBase 0x%xn", m_nt_header->codeBase);
  214. fprintf(fd, "tdataBase 0x%xn", m_nt_header->dataBase);
  215. fprintf(fd, "timageBase 0x%xn", m_nt_header->imageBase);
  216. fprintf(fd, "tsectionAlign 0x%xn", m_nt_header->sectionAlign);
  217. fprintf(fd, "tfileAlign 0x%xn", m_nt_header->fileAlign);
  218. fprintf(fd, "tosMajor 0x%xn", m_nt_header->osMajor);
  219. fprintf(fd, "tosMinor 0x%xn", m_nt_header->osMinor);
  220. fprintf(fd, "timageMajor 0x%xn", m_nt_header->imageMajor);
  221. fprintf(fd, "timageMinor 0x%xn", m_nt_header->imageMinor);
  222. fprintf(fd, "tsubsystemMajor 0x%xn", m_nt_header->subsystemMajor);
  223. fprintf(fd, "tsubsystemMinor 0x%xn", m_nt_header->subsystemMinor);
  224. fprintf(fd, "treserved 0x%xn", m_nt_header->reserved);
  225. fprintf(fd, "timageSize 0x%xn", m_nt_header->imageSize);
  226. fprintf(fd, "theadersSize 0x%xn", m_nt_header->headersSize);
  227. fprintf(fd, "tchecksum 0x%xn", m_nt_header->checksum);
  228. fprintf(fd, "tsubsystem 0x%xn", m_nt_header->subsystem);
  229. fprintf(fd, "tdllFlags 0x%xn", m_nt_header->dllFlags);
  230. fprintf(fd, "tstackReserveSize 0x%xn", m_nt_header->stackReserveSize);
  231. fprintf(fd, "tstackCommitSize 0x%xn", m_nt_header->stackCommitSize);
  232. fprintf(fd, "theapReserveSize 0x%xn", m_nt_header->heapReserveSize);
  233. fprintf(fd, "theapCommitSize 0x%xn", m_nt_header->heapCommitSize);
  234. fprintf(fd, "tloaderFlags 0x%xn", m_nt_header->loaderFlags);
  235. fprintf(fd, "tnumDataDirectories 0x%xn", m_nt_header->numDataDirectories);
  236. // data directories
  237. fprintf(fd, "nDataDirectoriesn");
  238. fprintf(fd, "t;RVAttSizen");
  239. for(i=0; i< m_nt_header->numDataDirectories; i++)
  240. {
  241. fprintf(fd, "t0x%xtt0x%x", 
  242. m_directories[i].RVA, m_directories[i].size);
  243. if (i < (sizeof(dataDirNames) / sizeof(char*)))
  244. fprintf(fd, "tt; %s", dataDirNames[i]);
  245. else
  246. fprintf(fd, "tt; !!!UNKNOWN DIRECTORY!!!");
  247. fprintf(fd, "n");
  248. }
  249. // sections
  250. fprintf(fd, "nSectionsn");
  251. fprintf(fd, "t;NamettVSizetRVAtSizetOffsettReltLinest#Relt#LinetFlagsn");
  252. for(i=0; i < m_pe_header->numSections; i++)
  253. {
  254. strncpy(buffer, (char*)(m_sections[i].name), 8);
  255. *(buffer+8) = 0;
  256. fprintf(fd, "t%st0x%xt0x%xt0x%xt0x%xt0x%xt0x%xt0x%xt0x%xt0x%xtn", 
  257. buffer,
  258. m_sections[i].misc.virtualSize,
  259. m_sections[i].RVA,
  260. m_sections[i].dataAlignSize,
  261. m_sections[i].dataOffset,
  262. m_sections[i].relocationsOffset,
  263. m_sections[i].lineNumbersOffset,
  264. m_sections[i].numRelocations,
  265. m_sections[i].numLineNumbers,
  266. m_sections[i].flags);
  267. }
  268. fclose(fd);
  269. return (true);
  270. }
  271. // SaveExecutable
  272. //
  273. // - Write the current executable
  274. //==============================================================================================
  275. bool CPEFile::SaveExecutable(char *filename)
  276. {
  277. FILE *f;
  278. // Executable not yet loaded!!!!
  279. if (!m_buffer)
  280. {
  281. MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  282. return (false);
  283. }
  284. // Write the current buffer into a file
  285. f = fopen(filename, "wb");
  286. if (!f)
  287. {
  288. MessageBox(m_hwnd, CString("Can't open for writing the file ") + CString(filename), "Open error", 0);
  289. return (false);
  290. }
  291. if (fwrite(m_buffer, sizeof(unsigned char), m_size, f) !=
  292. (size_t)m_size)
  293. {
  294. MessageBox(m_hwnd, "Can't write the whole executable", "Open error", 0);
  295. fclose(f);
  296. return (false);
  297. }
  298. fclose(f);
  299. return (true);
  300. }
  301. // SavePartialExecutable
  302. //
  303. // - Write the current executable in partial mode
  304. //==============================================================================================
  305. bool CPEFile::SavePartialExecutable(char *filename, DWORD start, DWORD length)
  306. {
  307. FILE *f;
  308. start -= m_nt_header->imageBase;
  309. // Executable not yet loaded!!!!
  310. if (!m_buffer)
  311. {
  312. MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  313. return (false);
  314. }
  315. // Write the current buffer into a file
  316. f = fopen(filename, "wb");
  317. if (!f)
  318. {
  319. MessageBox(m_hwnd, CString("Can't open for writing the file ") + CString(filename), "Open error", 0);
  320. return (false);
  321. }
  322. if (fwrite(m_buffer+start, sizeof(unsigned char), length, f) !=
  323. (size_t)length)
  324. {
  325. MessageBox(m_hwnd, "Can't write a part of this executable", "Open error", 0);
  326. fclose(f);
  327. return (false);
  328. }
  329. fclose(f);
  330. return (true);
  331. }
  332. // SaveHeaderOnly
  333. //
  334. // - Write the header of the current executable
  335. //==============================================================================================
  336. bool CPEFile::SaveHeaderOnly(char *filename)
  337. {
  338. FILE *f;
  339. DWORD dwHeaderSize;
  340. // Executable not yet loaded!!!!
  341. if (!m_buffer)
  342. {
  343. MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  344. return (false);
  345. }
  346. // Write the current buffer into a file
  347. f = fopen(filename, "wb");
  348. if (!f)
  349. {
  350. MessageBox(m_hwnd, CString("Can't open for writing the file ") + CString(filename), "Open error", 0);
  351. return (false);
  352. }
  353. dwHeaderSize = m_dosstub_size +
  354. sizeof(PEHeader) +
  355. sizeof(NTOptionalHeader) +
  356. sizeof(DataDirectory)*m_nt_header->numDataDirectories +
  357. sizeof(Section)*m_pe_header->numSections;
  358. // Save the whole headers
  359. if (fwrite(m_buffer, sizeof(unsigned char), dwHeaderSize, f) !=
  360. (size_t)dwHeaderSize)
  361. {
  362. MessageBox(m_hwnd, "Can't write the whole headers", "Open error", 0);
  363. fclose(f);
  364. return (false);
  365. }
  366. fclose(f);
  367. return (true);
  368. }
  369. int CPEFile::FindSectionIndex(DWORD addr)
  370. {
  371. int i;
  372. for (i=0; i<m_pe_header->numSections; i++)
  373. {
  374. if (addr >= m_sections[i].RVA && 
  375. addr < m_sections[i].RVA + m_sections[i].misc.virtualSize)
  376. {
  377. break;
  378. }
  379. }
  380. if (i<m_pe_header->numSections)
  381. return (i);
  382. else
  383. return (-1);
  384. }
  385. DWORD CPEFile::RVA2Offset(DWORD addr)
  386. {
  387. int i = FindSectionIndex(addr);
  388. if (i >= 0)
  389. return (addr - m_sections[i].RVA + m_sections[i].dataOffset);
  390. return (NULL);
  391. }
  392. // GetHeader
  393. //
  394. // - Replace the header of buffer into the current
  395. //==============================================================================================
  396. bool CPEFile::FixHeader()
  397. {
  398. // Executable not yet loaded!!!!
  399. if (!m_buffer)
  400. {
  401. MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  402. return (false);
  403. }
  404. CPEFile pe_file_header(m_hwnd);
  405. if (pe_file_header.LoadExecutable(m_filename) &&
  406. pe_file_header.UpdatePEVars(true)) // FIX RAW=RVA for all sections
  407. {
  408. memcpy(m_buffer, pe_file_header.m_buffer, pe_file_header.m_nt_header->headersSize);
  409. return (true);
  410. }
  411. return (false);
  412. }
  413. // Rebuild Import
  414. //
  415. // - Rebuild the import table
  416. //==============================================================================================
  417. bool CPEFile::RebuildImport(void **name_import)
  418. {
  419. // Executable not yet loaded!!!!
  420. if (!m_buffer)
  421. {
  422. MessageBox(m_hwnd, "Open a file before!!", "Open error", 0);
  423. return (false);
  424. }
  425. char buf[256];
  426. int  i;
  427. if ((i=FindSectionIndex(m_directories[ImportDataDirectory].RVA)) >= 0)
  428. {
  429. int nb_dll = 0, nn = 0;
  430. // Cut the import table to 3 parts
  431. //
  432. // 1 - Image Import Descriptor
  433. // 2 - Import Array Table
  434. // 3 - Function Name
  435. // FIRST
  436. IMAGE_IMPORT_DESCRIPTOR *tmp = 
  437. (IMAGE_IMPORT_DESCRIPTOR*)(m_buffer+m_sections[i].dataOffset+
  438. m_directories[ImportDataDirectory].RVA-m_sections[i].RVA);
  439. DWORD *tmp2;
  440. void *imp1 = tmp;
  441. void *imp2;
  442. void *imp3;
  443. // SECOND
  444. while (tmp->Name)
  445. {
  446. tmp++;
  447. nb_dll++;
  448. }
  449. tmp++;
  450. imp2 = tmp;
  451. // THIRD
  452. tmp2 = (DWORD*)tmp;
  453. while (nn < nb_dll)
  454. {
  455. if (!(*tmp2))
  456. {
  457. nn++;
  458. }
  459. tmp2++;
  460. }
  461. imp3 = tmp2;
  462. sprintf(buf, "%X %X %X",
  463. (DWORD)imp1-(DWORD)m_buffer,
  464. (DWORD)imp2-(DWORD)m_buffer,
  465. (DWORD)imp3-(DWORD)m_buffer);
  466. *name_import = imp3;
  467. MessageBox(m_hwnd, buf, "Ok", 0);
  468. return (true);
  469. }
  470. MessageBox(m_hwnd, "Argh! No section found.!!", "Import error", 0);
  471. return (false);
  472. }