记录Microcode
介绍
Microcode 是 hexrays 内部采用的介于机器代码与伪代码之间的一种中间表示语言(IR)。
Microcode 生成完成后,IDA 在 Microcode 的基础上生成 CTree。 CTree 是 IDA 内部用于表示 C语言伪代码的抽象语法树,IDA 也提供了大量 API 操作 CTree,可以实现一下伪代码展示方面的优化,例如删除某些节点等等。
Microcode 指令格式
opcode left, right, destination
一般来说有三个操作数,有一些指令可能缺少某个操作数,destination 也不一定会被修改(Store 指令)
Microcode 中常见的数据结构
函数是 IDA 中最大的汇编结果表示单位
函数 → 基本块 → 指令 → 操作数
Microcode 可视化插件
https://github.com/gaasedelen/lucid
Ctree 可视化插件
https://github.com/patois/HRDevHelper
Microcode生成过程:
生成 Microcode
变换 Microcode (例如优化)
局部变量分配
生成 CTree (CTree 是 IDA 用来表示伪代码的抽象语法树 AST)
优化 CTree
输出 CTree
Microcode 寄存器
microcode 的寄存器没有数量限制,物理寄存器往往会被直接映射到 microcode 寄存器,例如
- AL is mapped into al.1 (mreg number 8)
- AH is mapped into ah.1 (mreg number 9)
- EAX is mapped into eax.4 (mreg numbers 8-11)
- RSI is mapped into rsi.8
Microcode 分阶段生成, 最初阶段生成的代码非常冗余
Microcode 快速上手,手动调用 microcode 生成
import ida_hexrays
import idaapi
def print_microcode(func_ea):
maturity = ida_hexrays.MMAT_GLBOPT3
# maturity:
# MMAT_ZERO, //< microcode 不存在
# MMAT_GENERATED //< 已经生成的microcode
# MMAT_PREOPTIMIED //< 预先优化的pass已完成
# MMAT_LOCOPT //< local 本地每个基本块的优化已完成 control控制流图也就绪
# MMAT_CALLS //< 检测调用参数
# MMAT_GLBOPT1 //< 执行第一个全局优化pass
# MMAT_GLBOPT2 //< 大多数全局优化pass已完成
# MMAT_GLBOPT3 //< 完成所有的优化,microcode被修改
# MMAT_LVAR3 //< 分配所有的局部变量
hf = ida_hexrays.hexrays_failure_t()
pfn = idaapi.get_func(func_ea)
rng = ida_hexrays.mba_ranges_t(pfn)
mba = ida_hexrays.gen_microcode(rng,hf,None,
ida_hexrays.DECOMP_WARNINGS,maturity)
vp = ida_hexrays.vd_printer_t()
mba._print(vp)
print_microcode(0x1229)
Microcode 相关的数据结构,定义在 hexrays.hpp 文件
Microcode 相关的数据结构: mbl_array_t,这个结构用来存放函数的基本块信息
- 基本块之间使用双向链表链接
- 基本块数组存放在 natural 数组
Microcode 相关的数据结构: mblock_t,这个结构用来描述基本块信息。±基本块内的指令与指令之间使用双向链表链接
Microcode 相关的数据结构: minsn_t。用于描述指令信息的结构。(注意微码指令支持指令嵌套。)
Microcode 相关的数据结构: mop_t
用于描述操作数信息的结构,指令 minsn_t 有 0 ~ 3 个操作数,分别时 l (left), r (right), d (destination) 操作数的类型用 mop_t 来表示
Microcode 插件例子
- 实现 svc 0x900001 与 svc 0x9000F8 指令反编译成一条 call 指令
- install_microcode_filter 注册 microcode filter 实现拦截指令翻译
- microcode filter 是一种可以拦截 microcode 指令生成的机制,开发者需要继承 microcode_filter_t 类并实现 match 与 apply 两个函数。
- ida 在生成某一条指令的 microcode 之前会调用所有已经注册的 filter 的 match 函数,若 match 函数返回 True,则调用对应的 apply 函数实现指令替换。
- 我们需要将 svc 指令替换成 call 指令,ida 已经为我们实现了替换类 udc_filter_t, 这个类继承于 microcode_filter_t 并实现了 apply 方法(即替换call指令),我们需要继承 udc_filter_t 并实现它的 match 方法用于判断拦截的指令。
Microcode 插件例子
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com