文章目录
一、完整代码示例二、执行结果三、博客资源一、完整代码示例
使用 Python 解析 ELF 文件完整代码示例 :
# coding=utf-8# 解析 elf 文件需要导入的依赖库# 安装 pyelftools 库成功 , 安装 elftools 库会报错from elftools.elf.elffile import ELFFile# 导入 Capstone 反汇编框架 , 用于解析 ELF 文件from capstone import *def main():# 要解析的动态库路径elf_path = r'libwtcrypto.so'# 打开 elf 文件file = open(elf_path, 'rb')# 创建 ELFFile 对象 , 该对象是核心对象elf_file = ELFFile(file)# 打印 elf 文件头print(elf_file.header)# 打印 程序头入口 个数print(elf_file.num_segments())# 打印 节区头入口 个数print(elf_file.num_sections())# 遍历打印 程序头入口for segment in elf_file.iter_segments():print(segment.header)# 遍历打印 节区头入口for section in elf_file.iter_sections():print('name:', section.name)print('header', section.header)# 使用 Capstone 反汇编框架# 节区入口名称是 .text , 表示该节区数据是代码数据if section.name == '.text':# 获取节区地址file.seek(section.header['sh_addr'])# 获取节区大小sh_size = section.header['sh_size']# 读取 节区 二进制数据# 这是需要反汇编的机器码数据raw = file.read(sh_size)# 创建 Capstone 实例对象capstone = Cs(CS_ARCH_X86, CS_MODE_32)# 此处设置为 true , 表示需要显示细节 , 打开后 , 会标明每条汇编代码中对寄存器的影响# 如 : 本条汇编代码中 , 会读写哪些寄存器capstone.detail = True# 向汇编解析器中传入 节区数据 对应的 二进制数据 , 这些二进制数据都是机器码数据# 即 , 需要反汇编这些二进制数据为 汇编 代码# 第一个参数设置二进制数据# 第二个参数指的是读取 raw 二进制数据的起始地址 , 一般设置 0 即可# 得到的是反汇编后的汇编代码列表 , 如果反汇编失败 , 此处为空disasm = capstone.disasm(raw, 0)# 遍历反汇编代码列表for line in disasm:# 打印每行汇编代码的 地址 , 指令 , 操作对象text = '%08X: %s %s ' % (line.address, line.mnemonic, line.op_str)# 统计汇编代码行的字符串个数 , 保证在第 55 字节处打印寄存器读写信息# 00000000: push ebx ; 读寄存器:esp 写寄存器:esp ; 机器码 :53length = len(text)if length < 55:text += ' ' * (55 - length)text += ';'# 读取操作影响到的寄存器if hasattr(line, 'regs_read') and len(line.regs_read) > 0:text += ' 读寄存器:'for j, r in enumerate(line.regs_read):if j > 0:text += ','text += '%s' % line.reg_name(r)# 写出操作影响到的寄存器if hasattr(line, 'regs_write') and len(line.regs_write) > 0:text += ' 写寄存器:'for j, r in enumerate(line.regs_write):if j > 0:text += ','text += '%s' % line.reg_name(r)text += ' ; 机器码 :'# 打印 本条汇编代码对应的 机器码for i in range(line.size):text += '%02X ' % line.bytes[i]# 打印最终数据print(text)pass# 关闭文件file.close()passif __name__ == '__main__':main()
二、执行结果
D:\001_Develop\022_Python\Python39\python.exe C:/Users/octop/PycharmProjects/ELF_Parser/main.pyContainer({'e_ident': Container({'EI_MAG': [127, 69, 76, 70], 'EI_CLASS': 'ELFCLASS32', 'EI_DATA': 'ELFDATA2LSB', 'EI_VERSION': 'EV_CURRENT', 'EI_OSABI': 'ELFOSABI_SYSV', 'EI_ABIVERSION': 0}), 'e_type': 'ET_DYN', 'e_machine': 'EM_386', 'e_version': 'EV_CURRENT', 'e_entry': 0, 'e_phoff': 52, 'e_shoff': 16652, 'e_flags': 0, 'e_ehsize': 52, 'e_phentsize': 32, 'e_phnum': 7, 'e_shentsize': 40, 'e_shnum': 21, 'e_shstrndx': 20})721Container({'p_type': 'PT_PHDR', 'p_offset': 52, 'p_vaddr': 52, 'p_paddr': 52, 'p_filesz': 224, 'p_memsz': 224, 'p_flags': 4, 'p_align': 4})Container({'p_type': 'PT_LOAD', 'p_offset': 0, 'p_vaddr': 0, 'p_paddr': 0, 'p_filesz': 11872, 'p_memsz': 11872, 'p_flags': 5, 'p_align': 4096})Container({'p_type': 'PT_LOAD', 'p_offset': 15944, 'p_vaddr': 0, 'p_paddr': 0, 'p_filesz': 444, 'p_memsz': 4568, 'p_flags': 6, 'p_align': 4096})Container({'p_type': 'PT_DYNAMIC', 'p_offset': 15956, 'p_vaddr': 2, 'p_paddr': 2, 'p_filesz': 272, 'p_memsz': 272, 'p_flags': 6, 'p_align': 4})Container({'p_type': 'PT_GNU_EH_FRAME', 'p_offset': 11716, 'p_vaddr': 11716, 'p_paddr': 11716, 'p_filesz': 156, 'p_memsz': 156, 'p_flags': 4, 'p_align': 4})Container({'p_type': 'PT_GNU_STACK', 'p_offset': 0, 'p_vaddr': 0, 'p_paddr': 0, 'p_filesz': 0, 'p_memsz': 0, 'p_flags': 6, 'p_align': 0})Container({'p_type': 'PT_GNU_RELRO', 'p_offset': 15944, 'p_vaddr': 0, 'p_paddr': 0, 'p_filesz': 440, 'p_memsz': 440, 'p_flags': 6, 'p_align': 4})name: header Container({'sh_name': 0, 'sh_type': 'SHT_NULL', 'sh_flags': 0, 'sh_addr': 0, 'sh_offset': 0, 'sh_size': 0, 'sh_link': 0, 'sh_info': 0, 'sh_addralign': 0, 'sh_entsize': 0})name: .dynsymheader Container({'sh_name': 11, 'sh_type': 'SHT_DYNSYM', 'sh_flags': 2, 'sh_addr': 276, 'sh_offset': 276, 'sh_size': 832, 'sh_link': 2, 'sh_info': 1, 'sh_addralign': 4, 'sh_entsize': 16})name: .dynstrheader Container({'sh_name': 19, 'sh_type': 'SHT_STRTAB', 'sh_flags': 2, 'sh_addr': 1108, 'sh_offset': 1108, 'sh_size': 892, 'sh_link': 0, 'sh_info': 0, 'sh_addralign': 1, 'sh_entsize': 0})name: .hashheader Container({'sh_name': 27, 'sh_type': 'SHT_HASH', 'sh_flags': 2, 'sh_addr': 2000, 'sh_offset': 2000, 'sh_size': 364, 'sh_link': 1, 'sh_info': 0, 'sh_addralign': 4, 'sh_entsize': 4})name: .rel.dynheader Container({'sh_name': 33, 'sh_type': 'SHT_REL', 'sh_flags': 2, 'sh_addr': 2364, 'sh_offset': 2364, 'sh_size': 24, 'sh_link': 1, 'sh_info': 0, 'sh_addralign': 4, 'sh_entsize': 8})name: .rel.pltheader Container({'sh_name': 42, 'sh_type': 'SHT_REL', 'sh_flags': 2, 'sh_addr': 2388, 'sh_offset': 2388, 'sh_size': 280, 'sh_link': 1, 'sh_info': 6, 'sh_addralign': 4, 'sh_entsize': 8})name: .pltheader Container({'sh_name': 46, 'sh_type': 'SHT_PROGBITS', 'sh_flags': 6, 'sh_addr': 2672, 'sh_offset': 2672, 'sh_size': 576, 'sh_link': 0, 'sh_info': 0, 'sh_addralign': 16, 'sh_entsize': 4})name: .textheader Container({'sh_name': 51, 'sh_type': 'SHT_PROGBITS', 'sh_flags': 6, 'sh_addr': 3248, 'sh_offset': 3248, 'sh_size': 6327, 'sh_link': 0, 'sh_info': 0, 'sh_addralign': 16, 'sh_entsize': 0})00000000: push ebx ; 读寄存器:esp. 写寄存器:esp ; 机器码 :53 00000001: call 0xab; 读寄存器:esp,eip. 写寄存器:esp ; 机器码 :E8 A5 00 00 00 00000006: add ebx, 0x42b2;. 写寄存器:eflags ; 机器码 :81 C3 B2 42 00 00 0000000C: lea esp, [esp - 0x18] ; ; 机器码 :8D 64 24 E8 00000010: lea eax, [ebx + 0x98] ; ; 机器码 :8D 83 98 00 00 00 00000016: mov dword ptr [esp], eax ; ; 机器码 :89 04 24 00000019: call 0xfffffdf0; 读寄存器:esp,eip. 写寄存器:esp ; 机器码 :E8 D2 FD FF FF 0000001E: lea esp, [esp + 0x18] ; ; 机器码 :8D 64 24 18 00000022: pop ebx ; 读寄存器:esp. 写寄存器:esp ; 机器码 :5B 00000023: ret ; 读寄存器:esp. 写寄存器:esp ; 机器码 :C3 00000024: add byte ptr [eax], al ;. 写寄存器:eflags ; 机器码 :00 00 00000026: add byte ptr [eax], al ;. 写寄存器:eflags ; 机器码 :00 00 00000028: add byte ptr [eax], al ;. 写寄存器:eflags ; 机器码 :00 00 0000002A: add byte ptr [eax], al ;. 写寄存器:eflags ; 机器码 :00 00 0000002C: add byte ptr [eax], al ;. 写寄存器:eflags ; 机器码 :00 00 0000002E: add byte ptr [eax], al ;. 写寄存器:eflags ; 机器码 :00 00 00000030: lea esp, [esp - 0xc]; ; 机器码 :8D 64 24 F4 00000034: mov eax, dword ptr [esp + 0x10] ; ; 机器码 :8B 44 24 10 00000038: test eax, eax ;. 写寄存器:eflags ; 机器码 :85 C0 0000003A: je 0x3e ; 读寄存器:eflags ; 机器码 :74 02 0000003C: call eax ; 读寄存器:esp. 写寄存器:esp ; 机器码 :FF D0
三、博客资源
GitHub :/han120/ELF_Parser
【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★