capstone x86 python非官方文档

capstone是一个非常轻量易用的反汇编引擎,拥有非常简洁的API,支持多平台多语言

本文档仅涉及python和x86架构

安装

从pip安装

1
pip install capstone

从pip更新

1
pip install capstone --upgrade

示例

先来看一段非常简短的反汇编示例

1
2
3
4
5
6
7
8
9
from capstone import *
from capstone.x86 import *

CODE = b"\x55\x48\x8B\x05\xB8\x13\x00\x00\x48\x39\xC3\x74\x03\x48\x31\xC0\xC3"

md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
for i in md.disasm(CODE, 0x1000):
    print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

运行,输出为

1
2
3
4
5
6
0x1000: push rbp
0x1001: mov rax, qword ptr [rip + 0x13b8]
0x1008: cmp rbx, rax
0x100b: je 0x1010
0x100d: xor rax, rax
0x1010: ret

Cs类

两个初始化参数,第一个参数arch指定运行时宿主机架构(因为capstone的python实现本质上是ctypes调用动态库),第二个参数mode指定反汇编模式

1
2
3
class Cs(object):
    def __init__(self, arch, mode):
    #...

例如,将示例代码的模式更改为CS_MODE_86,输出

1
2
3
4
5
6
7
8
9
0x1000: push ebp
0x1001: dec eax
0x1002: mov eax, dword ptr [0x13b8]
0x1008: dec eax
0x1009: cmp ebx, eax
0x100b: je 0x1010
0x100d: dec eax
0x100e: xor eax, eax
0x1010: ret

detail成员变量设置为True可以获得更详细反汇编的内容

1
md.detail = True

disasm方法

code:要反汇编的二进制数据
offset:代码起始地址
count:反汇编数量,默认为0,为0则表示全部反汇编

返回生成器,可通过list()将其转换为数组

1
2
def disasm(self, code, offset, count=0):
#...

例如,将示例代码的offset更改为0,count更改为3,运行
显而易见,只输出了3条,而且起始地址为0

1
2
3
0x0: push ebp
0x1: dec eax
0x2: mov eax, dword ptr [0x13b8]

ModR/M字节、REX字节、SIB字节和SIB寻址

ModR/M字节用于指定指令的操作数和寻址模式,由mod(2位),reg/opcode(3位),和rm(3位)三部分组成

  • mod:指定寻址模式
    • 00:寄存器间接寻址或直接内存寻址
    • 01:8位偏移寄存器间接寻址
    • 10:32位偏移寄存器间接寻址
    • 11:寄存器直接寻址
  • reg/opcode:指定寄存器或操作码扩展
  • rm:指定寄存器或内存操作数

SIB(Scale-Index-Base)寻址使用segment:[base + index * scale + displacement]表示

例如mov ecx, ds:[eax + ebx * 4 + 16]ds是段寄存器(segment)(准确一点应该叫段选择子,因为现代x86架构中段寄存器存放的不是真的段地址),eax是基址寄存器(base),ebx是索引寄存器(index),4是比例因子(scale),16是位移(displacement)

SIB寻址看起来长,原始二进制数据就1字节大(就是所谓的SIB字节),格式SSIIIBBB

  • SS(Scale):比例因子(1, 2, 4, 8)
  • III(Index):索引寄存器
  • BBB(Base):基址寄存器

