⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 关于pe可执行文件的修改.htm

📁 关于PE可执行文件的修改
💻 HTM
📖 第 1 页 / 共 2 页
字号:
      SizeOfHeapReserve;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>DWORD&nbsp;&nbsp; 
      SizeOfHeapCommit;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>DWORD&nbsp;&nbsp; 
      LoaderFlags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>DWORD&nbsp;&nbsp; 
      NumberOfRvaAndSizes;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>IMAGE_DATA_DIRECTORY 
      DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];<BR>//IMAGE_DATA_DIRECTORY 
      结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等<BR>} IMAGE_OPTIONAL_HEADER32, 
      *PIMAGE_OPTIONAL_HEADER32;<BR><BR>typedef struct _IMAGE_DATA_DIRECTORY 
      {<BR>DWORD&nbsp;&nbsp; 
      VirtualAddress;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//表的RVA地址<BR>DWORD&nbsp;&nbsp; 
      Size;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//大小<BR>} 
      IMAGE_DATA_DIRECTORY, 
      *PIMAGE_DATA_DIRECTORY;<BR><BR>PE文件头后是节表,在winnt.h下如下定义<BR>typedef struct 
      _IMAGE_SECTION_HEADER 
      {<BR>BYTE&nbsp;&nbsp;&nbsp;&nbsp;Name[IMAGE_SIZEOF_SHORT_NAME];//节表名称,如“.text”<BR>union 
      {<BR>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp; 
      PhysicalAddress;&nbsp;&nbsp;&nbsp;&nbsp;//物理地址&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp; 
      VirtualSize;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//真实长度<BR>} 
      Misc;<BR>DWORD&nbsp;&nbsp; 
      VirtualAddress;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//RVA<BR>DWORD&nbsp;&nbsp; 
      SizeOfRawData;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//物理长度<BR>DWORD&nbsp;&nbsp; 
      PointerToRawData;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//节基于文件的偏移量<BR>DWORD&nbsp;&nbsp; 
      PointerToRelocations;&nbsp;&nbsp;&nbsp;&nbsp;//重定位的偏移<BR>DWORD&nbsp;&nbsp; 
      PointerToLinenumbers;&nbsp;&nbsp;&nbsp;&nbsp;//行号表的偏移<BR>WORD&nbsp;&nbsp;&nbsp;&nbsp;NumberOfRelocations;&nbsp;&nbsp;&nbsp;&nbsp;//重定位项数目<BR>WORD&nbsp;&nbsp;&nbsp;&nbsp;NumberOfLinenumbers;&nbsp;&nbsp;&nbsp;&nbsp;//行号表的数目<BR>DWORD&nbsp;&nbsp; 
      Characteristics;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//节属性<BR>} 
      IMAGE_SECTION_HEADER, 
      *PIMAGE_SECTION_HEADER;<BR><BR>以上结构就是在winnt.h中关于PE文件头的定义,如何我们用C/C++来进行PE可执行文件操作,就要用到上面的所有结构,它详细的描述了PE文件头的结构。<BR><BR>3、修改PE可执行文件<BR>现在让我们把一段代码写入任何一个PE格式的可执行文件,代码如下:<BR>-- 
      test.asm --<BR>.386p<BR>.model flat, stdcall<BR>option 
      casemap:none<BR><BR>include \masm32\include\windows.inc<BR>include 
      \masm32\include\user32.inc<BR>includelib \masm32\lib\user32.lib 
      <BR><BR>.code<BR><BR>start:<BR>&nbsp;&nbsp;&nbsp;&nbsp;INVOKE 
      MessageBoxA,0,0,0,MB_ICONINFORMATION or 
      MB_OK<BR>&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>end 
      start<BR><BR>以上代码只显示一个MessageBox框,编译后得到二进制代码如下:<BR>unsigned char 
      writeline[18]={<BR>0x6a,0x40,0x6a,0x0,0x6a,0x0,0x6a,0x0,0xe8,0x01,0x0,0x0,0x0,0xe9,0x0,0x0,0x0,0x0<BR>};<BR><BR>好,现在让我们看看该把这些代码写到那。现在用Tdump.exe显示一个PE格式得可执行文件信息,可以发现如下描述:<BR>Object 
      table:<BR>#&nbsp;&nbsp; 
      Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VirtSize&nbsp;&nbsp;&nbsp;&nbsp;RVA&nbsp;&nbsp;&nbsp;&nbsp; 
      PhysSize&nbsp;&nbsp;Phys off&nbsp;&nbsp;Flags&nbsp;&nbsp; 
      <BR>--&nbsp;&nbsp;--------&nbsp;&nbsp;--------&nbsp;&nbsp;--------&nbsp;&nbsp;--------&nbsp;&nbsp;--------&nbsp;&nbsp;--------<BR>01&nbsp;&nbsp;.text&nbsp;&nbsp;&nbsp;&nbsp; 
      0000CCC0&nbsp;&nbsp;00001000&nbsp;&nbsp;0000CE00&nbsp;&nbsp;00000600&nbsp;&nbsp;60000020 
      [CER]<BR>02&nbsp;&nbsp;.data&nbsp;&nbsp;&nbsp;&nbsp; 
      00004628&nbsp;&nbsp;0000E000&nbsp;&nbsp;00002C00&nbsp;&nbsp;0000D400&nbsp;&nbsp;C0000040 
      [IRW]<BR>03&nbsp;&nbsp;.rsrc&nbsp;&nbsp;&nbsp;&nbsp; 
      000003C8&nbsp;&nbsp;00013000&nbsp;&nbsp;00000400&nbsp;&nbsp;00010000&nbsp;&nbsp;40000040 
      [IR]<BR><BR>Key to section flags:<BR>&nbsp;&nbsp;C - contains 
      code<BR>&nbsp;&nbsp;E - executable<BR>&nbsp;&nbsp;I - contains initialized 
      data<BR>&nbsp;&nbsp;R - readable<BR>&nbsp;&nbsp;W - 
      writeable<BR><BR>上面描述此文件中存在3个段及每个段得信息,实际上我们的代码可以写入任何一个段,这里我选择“.text”段。<BR><BR>用如下代码得到一个PE格式可执行文件的头信息:<BR><BR>//writePE.cpp<BR><BR>#include 
      &lt;windows.h&gt;<BR>#include &lt;stdio.h&gt;<BR>#include 
      &lt;io.h&gt;<BR>#include &lt;fcntl.h&gt;<BR>#include 
      &lt;time.h&gt;<BR>#include &lt;SYS\STAT.H&gt;<BR><BR>unsigned char 
      writeline[18]={<BR>0x6a,0x40,0x6a,0x0,0x6a,0x0,0x6a,0x0,0xe8,0x01,0x0,0x0,0x0,0xe9,0x0,0x0,0x0,0x0<BR>};<BR><BR>DWORD 
      space;<BR>DWORD entryaddress;<BR>DWORD entrywrite;<BR>DWORD 
      progRAV;<BR>DWORD oldentryaddress;<BR>DWORD newentryaddress;<BR>DWORD 
      codeoffset;<BR>DWORD peaddress;<BR>DWORD flagaddress;<BR>DWORD 
      flags;<BR><BR>DWORD virtsize;<BR>DWORD physaddress;<BR>DWORD 
      physsize;<BR>DWORD MessageBoxAadaddress;<BR><BR>int main(int argc,char * * 
      argv)<BR>{<BR>HANDLE hFile, hMapping;<BR>void *basepointer;<BR>FILETIME * 
      Createtime;<BR>FILETIME * Accesstime;<BR>FILETIME * 
      Writetime;<BR>Createtime = new FILETIME;<BR>Accesstime = new 
      FILETIME;<BR>Writetime = new FILETIME;<BR><BR>if ((hFile = 
      CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, 
      FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 
      FILE_FLAG_SEQUENTIAL_SCAN, 0)) == 
      INVALID_HANDLE_VALUE)//打开要修改的文件<BR>{<BR>puts("(could not 
      open)");<BR>return 
      EXIT_FAILURE;<BR>}<BR>if(!GetFileTime(hFile,Createtime,Accesstime,Writetime))<BR>{<BR>printf("\nerror 
      getfiletime: %d\n",GetLastError());<BR>}<BR>//得到要修改文件的创建、修改等时间<BR>if 
      (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 
      0, 0)))<BR>{<BR>puts("(mapping failed)");<BR>CloseHandle(hFile);<BR>return 
      EXIT_FAILURE;<BR>}<BR>if (!(basepointer = MapViewOfFile(hMapping, 
      FILE_MAP_READ, 0, 0, 0)))<BR>{<BR>puts("(view 
      failed)");<BR>CloseHandle(hMapping);<BR>CloseHandle(hFile);<BR>return 
      EXIT_FAILURE;<BR>}<BR>//把文件头映象存入baseointer<BR>CloseHandle(hMapping);<BR>CloseHandle(hFile);<BR>map_exe(basepointer);//得到相关地址<BR>UnmapViewOfFile(basepointer);<BR>printaddress();<BR>printf("\n\n");<BR>if(space&lt;50)<BR>{<BR>printf("\n空隙太小,数据不能写入.\n");<BR>}<BR>else<BR>{<BR>writefile();//写文件<BR>}<BR><BR>if 
      ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, 
      FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 
      FILE_FLAG_SEQUENTIAL_SCAN, 0)) == 
      INVALID_HANDLE_VALUE)<BR>{<BR>puts("(could not open)");<BR>return 
      EXIT_FAILURE;<BR>}<BR><BR>if(!SetFileTime(hFile,Createtime,Accesstime,Writetime))<BR>{<BR>printf("error 
      settime : %d\n",GetLastError());<BR>}<BR>//恢复修改后文件的建立时间等<BR>delete 
      Createtime;<BR>delete Accesstime;<BR>delete 
      Writetime;<BR>CloseHandle(hFile);<BR>return 0;<BR>}<BR><BR>void 
      map_exe(const void *base)<BR>{<BR>IMAGE_DOS_HEADER * dos_head;<BR>dos_head 
      =(IMAGE_DOS_HEADER *)base;<BR>#include &lt;pshpack1.h&gt;<BR>typedef 
      struct PE_HEADER_MAP<BR>{<BR>DWORD signature;<BR>IMAGE_FILE_HEADER 
      _head;<BR>IMAGE_OPTIONAL_HEADER opt_head;<BR>IMAGE_SECTION_HEADER 
      section_header[];<BR>} peHeader;<BR>#include &lt;poppack.h&gt;<BR><BR>if 
      (dos_head-&gt;e_magic != IMAGE_DOS_SIGNATURE)<BR>{<BR>puts("unknown type 
      of file");<BR>return;<BR>}<BR><BR>peHeader * header;<BR>header = (peHeader 
      *)((char *)dos_head + dos_head-&gt;e_lfanew);//得到PE文件头<BR>if 
      (IsBadReadPtr(header, sizeof(*header))<BR>{<BR>puts("(no PE header, 
      probably DOS executable)");<BR>return;<BR>}<BR><BR>DWORD mods;<BR>char 
      tmpstr[4]={0};<BR>DWORD&nbsp;&nbsp;tmpaddress;<BR>DWORD&nbsp;&nbsp;tmpaddress1;<BR><BR>if(strstr((const 
      char 
      *)header-&gt;section_header[0].Name,".text")!=NULL)<BR>{<BR>virtsize=header-&gt;section_header[0].Misc.VirtualSize;<BR>//此段的真实长度<BR>physaddress=header-&gt;section_header[0].PointerToRawData;<BR>//此段的物理偏移<BR>physsize=header-&gt;section_header[0].SizeOfRawData;<BR>//此段的物理长度<BR>peaddress=dos_head-&gt;e_lfanew; 
      <BR>//得到PE文件头的开始偏移<BR><BR>peHeader peH;<BR>tmpaddress=(unsigned long 
      )&amp;peH;<BR>//得到结构的偏移<BR>tmpaddress1=(unsigned long 
      )&amp;(peH.section_header[0].Characteristics);<BR>//得到变量的偏移<BR>flagaddress=tmpaddress1-tmpaddress+2;<BR>//得到属性的相对偏移<BR>flags=0x8000;<BR>//一般情况下,“.text”段是不可读写的,如果我们要把数据写入这个段需要改变其属性,实际上这个程序并没有把数据写入“.text”段,所以并不需要更改,但如果你实现复杂的功能,肯定需要数据,肯定需要更改这个值,<BR><BR>space=physsize-virtsize;<BR>//得到代码段的可用空间,用以判断可不可以写入我们的代码<BR>//用此段的物理长度减去此段的真实长度就可以得到<BR>progRAV=header-&gt;opt_head.ImageBase; 
      <BR>//得到程序的装载地址,一般为400000<BR>codeoffset=header-&gt;opt_head.BaseOfCode-physaddress;<BR>//得到代码偏移,用代码段起始RVA减去此段的物理偏移<BR>//应为程序的入口计算公式是一个相对的偏移地址,计算公式为:<BR>//代码的写入地址+codeoffset<BR><BR>entrywrite=header-&gt;section_header[0].PointerToRawData+header-&gt;section_header[0].Misc.VirtualSize;<BR>//代码写入的物理偏移<BR>mods=entrywrite%16;<BR>//对齐边界<BR>if(mods!=0)<BR>{<BR>entrywrite+=(16-mods);<BR>}<BR>oldentryaddress=header-&gt;opt_head.AddressOfEntryPoint;<BR>//保存旧的程序入口地址<BR>newentryaddress=entrywrite+codeoffset;<BR>//计算新的程序入口地址&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>return;<BR>}<BR><BR>void 
      printaddress()<BR>{<BR>HINSTANCE gLibMsg=NULL;<BR>DWORD 
      funaddress;<BR>gLibMsg=LoadLibrary("user32.dll"); 
      <BR>funaddress=(DWORD)GetProcAddress(gLibMsg,"MessageBoxA");<BR>MessageBoxAadaddress=funaddress;<BR>gLibAMsg=LoadLibrary("kernel32.dll"); 
      <BR>//得到MessageBox在内存中的地址,以便我们使用<BR>}<BR><BR>void writefile()<BR>{<BR>int 
      ret;<BR>long retf;<BR>DWORD address;<BR>int tmp;<BR>unsigned char 
      waddress[4]={0};<BR><BR>ret=_open(filename,_O_RDWR | _O_CREAT | 
      _O_BINARY,_S_IREAD | _S_IWRITE);<BR>if(!ret)<BR>{<BR>printf("error 
      open\n");<BR>return;<BR>}<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>retf=_lseek(ret,(long)peaddress+40,SEEK_SET);<BR>//程序的入口地址在PE文件头开始的40处<BR>if(retf==-1)<BR>{<BR>printf("error 
      seek\n");<BR>return;<BR>}<BR>address=newentryaddress;<BR>tmp=address&gt;&gt;24;<BR>waddress[3]=tmp;<BR>tmp=address&lt;&lt;8;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[2]=tmp;<BR>tmp=address&lt;&lt;16;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[1]=tmp;<BR>tmp=address&lt;&lt;24;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[0]=tmp;<BR>retf=_write(ret,waddress,4);<BR>//把新的入口地址写入文件<BR>if(retf==-1)<BR>{<BR>printf("error 
      write: 
      %d\n",GetLastError());<BR>return;<BR>}<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>retf=_lseek(ret,(long)entrywrite,SEEK_SET);<BR>if(retf==-1)<BR>{<BR>printf("error 
      seek\n");<BR>return;<BR>}<BR>retf=_write(ret,writeline,18);<BR>if(retf==-1)<BR>{<BR>printf("error 
      write: 
      %d\n",GetLastError());<BR>return;<BR>}<BR>//把writeline写入我们计算出的空间<BR><BR>retf=_lseek(ret,(long)entrywrite+9,SEEK_SET);<BR>//更改MessageBox函数地址,它的二进制代码在writeline[10]处<BR>if(retf==-1)<BR>{<BR>printf("error 
      seek\n");<BR>return;<BR>}<BR><BR>address=MessageBoxAadaddress-(progRAV+newentryaddress+9+4);<BR>//重新计算MessageBox函数的地址,MessageBox函数的原地址减去程序的装载地址加上新的入口地址加9(它的二进制代码相对偏移)加上4(地址长度)<BR>tmp=address&gt;&gt;24;<BR>waddress[3]=tmp;<BR>tmp=address&lt;&lt;8;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[2]=tmp;<BR>tmp=address&lt;&lt;16;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[1]=tmp;<BR>tmp=address&lt;&lt;24;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[0]=tmp;<BR>retf=_write(ret,waddress,4);<BR>//写入重新计算的MessageBox地址<BR>if(retf==-1)<BR>{<BR>printf("error 
      write: 
      %d\n",GetLastError());<BR>return;<BR>}<BR><BR>retf=_lseek(ret,(long)entrywrite+14,SEEK_SET);<BR>//更改返回地址,用jpm返回原程序入口地址,其它的二进制代码在writeline[15]处<BR>if(retf==-1)<BR>{<BR>printf("error 
      seek\n");<BR>return;<BR>}<BR><BR>address=0-(newentryaddress-oldentryaddress+4+15);<BR>//返回地址计算的方法是新的入口地址减去老的入口地址加4(地址长度)加15(二进制代码相对偏移)后取反<BR>tmp=address&gt;&gt;24;<BR>waddress[3]=tmp;<BR>tmp=address&lt;&lt;8;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[2]=tmp;<BR>tmp=address&lt;&lt;16;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[1]=tmp;<BR>tmp=address&lt;&lt;24;<BR>tmp=tmp&gt;&gt;24;<BR>waddress[0]=tmp;<BR>retf=_write(ret,waddress,4);<BR>//写入返回地址<BR>if(retf==-1)<BR>{<BR>printf("error 
      write: 
      %d\n",GetLastError());<BR>return;<BR>}<BR><BR>_close(ret);<BR>printf("\nall 
      done...\n");<BR>return;<BR>}<BR><BR>//end<BR>由于在PE格式的文件中,所有的地址都使用RVA地址,所以一些函数调用和返回地址都要经过计算才可以得到,以上是我在实践中的心得,如果你有更好的办法,真心的希望你能告诉我。<BR><BR>如果存在错误,请告诉我,以免误导看这篇文章的人。<BR>写的较乱,请原谅。<BR><BR>ilsy@netguard.com.cn 
    </TD></TR></TBODY></TABLE>
<DIV class=footer>Copyright &copy; 1998-2003 XFOCUS Team. All Rights Reserved 
</DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -