【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★
生活随笔
收集整理的這篇文章主要介紹了
【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 ; 機器碼 :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.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
三、博客資源
GitHub : https://github.com/han1202012/ELF_Parser
總結
以上是生活随笔為你收集整理的【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 逆向】使用 Pytho
- 下一篇: 【Android 逆向】ELF 文件格式