参考以前的文章:
基于MIPS架构的BackTrace实现
http://blog.csdn.net/jerryutscn/archive/2010/03/10/5365263.aspx
我们可以把同样的功能添加到PSPLink上,以方便在逆向工作中对汇编代码的分析。
例如我们找到了一个比较重要的函数,其入口地址是882AC0C。
IDA可以帮我们产生下面的函数调用表:
但针对我们关注的上下文情况,真正的调用路径只有一条,这个时候我们就需要从栈帧里获得这个信息。
$ pspsh.exe host0:/> bpset 0x882AC0C 0x0882AC0C: 0x0000000D '....' - break 0x0 host0:/> exprint Exception - Breakpoint Thread ID - 0x047DA35D Th Name - main Module ID - 0x03ADE673 Mod Name - main EPC - 0x0882AC0C Cause - 0x10000024 BadVAddr - 0xA6A19114 Status - 0x60088613 zr:0x00000000 at:0x00000001 v0:0x08FF37C0 v1:0x08FF37C0 a0:0x08BE480C a1:0x09FFE090 a2:0x00000A27 a3:0x00000F80 t0:0x08AEFD94 t1:0x08FF41E8 t2:0x08AEFD94 t3:0x08AF0000 t4:0x08AEFA0C t5:0xDEADBEEF t6:0xDEADBEEF t7:0xDEADBEEF s0:0x08FF37C0 s1:0x00000A27 s2:0x0882ACE4 s3:0x08BE4804 s4:0x08FF37C0 s5:0x09FFE918 s6:0x08B21B64 s7:0xDEADBEEF t8:0xDEADBEEF t9:0xDEADBEEF k0:0x09FFEB00 k1:0x00000000 gp:0x08B3FB20 sp:0x09FFE080 fp:0x09FFEAC0 ra:0x0882AD08 host0:/> bt 882ac0c(8be480c,9ffe090,a27,f80) pc [882ac0c] ra [882ad08] sz [0] 882ace4(8be480c,9ffe090,a27,f80) pc [882ad08] ra [882af18] sz [2064] 882aec0(8be480c,9ffe090,a27,f80) pc [882af18] ra [882a934] sz [32] 882a860(8be480c,9ffe090,a27,f80) pc [882a934] ra [882f504] sz [16] 882f4d0(8be480c,9ffe090,a27,f80) pc [882f504] ra [882f160] sz [16] 882f078(8be480c,9ffe090,a27,f80) pc [882f160] ra [8a8e8e8] sz [32] 8a8e890(8be480c,9ffe090,a27,f80) pc [8a8e8e8] ra [8a9075c] sz [48] 8a906c0(8be480c,9ffe090,a27,f80) pc [8a9075c] ra [8918ac4] sz [48] 8918a2c(8be480c,9ffe090,a27,f80) pc [8918ac4] ra [890f7dc] sz [16] 890ed24(8be480c,9ffe090,a27,f80) pc [890f7dc] ra [890ecc4] sz [16] 890ec7c(8be480c,9ffe090,a27,f80) pc [890ecc4] ra [890c1fc] sz [16] 890be5c(8be480c,9ffe090,a27,f80) pc [890c1fc] ra [88ffdf8] sz [64] 88ffcf0(8be480c,9ffe090,a27,f80) pc [88ffdf8] ra [88ffeb8] sz [48] 88ffcf0(8be480c,9ffe090,a27,f80) pc [88ffeb8] ra [88ffeb8] sz [48] 88ffcf0(8be480c,9ffe090,a27,f80) pc [88ffeb8] ra [88ffeb8] sz [48] 88ffcf0(8be480c,9ffe090,a27,f80) pc [88ffeb8] ra [88ffcc8] sz [48] 88ffc98(8be480c,9ffe090,a27,f80) pc [88ffcc8] ra [8804c28] sz [16] 8804bbc(8be480c,9ffe090,a27,f80) pc [8804c28] ra [88047f4] sz [16] 8804358(8be480c,9ffe090,a27,f80) pc [88047f4] ra [9ffeac0] sz [32] 9e3f088(8be480c,9ffe090,a27,f80) pc [9ffeac0] ra [0] sz [0] done! host0:/> |
通过上面的信息,我们可以得知函数的调用关系是:
882ac0c <- 882ace4 <- 882aec0 <- 882a860 <- 882f4d0 |
结合IDA生成的图:
sub_882ac0c <- sub_882ace4 <- sub_882a860 <- sub_882f4d0 |
一比对我们发现backtrace显示的情况比IDA生成的表上多了一级函数调用:sub_882aec0
我们先找到函数882aec0,然后来到882af18,看到代码如下:
.text:0882AF10 jalr $s2 .text:0882AF14 move $a0, $s4 .text:0882AF18 b loc_882AF30 |
0882AF14是延迟槽,所以真正发生跳转的地方是0882AF10
指令:
jalr $s2
明显也是一级函数调用,因为跳转的地址保存在寄存器中,所以IDA作为静态分析的工具无法获得其对应信息。
这里还有一个问题:既然sub_882aec0这级调用已经不在了,为什么再上一级的函数调用sub_882a860又一致了呢?
我们来到函数sub_882A860
.text:0882A860 sub_882A860: … … .text:0882A928 move $a0, $0 .text:0882A92C jal sub_882AEC0 .text:0882A930 la $a2, sub_882ACE4 .text:0882A934 move $a0, $s0 .text:0882A938 move $s0, $v0 … … .text:0882A984 move $a0, $s0 .text:0882A988 jal sub_882AEC0 .text:0882A98C la $a2, sub_882ACE4 |
只能找到这2处引用sub_882ACE4的地方,相同点是,他都作为第3个参数传递给了函数sub_882AEC0。
我们没有在sub_882A860代码中找到关于函数sub_882ACE4的直接调用。至于为什么IDA认为sub_882A860调用了sub_882ACE4,无法获知。
下载补丁:
http://download.csdn.net/source/2588315
应用补丁:
$ cd psplinkusb $ patch -p1 < ../psplinkTraceback_2010_07_25.patch patching file psplink/Makefile patching file psplink/exception.c patching file psplink/exception.h patching file psplink/mips_opcode.h patching file psplink/shell.c patching file psplink/shellcmd.h patching file psplink/trap.c patching file psplink/trap.h patching file psplink/usbshell.c |
注意事项:
针对我的PSP固件5.00M33-6
需要修改文件:
/usr/local/pspdev/psp/sdk/lib/build_prx.mak |
里关于固件版本定义的宏:
ifeq ($(PSP_FW_VERSION),)
PSP_FW_VERSION=150
Endif
否则会导致psplink退出的时候PSP死机。
因为代码里是这样写的:
void psplinkReset(void) { #if _PSP_FW_VERSION >= 200 … … #else … … #endif } |
所以我改成了PSP_FW_VERSION=300