看代码:
1 #include <stdio.h> 2 #include <fcntl.h> 3 int key1(){ 4 asm("mov r3, pc\n"); 5 } 6 int key2(){ 7 asm( 8 "push {r6}\n" 9 "add r6, pc, $1\n" 10 "bx r6\n" 11 ".code 16\n" 12 "mov r3, pc\n" 13 "add r3, $0x4\n" 14 "push {r3}\n" 15 "pop {pc}\n" 16 ".code 32\n" 17 "pop {r6}\n" 18 ); 19 } 20 int key3(){ 21 asm("mov r3, lr\n"); 22 } 23 int main(){ 24 int key=0; 25 printf("Daddy has very strong arm! : "); 26 scanf("%d", &key); 27 if( (key1()+key2()+key3()) == key ){ 28 printf("Congratz!\n"); 29 int fd = open("flag", O_RDONLY); 30 char buf[100]; 31 int r = read(fd, buf, 100); 32 write(0, buf, r); 33 } 34 else{ 35 printf("I have strong leg :P\n"); 36 } 37 return 0; 38 }
C Code
1 #include <stdio.h> 2 #include <fcntl.h> 3 int key1(){ 4 asm("mov r3, pc\n"); 5 } 6 int key2(){ 7 asm( 8 "push {r6}\n" 9 "add r6, pc, $1\n" 10 "bx r6\n" 11 ".code 16\n" 12 "mov r3, pc\n" 13 "add r3, $0x4\n" 14 "push {r3}\n" 15 "pop {pc}\n" 16 ".code 32\n" 17 "pop {r6}\n" 18 ); 19 } 20 int key3(){ 21 asm("mov r3, lr\n"); 22 } 23 int main(){ 24 int key=0; 25 printf("Daddy has very strong arm! : "); 26 scanf("%d", &key); 27 if( (key1()+key2()+key3()) == key ){ 28 printf("Congratz!\n"); 29 int fd = open("flag", O_RDONLY); 30 char buf[100]; 31 int r = read(fd, buf, 100); 32 write(0, buf, r); 33 } 34 else{ 35 printf("I have strong leg :P\n"); 36 } 37 return 0; 38 }
分析代码,key1()+key2()+key3()==key时,得到flag
那么来分析给定的汇编代码:
1 (gdb) disass key1 2 Dump of assembler code for function key1: 3 0x00008cd4 <+0>: push {r11} ; (str r11, [sp, #-4]!) 4 0x00008cd8 <+4>: add r11, sp, #0 5 0x00008cdc <+8>: mov r3, pc 6 0x00008ce0 <+12>: mov r0, r3 7 0x00008ce4 <+16>: sub sp, r11, #0 8 0x00008ce8 <+20>: pop {r11} ; (ldr r11, [sp], #4) 9 0x00008cec <+24>: bx lr 10 End of assembler dump.
返回地址是r0而r0等于pc,且为arm指令
补充知识:
PC代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:1.取指(从存储器装载一条指令);2.译码(识别将要被执行的指令);3.执行(处理指令并将结果写回寄存器)。而R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址加8字节的地址,即:PC值=当前程序执行位置+8; ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4(假设在ARM状态下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。
所以
r0的地址等于0x8cdc+0x8
再看key2:
(gdb) disass key2 Dump of assembler code for function key2: 0x00008cf0 <+0>: push {r11} ; (str r11, [sp, #-4]!) 0x00008cf4 <+4>: add r11, sp, #0 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 0x00008d14 <+36>: sub sp, r11, #0 0x00008d18 <+40>: pop {r11} ; (ldr r11, [sp], #4) 0x00008d1c <+44>: bx lr End of assembler dump.
返回地址为r3,bx r6跳转为thumb指令,所以r3=0x8d04+0x4+0x4;
附:arm与thumb跳转:
http://blog.csdn.net/itismine/article/details/4753701
再看key3:
1 (gdb) disass key3 2 Dump of assembler code for function key3: 3 0x00008d20 <+0>: push {r11} ; (str r11, [sp, #-4]!) 4 0x00008d24 <+4>: add r11, sp, #0 5 0x00008d28 <+8>: mov r3, lr 6 0x00008d2c <+12>: mov r0, r3 7 0x00008d30 <+16>: sub sp, r11, #0 8 0x00008d34 <+20>: pop {r11} ; (ldr r11, [sp], #4) 9 0x00008d38 <+24>: bx lr 10 End of assembler dump. 11 (gdb)
返回地址为r0,r0=lr,而lr保存返回地址
返回到main函数:
1 (gdb) disass main 2 Dump of assembler code for function main: 3 0x00008d3c <+0>: push {r4, r11, lr} 4 0x00008d40 <+4>: add r11, sp, #8 5 0x00008d44 <+8>: sub sp, sp, #12 6 0x00008d48 <+12>: mov r3, #0 7 0x00008d4c <+16>: str r3, [r11, #-16] 8 0x00008d50 <+20>: ldr r0, [pc, #104] ; 0x8dc0 <main+132> 9 0x00008d54 <+24>: bl 0xfb6c <printf> 10 0x00008d58 <+28>: sub r3, r11, #16 11 0x00008d5c <+32>: ldr r0, [pc, #96] ; 0x8dc4 <main+136> 12 0x00008d60 <+36>: mov r1, r3 13 0x00008d64 <+40>: bl 0xfbd8 <__isoc99_scanf> 14 0x00008d68 <+44>: bl 0x8cd4 <key1> 15 0x00008d6c <+48>: mov r4, r0 16 0x00008d70 <+52>: bl 0x8cf0 <key2> 17 0x00008d74 <+56>: mov r3, r0 18 0x00008d78 <+60>: add r4, r4, r3 19 0x00008d7c <+64>: bl 0x8d20 <key3> 20 0x00008d80 <+68>: mov r3, r0 21 0x00008d84 <+72>: add r2, r4, r3 22 0x00008d88 <+76>: ldr r3, [r11, #-16] 23 0x00008d8c <+80>: cmp r2, r3 24 0x00008d90 <+84>: bne 0x8da8 <main+108> 25 0x00008d94 <+88>: ldr r0, [pc, #44] ; 0x8dc8 <main+140> 26 0x00008d98 <+92>: bl 0x1050c <puts> 27 0x00008d9c <+96>: ldr r0, [pc, #40] ; 0x8dcc <main+144> 28 0x00008da0 <+100>: bl 0xf89c <system> 29 0x00008da4 <+104>: b 0x8db0 <main+116> 30 0x00008da8 <+108>: ldr r0, [pc, #32] ; 0x8dd0 <main+148> 31 0x00008dac <+112>: bl 0x1050c <puts> 32 0x00008db0 <+116>: mov r3, #0 33 0x00008db4 <+120>: mov r0, r3 34 0x00008db8 <+124>: sub sp, r11, #8 35 0x00008dbc <+128>: pop {r4, r11, pc} 36 0x00008dc0 <+132>: andeq r10, r6, r12, lsl #9 37 0x00008dc4 <+136>: andeq r10, r6, r12, lsr #9 38 0x00008dc8 <+140>: ; <UNDEFINED> instruction: 0x0006a4b0 39 0x00008dcc <+144>: ; <UNDEFINED> instruction: 0x0006a4bc 40 0x00008dd0 <+148>: andeq r10, r6, r4, asr #9 41 End of assembler dump.
第20行,key3的地址为0x8d80,
python得到key的值:
1 #/usr/bin/python 2 3 key1=0x8cdc+0x8 4 key2=0x8d04+0x4+0x4 5 key3=0x8d80 6 7 key=key1+key2+key3 8 9 print key
得到结果:
时间: 2024-11-03 12:23:57