飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 8030|回复: 15

[分享] 菜鸟的PE结构学习之路(二) 初学PE头

[复制链接]
  • TA的每日心情
    开心
    2015-8-2 16:07
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-9-23 14:50:21 | 显示全部楼层 |阅读模式
    本帖最后由 F8LEFT 于 2014-9-23 17:22 编辑

       菜鸟在此,大牛飞过~~~~~~~
        以上仅为个人的一点小小的心得,有什么不对的地方还请各位指出。
          大家好,我是F8。继续的,我来水贴了,顺便骗分骗经验。啦啦啦,求别打我。
          上次我简单的介绍了DOS头,因为DOS头并不算重要,所以以后可能不会再提及了,有兴趣的请自行翻一下我前面的帖子(这不是打广告~~~)。

           那么,下面正式开始:

    ----------------------------------请叫我分割线-------------------------------------分割线-----------------------------------

         下面我们来玩一下PE头,不过在这之前,得先介绍一下相对偏移基址的概念。

         首先,来看一个长16,3的字符数组的定义:
         char Text[3][0x10];                                        //定义3个长0x10的字符串
         然后我要求在OD中手动定位这3个字符串,并写一个程序,动态修改它的内容。不难,对吧。好的,那么我们来找一下它的位置吧。
         于是,我用了下面的代码来显示他们的位置。
         cout<<" VA\tRVA"<<endl;
         char Text[3][0x10];                                        //定义3个长0x10的字符串
         for(int i = 0; i < 3; i++) {
               cout<<hex<<(DWORD)Text<<"\t+"<<hex<<(DWORD)(Text-Text[0])<<endl;                                      //显示字符的内存地址与相对偏移
         }

          4次运行结果:
    1.jpg    2.jpg    3.jpg    4.jpg

          奇怪了?明明是同一段代码,但是一运行起来,在内存中的地址却不一样,这是为啥?
          啧啧,OD中载入看一下原因。
          点开内存窗口,快捷键ALT+M,查一下模块的地址:

    5.jpg
    6.jpg
    7.jpg

          晕了,晕了,开了3次,每一次的程序装载的地址都不一样。。。
          其实,程序被装载到内存的地址叫做基址,像上面,10x1140000,200190000,300380000就被叫做基址了。而每次程序打开,都会被转载到不同的地址,这技术就叫做动态基址
          这就难办了,这字符串的地址都是会变化的,那么我要怎么去定位它呢?不对,再仔细看看,上面的运行图中,有几个数是不变的,就是那个叫做RVA的东西啦。那是字符串的地址间相减的结果,不变也正常。等等,既然是这样,如果用字符串的地址减去程序的基址,得到的结果还是一样的吗?我把程序做一点小小的修改:
          cout<<" VA\tRVA"<<endl;
         HMODULE hModuleBase =GetModuleHandle(NULL);
          for(int i = 0; i < 3; i++) {
          cout<<hex<<(DWORD)Text<<"\t+"<<hex<<(DWORD)(Text-(DWORD)hModuleBase<<endl;
          }

        DEBUG                                               RELEASE:
    8.jpg    9.jpg    10.jpg    11.jpg

          结果出来了,和我预想中的一样,字符串的地址减基址大小是不变的。这个便是RVA:相对偏移地址的概念。用来指出两个地方之间的地址差值。
          上面我分别用来Debug版本的和Release版本的做了演示,所以你会看到有两组RVA

          啰嗦了这么久,总算可以真正的开始了。上一次说到了DOS头,接下来我们就要从DOS头引入到PE头了。先复习一下:

    12.jpg
           图中,DOS尾部的最后4个字节的数据,IMAGE_DOS_HEADER.lfanew的数据指出了PE头的相对偏移。也就是说,对于文件来说,PE头的开始地址便是 00000000+000000C8 = 000000C8,如果加载到了内存中,基地址是00400000,那么PE头的开始地址就是004000C8。好了,直接跳到C8这个地方看一下吧。

    13.jpg

          这里便是PE头的一个大概了。具体的解析在下一遍文章介绍。现在先来简要的认识几个重要的参数:
          最外层的是一个IMAGE_NT_HEADERS,位于0xC8处,它定义如下:
    typedef struct _IMAGE_NT_HEADERS {
        DWORD Signature;                                                        //PE标志”PE\0\0”
        IMAGE_FILE_HEADER FileHeader;                                //基本的文件头
        IMAGE_OPTIONAL_HEADER32 OptionalHeader;                //扩展文件头
    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
           所以,它的第一个参数是IMAGE_NT_HEADERS.signature,固定为 “PE\0\0”, 0x50, 0x45, 0x00, 0x00。呵呵,就是PE头的标识了,因此想快速找PE头,认准这个参数就可以。。
           然后第二个参数, IMAGE_FILE_HEADER,是标准文件头,长0x14,与signature加起来为0x18,恰好占1行半,请记住这个。这里我特别的标志了它的倒数第二个参数,IMAGE_FILE_HEADER.SizeOfOptionalHeader。正如名字一样,是标志出扩展头的大小的。因为扩展头的长度是可变的,所以。。。这里的值为 00E0,于是,扩展头的大小也为0xE0,挺好看的吧。
           最后是第三个参数IMAGE_OPTIONAL_HEADER,俗称扩展头,关于PE文件的大部分信息都可以在这里找到,可以说,这个部分是最为重要的。起始位置为PE头+0x18的地方,请记住了。
            啰啰嗦嗦地写了这么多,就暂且打住吧,准备下节开始才正式的讲解PE头,感谢大家的支持啊,啦啦啦。
    第一篇传送门
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-8-23 23:49
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    发表于 2014-9-23 15:35:31 | 显示全部楼层
    前排学习。。。坐下沙发!

    点评

    感谢支持  详情 回复 发表于 2014-9-23 17:22
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-8-2 16:07
  • 签到天数: 2 天

    [LV.1]初来乍到

     楼主| 发表于 2014-9-23 17:22:41 | 显示全部楼层
    GGLHY 发表于 2014-9-23 15:35
    前排学习。。。坐下沙发!

    感谢支持
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    4 天前
  • 签到天数: 1515 天

    [LV.Master]伴坛终老

    发表于 2014-9-24 13:52:52 | 显示全部楼层

    顶起

    支持,定期啊...我要学.....求大腿.........
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2019-8-6 08:15
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-9-24 23:28:11 | 显示全部楼层
    定期啊...我要学.
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2015-1-9 10:32:07 | 显示全部楼层
    顶起,,,,谢谢作者。
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-9-18 09:23
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2015-1-22 09:01:57 | 显示全部楼层
    学习一下,感谢分享了
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表