PE格式分析_3(IMAGE_FILE_HEADER)
本文最后更新于 280 天前,其中的信息可能已经有所发展或是发生改变。

pe格式代码,分析PE header

#include <stdio.h>
#include <Windows.h>

//#include <winnt.h>  // 定义了pe结构体的所有成员

int main()
{
    /******************************* Dos header ************************************/
    IMAGE_DOS_HEADER Header;  // Dos头

    /******************************* PE header ************************************/
    //IMAGE_FILE_HEADER peHeader;  // 新的文件格式从这里开始,并开始区分32和64位程序,但是文件头被NT头包含
    IMAGE_NT_HEADERS32 NTHeader;   // IMAGE_NT_HEADERS32  IMAGE_NT_HEADERS64   NT头(PE)

    // NT头包含:
    {
        IMAGE_FILE_HEADER FileHeader; // 文件头,保存文件信息
        IMAGE_OPTIONAL_HEADER32 OptionalHeader; // 选项头,存放程序信息

         // 选项头包含:
        {
            IMAGE_DATA_DIRECTORY DataDirectory[1]; // 数据目录,存放各种表,放1个表就增加1项
        }
    }

    /******************************* Section header ************************************/
    IMAGE_SECTION_HEADER SectionHeader[1]; //节表,存放段信息,描述映射信息,描述可执行文件在内存中怎么放
    // 节数据 ...                          // 节表和节数据 描述文件中的所有数据如何映射到内存

    /******************************* Debug information and certificates ************************************/
    // ....

    printf("IMAGE_DOS_HEADER: size %d\n", sizeof(IMAGE_DOS_HEADER));  //dos的大小
    //IMAGE_FILE_MACHINE_ALPHA64

    return 0;
}

IMAGE_NT_HEADERS

IMAGE_NT_HEADERS32 接下来这个结构体如何区分32或64位并解析?
发现这两个结构体,只有最后一结构体成员个区分32和64

typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

第一个成员:

DWORD Signature; 这个字段是固定的;
操作系统识别PE格式,就是开头的"MZ"和这里的字段;
宏定义: #define IMAGE_NT_SIGNATURE 0x50450000 // PE00

file

第二个成员:

IMAGE_FILE_HEADER:描述磁盘上PE文件的相关信息

 // 文件头结构体 20B: _IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER {
  WORD  Machine;                // ***** 表示CPU平台,不可修改:
                                // 32位IMAGE_FILE_MACHINE_I386, 0x014c
                                // 64位IMAGE_FILE_MACHINE_AMD64, 0x8664
  WORD  NumberOfSections;       // ***** 表示段的个数
                                //IMAGE_SECTION_HEADER SectionHeader[];  可以决定这里有几项 
                                // 遍历节表经验:根据此处的个数拿对应的节表数据
  DWORD TimeDateStamp;          // 时间戳:链接器填写的文件生成的时间,作用不大(可修改)
  DWORD PointerToSymbolTable;   // 调试信息,微软调试用pdb,这里给别的操作系统用的
  DWORD NumberOfSymbols;        // 符号表个数:windows的符号表信息一般由PDB放置在文件后端(无用)
  WORD  SizeOfOptionalHeader;   // ***** 这是选项头大小:用于定位节表位置=选项头地址+选项头大小(不可随便修改)
  WORD  Characteristics;        // ***** 决定文件属性,指应用程序是一个什么程序(不可随便修改),如:dll、console....
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

第一个字段: Machine , 这里支持的真多,014c表示32位程序

file

file


小知识:
64位cpu 个人用户电脑是AMD
服务器上用的是inter IA 安腾,因为inter的64位cpu是全新架构,不兼容旧32位程序,所以没有发展起来,提起64位,用的都是AMD的;

如果是32位程序,我想把这个标志位改成64位程序会怎么样?
欺骗,不能运行, 那怎么做呢?
方式:卖出去就说是64位,运行的时候偷偷改成32位,运行退出再改回64位; 自古套路得人心啊;这样在反汇编也具有欺诈性
对抗: 有的三线产品是直接拿C8的偏移的,这里可以删掉一部分,把C8偏移改改,三线产品直接崩溃

第二个字段: NumberOfSections
IMAGE_SECTION_HEADER SectionHeader[]; 这个节表的最后一项是0
有的软件遍历数组,遍历到0结束,把PE中这个位置随便改一下,其他软件打开就蹦
这个数量很重要,遍历程序有几个段,一定要先拿这个段数量,调试器就是遍历节表来获取几个段的;

可以给软件增加一个段,软件运行的时候,把自己的代码也运行了;

最后一个字段:Characteristics
这个是组合使用的

反调试:****
如果只使用IMAGE_OPTIONAL_HEADER32结构体来获取节的数量,会导致一调试就崩溃,应该从文件头里获取选项头的大小,OD犯了这个错误;


欺骗的最高艺术,让一切看起来和真的一样;


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