
"""
这个寄存器是做什么用的?
嗯……我就把它重命名为 veryuniquename,然后做个文本搜索,找到所有引用!
好的……等待搜索结束……马上就好……完成!
现在只需要理解搜索结果中哪些与当前寄存器的使用帧相关。
应该不难,对吧?
"""
如果你遇到过这种情况(或许不止一次),那你有福了!
只需按下 Shift-X,你的烦恼就会消失!
你也可以在使用的帧中重命名寄存器。只需按下 Shift-N,然后按照指示操作!
还有——与其逐个修改所有用法的类型,不如只按一次 Shift-T。
最后但同样重要的是——如果你想为这个寄存器的所有用法设置偏移量(就像做 Ctrl-R 一样),只需按下 Shift-R。
注意:有时已经有其他插件使用了 Shift-T。请卸载那个插件——反正你以前也没用过它 :-)。
该插件使用 sark 来方便地与 IDA 脚本交互,并使用 cachetools 来缓存帧扫描,从而大大加快速度。
Oregami 支持 IDA 7.x/8.x 以及 IDA 9.0+。
如果你使用 IDA 9,请确保安装了支持 IDA 9 的最新版 sark。
注意:IDA 9 引入了自己的 Shift-X 功能。如果你需要使用 IDA 内置的 Shift-X 而不是 oregami 的,你需要在插件文件中更改 oregami 的快捷键。
[对于 python3]
pip3 install sark
[对于 python2]
如果使用 IDA 的 python2 变体,则应运行:
pip2 install -U git+https://github.com/tmr232/[email protected]#egg=Sark
注意:python2 不再积极支持(因为 IDA 大多已迁移到 python3,我也是如此),所以这可能无法工作。
git clone https://github.com/shemesh999/oregami
sark 代码库提供了许多插件。其中之一是: https://github.com/tmr232/Sark/blob/master/plugins/plugin_loader.py
我们建议将其复制到你的插件目录,然后以管理员权限运行一次 IDA(以便它创建 plugins.list 文件)。
完成此操作后,你可以通过将新插件的路径添加到创建的某个 plugins.list 文件(例如,一个创建在 IDA 的 cfg 文件夹中)来添加新插件。
现在,将以下内容添加到其中一个 plugins.list 文件:
FULLPATH\oregami\oregami_plugin.py
FULLPATH\oregami\regname_plugin.py
FULLPATH\oregami\typeregter_plugin.py
FULLPATH\oregami\offreg_plugin.py
重启 IDA,插件应该可以工作了。
或者:
将所有文件(包括内部的 oregami 文件夹,不包括 setup.py)复制到 IDA 插件目录。
除了作为插件使用,oregami 还可以用来编写你自己的脚本!
为此,你应首先使用附带的 setup.py 文件进行安装。也就是说,你需要运行:
'python setup.py develop',之后你就可以使用内部类和函数了。
注意:我们建议使用 'develop' 而不是 'install',这样如果你拉取 oregami 的新版本,它将开箱即用。
例如:
-- script.py --
def find_func_usage(func_ea, reg='r0'):
"""
Find and print all usages of a register, including the information of the specific operands
it is in, and what operation it does in the operand.
"""
import oregami
rf = oregami.RegFrame(func_ea, reg)
for insn in rf.get_instructions():
print('Addr:{:x}'.format(insn.ea))
for opnd in insn.operands:
if opnd.uf_is_external:
continue
print('--opnd_idx:{} - {}'.format(opnd.n, oregami.UsageBits(opnd.op_flags)))
假设有以下指令序列:
ROM:01000010 e_lis r10, 0x4004 # 0x40040000 # 立即数左移加载
ROM:01000014 e_add16i r10, r10, 0x1337 # 0x40041337 # 立即数加法
ROM:01000020 se_mr r30, r31 # 寄存器移动
ROM:01000022 cmplw r11, r10 # 逻辑字比较
ROM:01000026 se_bge loc_1000036 # 大于等于则分支
ROM:01000028
ROM:01000028 loc_1000028: # CODE XREF: sub_0100000+144↓j
ROM:01000028 e_stmw r30, 0(r11) # 多字存储
ROM:0100002C e_add16i r11, r11, 8 # 立即数加法
ROM:01000030 cmplw r11, r10 # 逻辑字比较
ROM:01000034 se_blt loc_1000028 # 小于则分支
ROM:01000036
ROM:01000036 loc_1000036: # CODE XREF: sub_0100000+136↑j
ROM:01000036 e_add16i r10, r10, 8 # 立即数加法
ROM:0100003A e_li r11, 0 # 立即数加载
如果我们从地址 01000022 开始扫描 r10 寄存器的使用帧,将会发现使用帧中包含三种类型的用法。
这包括初始化寄存器值的指令。
我们可以只包含最后一条改变寄存器值的指令(示例中的地址 01000014),或者包含用于设置寄存器初始值的操作序列(示例中的地址 01000010 和 01000014)。
用于寄存器初始化的操作序列可称为“初始化阶段”。
根据 RegFrame 初始化时的参数 init_stage_bool,你可以选择是否支持初始化阶段。
这包括使用寄存器值且不会以任何方式改变它的指令。对应示例中的第 01000022 和 01000030 行。
这包括使用寄存器值但随后改变其值的指令。这些指令可以被视为属于两个不同的使用帧——一个指向它们,另一个从它们出发。
对应示例中的第 01000036 行。
当扫描使用帧时,遇到初始化操作或中断操作将导致我们在某个方向上停止扫描。
但是,我们也可能因为使用帧之外的指令而停止扫描。
例如,从地址 01000030 开始扫描 r11 寄存器的使用帧,将在第 0100003A 行停止。
这是 oregami 中使用的基本类。通过在某个地址和特定寄存器上初始化它,它将扫描该寄存器的使用帧,并为所有相关指令创建 UFInstruction 对象。
get_instruction - 从给定地址获取指令
get_instructions - 一个生成器,返回使用帧中的指令。
你也可以请求已用指令的特定子集:
get_init_instructions - 仅获取初始化类型的指令
get_pure_instructions - 仅获取纯使用类型的指令
get_break_instructions - 仅获取中断类型的指令
get_nobreak_instructions - 仅获取非中断类型的指令(即 init + pure)
get_noinit_instructions - 仅获取非初始化类型的指令(即 pure + break)
get_outbreak_instructions - 仅获取外部中断类型的指令
默认情况下,此类将缓存扫描结果,并防止自身重新扫描相同的使用帧。
这意味着请求任何作为使用帧一部分的指令(特别是 init + pure 类型。不包括 break,因为从它们开始扫描应返回从它们出发的使用帧)的 RegFrame,将返回相同的预计算 RegFrame 实例。
要强制重新扫描,请在初始化类时使用 force 标志。
这是 RegFrame 返回的类,表示使用帧中的一条指令。
此类继承自 sark 的 Instruction 类,因此支持相同的方法。
一个主要区别是,它包含的不是 sark Operand 类的操作数组,而是 UFOperand 类的数组。
此类还包含用于理解指令类型(init、pure、break、outbreak)和操作位(读取、写入、显式、不同类型的隐式)的方法。
这是特定 UFInstruction 中操作数组中的类。
此类继承自 sark 的 Instruction 类,因此支持相同的方法。
除了 sark 的操作外,它还包含获取操作位(读取、写入、显式、不同类型的隐式)的方法,以及判断该操作数是否实际属于使用帧的方法(用于知道在 break 类型指令中哪个操作数属于使用帧)。
这是一个用于分析特定指令以了解其与寄存器有关的用法的类。
它利用 IDA 的知识、文本分析以及特定于处理器的细节来完成。
此类存在的原因是,基本的 IDA 分析往往会在许多操作码中对使用的寄存器集合以及它们的使用方式做出不准确的描述。
此类继承自 sark 的 Instruction 类,因此支持相同的方法。
一个主要区别是,它包含的不是 sark Operand 类的操作数组,而是 RegOperand 类的数组。
这是一个用于分析特定操作数以了解其与寄存器有关的用法的类。
它利用 IDA 的知识、文本分析以及特定于处理器的细节来完成。
此类存在的原因是,基本的 IDA 分析往往会在许多操作码中对使用的寄存器集合以及它们的使用方式做出不准确的描述。
此类继承自 sark 的 Operand 类,因此支持相同的方法。