Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★相关的知识,希望对你有一定的参考价值。
一、完整代码示例
使用 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 ; 机器码 :53
length = 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()
pass
if __name__ == '__main__':
main()
二、执行结果
D:\\001_Develop\\022_Python\\Python39\\python.exe C:/Users/octop/PycharmProjects/ELF_Parser/main.py
Container({'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})
7
21
Container({'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': 20040, 'p_paddr': 20040, 'p_filesz': 444, 'p_memsz': 4568, 'p_flags': 6, 'p_align': 4096})
Container({'p_type': 'PT_DYNAMIC', 'p_offset': 15956, 'p_vaddr': 20052, 'p_paddr': 20052, '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': 20040, 'p_paddr': 20040, '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: .dynsym
header 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: .dynstr
header 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: .hash
header 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.dyn
header 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.plt
header 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: .plt
header 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: .text
header 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
三、博客资源
以上是关于Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向使用 Python 代码解析 ELF 文件 ( PyCharm 中创建 Python 程序 | 导入 ELFFile 库 | 解析 ELF 文件 )
Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编框架 | PyCharm 中导入 Capstone 反汇编框架 )
Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★
Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段
Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 反汇编二进制机器码 | 打印反汇编数据 )
Android 逆向Android 逆向方法 ( 静态逆向解析 | 函数调用分析 | 动态运行跟踪 | 运行日志分析 | 文件格式解析 | 敏感信息分析 | 网络信息监控 | 环境伪装模拟 )