【问题标题】:How can I obtain a PE file's instructions using Python?如何使用 Python 获取 PE 文件的指令?
【发布时间】:2015-06-26 13:43:34
【问题描述】:

所以我正在尝试使用 Python 为学校项目编写一个基本的反汇编程序。我正在使用 pydasm 和 capstone 库。我不明白的是如何使用 Python 实际访问程序的汇编指令。这些库允许我反汇编指令,但我不知道如何在 Python 中访问程序的指令。谁能给我一些指导?

谢谢。

【问题讨论】:

    标签: python portable-executable capstone


    【解决方案1】:

    您应该对代码部分保持谨慎,因为代码部分的基础可能不仅仅包含代码(导入或只读数据可能存在于此位置)。

    开始反汇编的最佳方法是查看IMAGE_OPTIONAL_HEADER 中的AddressOfEntryPoint 字段,该字段指示PE 文件中的第一个执行字节(除非存在TLS,但这是另一个主题)。

    一个非常好的python浏览PE文件的库是pefile

    这是一个在程序入口点获取前 10 个字节的示例:

    #!/usr/local/bin/python2
    # -*- coding: utf8 -*-
    from __future__ import print_function
    import sys
    import os.path
    import pefile
    
    
    def find_entry_point_section(pe, eop_rva):
        for section in pe.sections:
            if section.contains_rva(eop_rva):
                return section
    
        return None
    
    
    def main(file_path):
        print("Opening {}".format(file_path))
    
        try:
            pe = pefile.PE(file_path, fast_load=True)
            # AddressOfEntryPoint if guaranteed to be the first byte executed.
            eop = pe.OPTIONAL_HEADER.AddressOfEntryPoint
            code_section = find_entry_point_section(pe, eop)
            if not code_section:
                return
    
            print("[+] Code section found at offset: "
                  "{:#x} [size: {:#x}]".format(code_section.PointerToRawData,
                                              code_section.SizeOfRawData))
    
            # get first 10 bytes at entry point and dump them
            code_at_oep = code_section.get_data(eop, 10)
            print("[*] Code at EOP:\n{}".
                  format(" ".join("{:02x}".format(ord(c)) for c in code_at_oep)))
    
        except pefile.PEFormatError as pe_err:
            print("[-] error while parsing file {}:\n\t{}".format(file_path,
                                                                  pe_err))
    
    if __name__ == '__main__':
        if len(sys.argv) < 2:
            print("[*] {} <PE_Filename>".format(sys.argv[0]))
        else:
            file_path = sys.argv[1]
            if os.path.isfile(file_path):
                main(file_path)
            else:
                print("[-] {} is not a file".format(file_path))
    

    只需将您的 PE 文件的名称作为第一个参数传递。

    在上面的代码中,code_at_oep 变量保存了入口点的前几个字节。您可以从那里将此字节传递给顶点引擎。

    请注意,这些第一个字节可能只是 jmpcall 指令,因此您必须遵循代码执行才能正确反汇编。正确反汇编程序仍然是计算机科学中的一个悬而未决的问题......

    【讨论】:

      【解决方案2】:

      这取决于您使用的操作系统。您对 Linux 还有一些其他问题,所以我假设您正在使用它。在 Linux 上,可执行文件通常采用 ELF 格式,因此您需要 python library to read that 或使用其他工具来提取所需的 ELF 文件部分。

      实际的指令存储在.text 部分中,因此如果您提取该部分的内容,那些应该是您要反汇编的原始字节。

      【讨论】:

      • 谢谢。你回答了我应该在你的回复结束时问的问题。我正在处理 PE 文件,您明确表示我正在寻找的是 .text 部分的转储。但是,在我的一生中,我无法在 pefile 库输出的所有信息中找到 .text 部分。
      • @AsaHunt 抱歉,我对 pefile 不是很熟悉。我将编辑您的问题以尝试吸引一些更合适的人。
      【解决方案3】:

      所以这是我的代码,它可以反汇编您的 exe 文件并以 x86 汇编语言为您提供输出,我使用了 pefilecapstone

      #!/usr/bin/python
      import pefile
      from capstone import *
      
      # load the target PE file
      pe = pefile.PE("/file/path/code.exe")
      
      # get the address of the program entry point from the program header
      entrypoint = pe.OPTIONAL_HEADER.AddressOfEntryPoint
      
      # compute memory address where the entry code will be loaded into memory
      entrypoint_address = entrypoint+pe.OPTIONAL_HEADER.ImageBase
      
      # get the binary code from the PE file object
      binary_code = pe.get_memory_mapped_image()[entrypoint:entrypoint+100]
      
      # initialize disassembler to disassemble 32 bit x86 binary code
      disassembler = Cs(CS_ARCH_X86, CS_MODE_32)
      
      # disassemble the code
      for instruction in disassembler.disasm(binary_code, entrypoint_address):
          print("%s\t%s" %(instruction.mnemonic, instruction.op_str))
      

      确保更改并提供正确的 exe 文件路径,您还需要指定要在第 15 行打印多少条指令。这里[entrypoint:entrypoint+100] 我只指定了 100 条指令,但您可以更改它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多