把ARM环境搭好后,就可以动态调试了。之前一道arm逆向的题目,由于没有环境一直只能静态分析,但对arm完全不熟,进行不下去。果然能动态调试就好了。
题目给了一个.c文件和一个.asm文件。我首先编译.c文件,但发现得到的结果用了好多thumb的16 bits的代码,而这和给的.asm文件是不同的。搜索后发现需要指定-marm
。于是
$ gcc leg.c -g -marm -o leg
然后就可以用gdb一步步看了,非常清楚。
特别地,我之前还一直以为执行时寄存器pc
里的值是下一条指令的地址,但发现实际是
The address of the currently executing instruction is typically PC-8 for ARM, or PC-4 for Thumb.
即pc
里应该是当前执行的地址加8。所以函数key1
里:
0x00008cdc <+8>: mov r3, pc 0x00008ce0 <+12>: mov r0, r3
会把0x8cdc+8=0x8ce4
放到r3
和r0
,即返回0x8ce4
。
而函数key3
里:
0x00008d28 <+8>: mov r3, lr 0x00008d2c <+12>: mov r0, r3
由于调用key3
时返回地址lr
是0x8d80
,于是key3
返回0x8d80
。
最后来看函数key2
:
0x00008cf8 <+8>: push {r6} ; (str r6, [sp, #-4]!) 0x00008cfc <+12>: add r6, pc, #1 0x00008d00 <+16>: bx r6 0x00008d04 <+20>: mov r3, pc 0x00008d06 <+22>: adds r3, #4 0x00008d08 <+24>: push {r3} 0x00008d0a <+26>: pop {pc} 0x00008d0c <+28>: pop {r6} ; (ldr r6, [sp], #4) 0x00008d10 <+32>: mov r0, r3
在0x8cfc
那里,会把r6
的值设为0x8cfc+8+1=0x8d05
,然后bx r6
会转成thumb模式。而这里0x8d05
不是2的倍数,用gdb调试发现执行时因为对齐,似乎会从2的倍数那里执行,即0x8d04
。因为是thumb模式,于是接下来又把r3
设为0x8d04+4+4=0x8d0c
,作为返回值。
综上,需要输入的数是0x8ce4+0x8d80+0x8d0c=108400
补充:大概查了下,关于bx
的地址有加1那里,加1是为了指定跳转到thumb模式,如果还是跳到arm模式就不需要了;此外即使加了1,bx
最后取的地址还是没加1的