Python中capstone实现反汇编可执行文件

1、基本案例——disasm函数

capstone有非常简单的API,所以使用该框架编写工具非常简单。接下来,下面的代码实现的功能是反汇编一些X86二进制文件,并打印出其对应的汇编语句。

代码展示:

from capstone import *  #将capstone模块中函数全部导入
code=b"\x55\x48\x8b\x13\x00\x00"  #设置需要进行反汇编的十六进制机器码
​
#创建Cs类对象md,我们需要给这个类传两个参数:硬件架构,硬件模式(位长)
md=Cs(CS_ARCH_X86,CS_MODE_64) #表示此时md对象对采用x86架构64位,对机器码进行汇编
​
for i in md.disasm(code,0x1000): #循环遍历disasm函数返回的列表
    print("0x%x:\t %s\t%s" %(i.address,i.mnemonic,i.op_str))

代码解释:(此时的行数是不计注释和空行)

代码的前两行的作用分别是导入模块中需要使用的函数(或类)和设置需要进行反汇编的机器码。第三的作用是为Cs类创建一个类对象md,便于在后续代码中调用Cs类中定义的方法。

反汇编二进制文件(机器码)实际上使用的是Cs类中定义的成员函数disasm()。因为我们在代码的第三行已经初始了一个类对象md,所以当我们要使用disasm()这个函数的时候,直接使用类对象调用即可---md.disasm()。disasm需要传两个参数:

①第一个参数:需要进行反汇编的机器码;

②第二个参数:反汇编的开始地址,默认情况下,disasm会反汇编传入的所有机器码,直到没有代码或断开为止。本例中,第二个参数设置为0x1000。

disasm函数的执行完成后,会返回一个CsInsn类的指令列表。

代码的第四行使用for循环遍历disasm函数返回的列表,第五行打印该指令的一些内部信息。

执行结果:

类CsInsn公开了我们要访问的反汇编指令的所有内部信息。以下是一些常用的字段: id 汇编指令的id

address 汇编指令的地址

mnemonic 指令的助记符

op_str 汇编指令的操作码

size 汇编指令的大小,以字节为单位

bytes 指令的字节序列

验证代码如下:

2.更精简的API——disasm_lite函数

刚刚我介绍了capstone模块中的Cs类中的成员函数disasm()。这个函数处理后会返回一个CsInsn类列表。返回结果提供了反汇编指令的全部可用信息。但是当我只需要汇编代码的基本信息,如:地址、大小、助记符等基本的数据,我们可以使用disasm_lite()函数,该函数返回一个元组,元组包括:地址、大小、助记符、op_str。这个函数的执行速度相比于disasm函数会更快。

代码展示:

from capstone import *
code=b"\x55\x48\x8b\x13\x00\x00"
md=Cs(CS_ARCH_X86,CS_MODE_64)
for (address,size,mnemonic,op_str) in md.disasm_lite(code,0x1000):
    print("0x"+str(address),size,mnemonic,op_str)

运行结果:

3、对可执行文件的.text节进行反汇编,且将反汇编内容保存到huibain.txt文件中:

具体代码:

from capstone import *  # 导入Capstone库,用于反汇编
import pefile  # 导入PE文件解析库

def FOA_Disassembly(FilePath):
    global VirtualAddress,VirtualSize,ActualOffset
    pe = pefile.PE(FilePath)  # 解析PE文件
    ImageBase = pe.OPTIONAL_HEADER.ImageBase  #从pe文件对象中获取可选头部(OPTIONAL_HEADER)中的ImageBase字段,并将其赋值给变量
    #pe对象中的ImageBase字段通常用来指定可执行文件中加载时的基地址,
    #这个值可以影响程序在内存中的加载位置。
    # 通过获取Imagebase字段的值,可以了解程序在加载时的首先基地址

   #PE对象中的sections属性,用于获取PE文件中的各个节。
    for item in pe.sections:
        #当从外部数据源读取数据时,数据通常以字节流的形式表示。
        #Python中decode函数用于将字节流解码为字符串,本次实验中解码后的字符串以UTF-8进行编码
        if str(item.Name.decode('UTF-8').strip(b'\x00'.decode())) == ".text":  # 查找包含代码的节
            VirtualAddress = item.VirtualAddress  # 节的虚拟地址
            VirtualSize = item.Misc_VirtualSize  # 节的虚拟大小
            ActualOffset = item.PointerToRawData  # 节在文件中的偏移量

    StartVA = ImageBase + VirtualAddress  # 起始虚拟地址
    StopVA = ImageBase + VirtualAddress + VirtualSize  # 结束虚拟地址
    with open(FilePath, "rb") as fp:
        #Python中seek函数的作用:移动文件读写指针到指定的偏移量位置
        fp.seek(ActualOffset)
        HexCode = fp.read(VirtualSize)  # 读取.text节中的信息,使用read函数读取.text大小byte的信息

    md = Cs(CS_ARCH_X86, CS_MODE_32)  # 初始化Capstone引擎,指定架构和模式
    with open("./huibain.txt","a",encoding="utf-8") as f:
        for item in md.disasm(HexCode, 0):  # 反汇编节中的代码
            addr = hex(int(StartVA) + item.address)  # 计算指令的虚拟地址
            dic = {"Addr": str(addr), "OpCode": item.mnemonic + " " + item.op_str}  # 构建指令信息字典
            f.write(dic["Addr"]+" "+dic["OpCode"])
            f.write("\n")

if __name__ == "__main__":
    ref = FOA_Disassembly("./test.exe")  # 调用函数解析指定的可执行文件
    print("转换完成!请查看当前目录下,huibain.txt文件")  # 打印反汇编结果

运行成功截图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值