REX字节用于扩展寄存器和操作数的位数,格式为 `0100 WRXB

  • 0100:是常量魔数
  • W:指定操作数大小,1为64位,0为32位
  • R:扩展ModR/M字节中的reg/opcode字段
  • X:扩展SIB字节中的Index字段
  • B:扩展ModR/M字节中的rm字段或SIB字节中的Base字段

很复杂,但是了解就行,capstone都已经解析好了,就在CsInsn类的operands中

CsInsn类

disasm返回的生成器用来生成CsInsn类

成员变量 类型 说明
addr_size int 地址大小,该值固定,取决于反汇编模式:32位是4,64位是8
address int 指令地址
avx_cc int AVX指令的条件码(Condition Code)
avx_rm int AVX指令浮点运算的舍入模式(Rounding Mode)
avx_sae bool AVX指令的SAE(Suppress All Exceptions)标志,控制浮点运算是否抛出异常
bytes bytearray 指令的原始二进制数据
disp int SIB位移(displacement)
disp_offset int SIB位移在指令中的位置
disp_size int SIB位移大小
eflags int 该指令可能会修改的eflags标志,由X86_EFLAGS_*枚举,例如cmp指令该值为0011 1111,代表会修改AF CF SF ZF PF OF标志
encoding CsX86Encoding 包含disp_offset disp_size imm_offset imm_size modrm_offset
fpu_flags int 该指令可能会修改的浮点单元(Floating Point Unit)标志,由X86_FPU_FLAGS_*枚举
groups List[int] 指令所属的组,由X86_GRP_*枚举,例如和分支相关的指令为X86_GRP_BRANCH_RELATIVE
id int 指令的id,由X86_INS_*枚举,例如460是X86_INS_MOV
imm_offset int 立即数在指令中的位置
imm_size int 立即数的字节大小
menmonic str 指令字符串,例如”mov”
modrm int ModR/M字节
modrm_offset int ModR/M字节在指令中的位置
op_str str 操作数字符串,例如”rax, qword ptr [rip + 0x13b8]“
opcode List[int] 操作码
operands List[X86Op] 操作数类
prefix List[int] 前缀,用于切换操作数大小、指定段寄存器等
regs_read List[int] 读取的寄存器,由X86_REG_*枚举,例如35是X86_REG_RAX
regs_write List[int] 写入的寄存器,同上
rex int REX字节
sib int SIB字节
sib_base int SIB基址寄存器(base)
sib_index int SIB索引寄存器(index)
sib_scale int SIB比例因子(scale)
size int 指令原始二进制数据的长度
sse_cc int SSE指令的条件码
xop_cc int XOP指令的条件码

X86Op类(操作数类)

成员变量 类型 说明
access int 指令对内存或寄存器的访问模式,是读取(CS_AC_READ)还是写入(CS_AC_WRITE)
avx_bcast int AVX指令广播模式,由CS_AVX_BCAST_*枚举
avx_zero_opmask bool AVX指令是否使用零掩码(好像只有AVX-512支持),也就是是否将掩码寄存器中未选中的元素置零
imm int 如果操作数是立即数,该值就是该立即数
mem X86OpMem 如果操作数是内存,该类存放的就是SIB寻址内容
mem.base int SIB基址寄存器(base)
mem.disp int SIB位移(displacement)
mem.index int SIB索引寄存器(index)
mem.scale int SIB比例因子(scale)
mem.segment int SIB段选择子(segment)
reg int 如果操作数是寄存器,该值就是该寄存器
size int 操作大小,比如al是1,ax是2,eax是4,rax是8
type int 操作数类型,是立即数(X86_OP_IMM)还是寄存器(X86_OP_REG)还是内存(X86_OP_MEM)
value X86OpValue 包含mem imm reg

keystone文档

都反汇编了,顺带把汇编的文档也写了(笑

反汇编用capstone,那么汇编就要用到keystone

从pip安装

1
pip install keystone-engine

从pip更新

1
pip install keystone-engine --upgrade

这玩意用起来非常简单,都不需要文档,贴个代码瞪眼一看就懂了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from keystone import *

instructions_str="""
push rbp
mov rax, qword ptr [rip + 0x13b8]
cmp rbx, rax
je LABEL_1
xor rax, rax
LABEL_1:
ret
"""

try:
encoding, count = Ks(KS_ARCH_X86, KS_MODE_64).asm(instructions_str)
with open("output.bin", "wb") as f:
f.write(bytes(encoding))
except KsError as e:
print("编译错误:%s" % e)

capstone x86 python非官方文档
https://crackme.net/articles/man_capstone/
作者
Brassinolide
发布于
2025年2月6日
许可协议