capstone x86 python非官方文档
capstone是一个非常轻量易用的反汇编引擎,拥有非常简洁的API,支持多平台多语言
本文档仅涉及python和x86架构
安装
从pip安装
1 |
|
从pip更新
1 |
|
示例
先来看一段非常简短的反汇编示例
1 |
|
运行,输出为
1 |
|
Cs类
两个初始化参数,第一个参数arch
指定运行时宿主机架构(因为capstone的python实现本质上是ctypes调用动态库),第二个参数mode
指定反汇编模式
1 |
|
例如,将示例代码的模式更改为CS_MODE_86
,输出
1 |
|
将detail
成员变量设置为True可以获得更详细反汇编的内容
1 |
|
disasm方法
code
:要反汇编的二进制数据offset
:代码起始地址count
:反汇编数量,默认为0,为0则表示全部反汇编
返回生成器,可通过list()
将其转换为数组
1 |
|
例如,将示例代码的offset
更改为0,count
更改为3,运行
显而易见,只输出了3条,而且起始地址为0
1 |
|
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文档
都反汇编了,顺带把汇编的文档也写了(笑
从pip安装
1 |
|
从pip更新
1 |
|
这玩意用起来非常简单,都不需要文档,贴个代码瞪眼一看就懂了
1 |
|