jmp ds:off_20B280CC[ebx*4]
jmp dword ptr ds:loc_6B2A825C[ecx*4]
[Q:是由于switch / jump吗?]从GetOperandValue(inst.ea, 0)
可以看到,这些跳转的操作数类型是“内存引用”(类型值2)。像jb short loc_6B2A8154
这样的跳转语句的操作数类型为“立即临近地址”(类型值7)。但是,thunk函数中的诸如jmp ds:__imp_memset
之类的跳转语句用于调用导入的函数,其操作数类型也为“内存引用”。 有什么办法可以区分switch / case和thunk函数的跳转语句?
#1 楼
在许多情况下,IDA已经知道跳转是跳转表的一部分,并且很可能是切换的结果。如果是这样,则可以使用IDAPython访问它。相关的功能是
get_switch_info_ex(ea)
和get_switch_info_ex(ea)
。通过查看IDAPython文档,我们发现: /> calc_switch_cases(insn_ea,py_swi)
获取有关交换机的案例的信息。
返回的信息可以按如下方式使用: br />
@param insn_ea:“间接跳转”指令的地址@param si:
切换信息
@return:具有2个成员的结构:“ cases”,和'targets'。
返回值:case_and_targets_t
要从示例中获取
results
变量,我们使用以下代码:for idx in xrange(len(results.cases)):
cur_case = results.cases[idx]
for cidx in xrange(len(cur_case)):
print "case: %d" % cur_case[cidx]
print " goto 0x%x" % results.targets[idx]
因此,要检查指令是否为开关,可以使用以下功能:
si = idaapi.get_switch_info_ex(ea)
results = idaapi.calc_switch_cases(ea, si)
if not results:
print "No switch related jump at 0x{:X}".format(ea)
如果您希望使用它,我为Sark中的IDA交换机编写了一个基本包装器类。见这里。
#2 楼
在x86体系结构上,由于switch / case语句而产生的跳转语句通常遵循以下模式:比例因子。取决于您的编译器,搜索带有索引的内存操作数的跳转指令可能会有好的结果。高效的代码。例如:
jmp <offset> [<index-register> * 4] ;; pointers are 4 bytes
将效率非常低地实现为表查找。因此,仅查找索引的内存操作数并不一定会在程序中找到所有开关/大小写。完全有可能确定发出序列更好
switch (foo) {
case 1: do_something(); break;
case 10000: do_something_else(); break;
case 1000000: do_final_thing(); break;
}
mov eax,table_offset[eax*4]
jmp eax
要覆盖所有基础,您将被迫使用其他技术(例如向后切片)来确定已编译的switch / case语句的目标。 。
评论
感谢您解释其他开关/案例方案。我得照顾那些。但是,作为第一步,我要弄清楚索引的内存操作数用于开关/大小写跳转。我正在使用IDA Python脚本来获取指令类型,操作数类型和值等。使用IDA Python,由于thunk函数的缘故,我仍然无法区分对索引内存引用和其他内存引用的切换/案例跳转。任何指针将不胜感激。
–苏丹娜
16-4-1在18:38
我不熟悉IDA,但是在识别了间接jmp之后,您能否将其操作码开始与FF 24 85 / 8D / 95 / 9D等进行比较。
– JohnKällén
16年4月1日在18:50