zoukankan      html  css  js  c++  java
  • 【原创】编程获取PE文件信息的方法(转)

    标 题: 【原创】编程获取PE文件信息的方法
    作 者: xhK
    时 间: 2008-12-20,22:24
    链 接: http://bbs.pediy.com/showthread.php?t=79108

    前几天,一个学习破解的同学问我一个问题:pe文件的入口点是怎么获取的。我就给他说了一些pe文件格式的东西,并用C编程实现获取了OEP,想想可能很多新手也有此问题,于是就写点东西出来,希望对初学者有所帮助吧

     pe文件的相关内容,看雪论坛上有很多资料的http://www.pediy.com/Document.htm 还有一些pe文件的结构图,望初学者一定看下,对您的学习会有很大的帮助的。 我在这里只写一些常用的pe结构信息了,建议大家结合着详细的pe结构图(http://www.pediy.com/document/PE.rar)看此文章。

    今天,我以获取pe文件的oep为例,介绍一个获取pe文件信息的方法,当然只是一个比较笨的方法,一般笨的都是不需要很多知识的,应该符合初学者的口味吧

    为了便于大家阅读本文,我也做了个几个简单的图片,希望可以对大家有所帮助。
    看下面这个图片
     名称:  1.gif
查看次数: 264
文件大小:  10.3 KB
    这个是对配pe文件头的简单展开,信息并不全,本文只讨论oep的获取,其他信息的获取和此法一样,大家要学会举一反三,相信大家都有这个能力。

    也许有人会认为获取pe文件信息不会很简单,因为pe文件是二进制的。其实不然,虽然是二进制的,但毕竟是硬盘上的数据,只要有数据,我就可以读取呀,二进制的确难搞,但是我们可以转换下,转换成我们能够看懂的不就行了。
    在说方法之前,大家先看下面这个图片,这pe是我自己写的,弹出一个对话框的程序。
     名称:  2.gif
查看次数: 262
文件大小:  12.5 KB
    可以看到里面有MZ 、PE,分别是DOS头标志和PE头标志,还有几个段(也就是节区)的标记。从中可以知,有些信息我们还可以从记事本里看得到的,我们甚至可以直接在记事本里修改一些信息而不会破坏程序的运行,然由于编码问题,大多数情况下会破坏pe文件的结构,从而导致pe文件无法正确地执行。

    好了其他方面的不多说了,现在专心点吧,只说下oep的获取,我把原理画成了一张图,大家可以先看图,图后来解释。
     名称:  3.gif
查看次数: 262
文件大小:  10.0 KB
    其实在第一个图中我就画出了,获取oep的方法,下面分析下
    Oep是保存在AddressOfEntryPoint里面的,这个是OptionalHeader中的一个成员,OptionalHeader是pe头的中的一个成员,所以只要获取了pe头peHeader,那么(peHeader.OptionalHeader).AddressOfEntryPoint就是oep的值了,而pe头怎么获取呢,在dos头中有一个e_lfanew里面保存的是pe头的地址,那么就要获得dos头,那么dos头该怎么获取呢?如果你也有这样问,而且没有想到答案的话,可以知道,你的编程水平的确有待提高,或者要多写点代码了。
    这和我那个同学当时问的一样,我就有笑了。
    Dos头是打开文件的首指针指的就是dos头的标志信息的第一个字符M,所以dos头就不用定位了,打开一个pe文件,指针指的就是dos头了。所以我们的方法可分一下几个步骤(结合上图):
    1.  打开一个pe文件
    2.  把从dos头起始复制长度为sizeof(dos头)的数据,然后写到一个IMAGE_DOS_HEADER结构的变量中,再次命名为dosHeader.
    3.  读取dosHeader.elfanew的值,这是pe头的地址,有了起始地址,用和获取dosHeader同样的方法获取pe头信息。
    4.  最后获取oep信息。

    代码如下:
    #include <stdio.h>
    #include <windows.h>

    void main(int m,char *args[])
    {
      char *fileName=args[1];
      HANDLE hFile=CreateFile(fileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);

      if(hFile==INVALID_HANDLE_VALUE)
      {
        printf("Open error\n");
        return;
      }

      IMAGE_DOS_HEADER dosHeader;
      BOOL bRet;
      DWORD readSize;
      bRet=ReadFile(hFile,&dosHeader,sizeof(dosHeader),&readSize,NULL);
      if(!bRet)
      {
        printf("Read Error!\n");
        CloseHandle(hFile);
        return;
      }
      printf("%X\n",dosHead.e_lfanew);

      IMAGE_NT_HEADERS peHeader;
      SetFilePointer(hFile,dosHead.e_lfanew,NULL,FILE_BEGIN);
        bRet=ReadFile(hFile,&peHeader,sizeof(peHeader),&readSize,NULL);
      if(!bRet)
      {
        printf("Read Error!\n");
        return;
        CloseHandle(hFile);
      }

      IMAGE_OPTIONAL_HEADER32 imOpHeader;
      imOpHeader=peHeader.OptionalHeader;

      printf("%X\n",imOpHeader.AddressOfEntryPoint);
      CloseHandle(hFile);
      
    }
    编译环境:visual C++ 6.0
    在我的xp sp3上运行情况如下:
    此图已经缩小,点击察看原图。
    查看C:\1.exe的oep,获取的和OD的是一致的,说明方法是正确的。还有一种方法是从内存镜像中获取,对初学者来说会有一定的难度,就先不讨论了

    如果你有些函数看不明白,可以看微软的msdn,建议看英文的,全!以前在中文的上面找,很多东西都找不到,在英文版生都能够找的到。

    这个仅获取了pe文件的oep,你可以用此方法获取pe文件的其他信息,还是那句话,要举一反三了。熟能生巧。

    在此感谢一个同学帮我整理了图片。

    大家有问题可以和我交流下。
  • 相关阅读:
    《Java课程实习》日志(周二)
    spring helloworld
    [Android L or M ]解除SwitchPreference与Preference的绑定事件
    Smobiler实现列表展示—GridView(开发日志十二)
    LA 4329(树状数组)
    CreateDialog Win32 API调用的一个小问题
    Android Gallery2源代码分析
    你男朋友是程序猿吧
    javaEE之--------统计站点在线人数,安全登录等(观察者设计模式)
    AppFuse 3常见问题与解决方法
  • 原文地址:https://www.cnblogs.com/feng801/p/1386892.html
Copyright © 2011-2022 走看看