-
-
[求助]如何重建switch/case结构
-
发表于: 2010-11-7 11:13 3521
-
switch/case语句是主流高级编程语言经常使用的语句,对一般的编译器而言,如果case的情况不是很多,编译器会采用“if-else”的结构,但如果case的情况较多的话,编译器则会采用跳转表的方式,因为这种方式效率较高。
现在的问题是,如果我要用嵌入汇编的高级语言重建某个带有跳转表结构的函数会出现问题。之所以要用“嵌入汇编的高级语言”,主要是因为希望能够同时兼顾重用ida或OD中的反汇编代码,(我不想重新分析所有的指令,这个程序的内部逻辑非常复杂,我所需要的只是提取其中的一个子功能),同时又能够利用高级语言的能够操作复杂数据类型特性,比如类(这个程序是用Visual C++ MFC编写的,我所分析的代码中大量使用了__thiscall)。换句话说,我的目的就是尽量用最简单的方法重建该程序的这个功能。
当我在重建一个带有switch/case语句的函数时碰到了困难。我们知道跳转表其实是一个全局变量,其地址往往在该函数的最后一个ret指令的后面,也就是说跳转表地址并不位于任何函数当中,在指令中访问跳转表采用 jmp off_523820[eax*4] 的方式,而 off_523820 这个全局变量应该是编译器在编译的时候产生的。
前面我提到,我不想重新分析所有的指令,我希望直接重用ida中的反汇编代码,于是我新建一个类,添加一个空的成员函数,然后把这些反汇编代码放进这个成员函数的函数体之中,希望能够编译通过。结果出错: off_523820 这个 变量找不到。我们知道 off_523820 这个变量实际上是跳转表的首地址,于是我在类定义中添加一个 DWORD 类型的静态数组,数组的大小正好等于原来的跳转表中的项目个数,我用的是delphi,像这样定义: jmptable:array[1..13] of DWORD; ,但是编译仍然报错,“Invalid combination of opcode and operands”。让人奇怪的是我把[1..13]去掉,即把jmptable定义成动态数组后编译通过,后来我又把jmptable定义成 integer ,编译也通过 ,把我给弄糊涂了。
我能想到的一个方法是要修改源代码,在jmp指令前先用一个寄存器来保存 off_523820 的地址,比如 mov edx, offset jmptable, jmp的时候就采用jmp [edx+eax*4],这样倒是编译没问题,但我查看相邻的代码发现所有的寄存器都已经使用,我又不能使用堆栈来保存地址,因为涉及到直接跳转,堆栈无法恢复。
另外我还想到是否可以在函数外定义全局静态数组,结果都是同样的结果。
特此寻求各位大侠的帮助,谢谢。
现在的问题是,如果我要用嵌入汇编的高级语言重建某个带有跳转表结构的函数会出现问题。之所以要用“嵌入汇编的高级语言”,主要是因为希望能够同时兼顾重用ida或OD中的反汇编代码,(我不想重新分析所有的指令,这个程序的内部逻辑非常复杂,我所需要的只是提取其中的一个子功能),同时又能够利用高级语言的能够操作复杂数据类型特性,比如类(这个程序是用Visual C++ MFC编写的,我所分析的代码中大量使用了__thiscall)。换句话说,我的目的就是尽量用最简单的方法重建该程序的这个功能。
当我在重建一个带有switch/case语句的函数时碰到了困难。我们知道跳转表其实是一个全局变量,其地址往往在该函数的最后一个ret指令的后面,也就是说跳转表地址并不位于任何函数当中,在指令中访问跳转表采用 jmp off_523820[eax*4] 的方式,而 off_523820 这个全局变量应该是编译器在编译的时候产生的。
前面我提到,我不想重新分析所有的指令,我希望直接重用ida中的反汇编代码,于是我新建一个类,添加一个空的成员函数,然后把这些反汇编代码放进这个成员函数的函数体之中,希望能够编译通过。结果出错: off_523820 这个 变量找不到。我们知道 off_523820 这个变量实际上是跳转表的首地址,于是我在类定义中添加一个 DWORD 类型的静态数组,数组的大小正好等于原来的跳转表中的项目个数,我用的是delphi,像这样定义: jmptable:array[1..13] of DWORD; ,但是编译仍然报错,“Invalid combination of opcode and operands”。让人奇怪的是我把[1..13]去掉,即把jmptable定义成动态数组后编译通过,后来我又把jmptable定义成 integer ,编译也通过 ,把我给弄糊涂了。
我能想到的一个方法是要修改源代码,在jmp指令前先用一个寄存器来保存 off_523820 的地址,比如 mov edx, offset jmptable, jmp的时候就采用jmp [edx+eax*4],这样倒是编译没问题,但我查看相邻的代码发现所有的寄存器都已经使用,我又不能使用堆栈来保存地址,因为涉及到直接跳转,堆栈无法恢复。
另外我还想到是否可以在函数外定义全局静态数组,结果都是同样的结果。
特此寻求各位大侠的帮助,谢谢。
赞赏
他的文章
看原图
赞赏
雪币:
留言: