【问题标题】:How to parse PE file dont use API如何解析PE文件不使用API
【发布时间】:2020-01-17 07:24:28
【问题描述】:

我根据这个article学习了如何解析PE文件

在本文中,他们使用现有的 API 和结构

现在我想自己重写一个程序,不调用api和可用的结构。阅读PE文件的一些信息如下图所示

我想问的是算法或开发人员是如何创建它们的。可以给我一些提示或链接吗? 我需要使用 fread() 和 fseek() 来逐一读取,对吧??

谢谢

编辑:哦,我很好奇,想了解更多

【问题讨论】:

  • 为什么要自己动手?它只是作为一种学习经验还是一种好奇心(这很好,但请在您的问题中添加一个注释)?还是您认为自己重写会解决其他问题?通常,这样的事情并不是微不足道的,并且取决于您将使用它,如果您自己编写它比使用现有 API 犯错误的机会更高。
  • 谢谢老兄,只是好奇,想了解更多。你能给我一些提示吗?
  • 文章中的程序没有使用任何现有的API,而只使用了反映PE头不同部分的现有结构。您需要知道的大部分内容都在文章中。您可以通过谷歌搜索诸如“Microsoft PE header”之类的内容来找到有关 PE 标头的更多信息。
  • 这个问题对于目前的网站来说太宽泛了。继续尝试,并在遇到任何困难时提出具体问题。

标签: c++ c parsing portable-executable


【解决方案1】:

一般有两种方法:

  • 如果您确定二进制格式将始终与相同架构上的相同二进制文件一起使用,则可以将数据读入内存并将其视为“指向结构的指针”。这很可能是原始作者实现它的方式。缺点是这段代码不能跨架构甚至编译器标志(结构中的填充、对齐等)移植。
  • 另一种更便携的方法是逐个读取数据条目。这导致大量代码与结构非常相似,但它是可移植的和通用的。这些类型的二进制文件格式通常与使用它们的代码一起发展,您可以简单地插入版本和 if 语句来改变它们的读取方式。

    例如,使用某知名开源项目的stream API,您将阅读前几个条目如下:

Common::SeekableReadStream * s = ...;
PIMAGE_DOS_HEADER d = new IMAGE_DOS_HEADER;
d->e_magic = s->readUint16LE();
d->e_cblp = s->readUint16LE();
d->e_cp = s->readUint16LE();
...

作为这两种方法之间的中间地带,我开始喜欢Kaitai struct,您可以在其中以声明性样式编写格式规范,并让其编译器为您生成结构定义以及要读取的代码(并写!)这些文件格式。

看看their gallery的相应摘录:

  mz_header:
    seq:
      - id: magic
        size: 2
      - id: last_page_extra_bytes
        type: u2
      - id: num_pages
        type: u2
      - id: num_relocations
        type: u2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-17
    • 1970-01-01
    • 2023-03-14
    • 2011-02-22
    • 1970-01-01
    • 2012-12-15
    相关资源
    最近更新 更多