Daddy told me I should study arm.
But I prefer to study my leg!
Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm
ssh [email protected] -p2222 (pw:guest)
考查ARM的函数调用与返回。ARM 下面的函数调用与 x86 下面的函数调用有着相似之处,例如都要保护返回地址、进入子函数执行、执行完成后根据返回地址返回等一系列操作,但是它们有着许多的不同。
关于ARM寄存器结构的基本内容详见我的另外两篇文章:
ARM状态结构小记
ARM寄存器结构小记
ARM属于RISC指令集,不同于 x86 CISC指令集的堆栈传参,ARM 在函数调用时倾向于寄存器传参。一般地,当参数不超过4个时,系统会使用 R0-R4 寄存器进行参数传递,超过四个才会借助堆栈。
ARM的PC永远指向当前执行指令之后的第二条指令,即处于流水线取指阶段的指令,而 x86 的 PC 指向的是当前执行的指令。
调用子函数也和 x86 不同,x86下是使用 CALL 指令,ARM下是使用 BL (带链接跳转,即当前执行指令的下一条指令保存到 R14,并跳转,进入子函数后会将 R14 的值入栈)指令。
关于返回值,x86 使用 EAX 寄存器传递返回值,ARM 使用 R0 传递返回值。
掌握上述基础知识后,这题就迎刃而解了。
先放上题目源码:
#include
#include
int key1(){
asm("mov r3, pc\n");
}
int key2(){
asm(
"push {r6}\n"
"add r6, pc, $1\n"
"bx r6\n"
".code 16\n"
"mov r3, pc\n"
"add r3, $0x4\n"
"push {r3}\n"
"pop {pc}\n"
".code 32\n"
"pop {r6}\n"
);
}
int key3(){
asm("mov r3, lr\n");
}
int main(){
int key=0;
printf("Daddy has very strong arm! : ");
scanf("%d", &key);
if( (key1()+key2()+key3()) == key ){
printf("Congratz!\n");
int fd = open("flag", O_RDONLY);
char buf[100];
int r = read(fd, buf, 100);
write(0, buf, r);
}
else{
printf("I have strong leg :P\n");
}
return 0;
}
(gdb) disass main
Dump of assembler code for function main:
0x00008d3c <+0>: push {r4, r11, lr}
0x00008d40 <+4>: add r11, sp, #8
0x00008d44 <+8>: sub sp, sp, #12
0x00008d48 <+12>: mov r3, #0
0x00008d4c <+16>: str r3, [r11, #-16]
0x00008d50 <+20>: ldr r0, [pc, #104] ; 0x8dc0
0x00008d54 <+24>: bl 0xfb6c
0x00008d58 <+28>: sub r3, r11, #16
0x00008d5c <+32>: ldr r0, [pc, #96] ; 0x8dc4
0x00008d60 <+36>: mov r1, r3
0x00008d64 <+40>: bl 0xfbd8 <__isoc99_scanf>
0x00008d68 <+44>: bl 0x8cd4
0x00008d6c <+48>: mov r4, r0
0x00008d70 <+52>: bl 0x8cf0
0x00008d74 <+56>: mov r3, r0
0x00008d78 <+60>: add r4, r4, r3
0x00008d7c <+64>: bl 0x8d20
0x00008d80 <+68>: mov r3, r0
0x00008d84 <+72>: add r2, r4, r3
0x00008d88 <+76>: ldr r3, [r11, #-16]
0x00008d8c <+80>: cmp r2, r3
0x00008d90 <+84>: bne 0x8da8
0x00008d94 <+88>: ldr r0, [pc, #44] ; 0x8dc8
0x00008d98 <+92>: bl 0x1050c
0x00008d9c <+96>: ldr r0, [pc, #40] ; 0x8dcc
0x00008da0 <+100>: bl 0xf89c
0x00008da4 <+104>: b 0x8db0
0x00008da8 <+108>: ldr r0, [pc, #32] ; 0x8dd0
0x00008dac <+112>: bl 0x1050c
0x00008db0 <+116>: mov r3, #0
0x00008db4 <+120>: mov r0, r3
0x00008db8 <+124>: sub sp, r11, #8
0x00008dbc <+128>: pop {r4, r11, pc}
0x00008dc0 <+132>: andeq r10, r6, r12, lsl #9
0x00008dc4 <+136>: andeq r10, r6, r12, lsr #9
0x00008dc8 <+140>: ; instruction: 0x0006a4b0
0x00008dcc <+144>: ; instruction: 0x0006a4bc
0x00008dd0 <+148>: andeq r10, r6, r4, asr #9
End of assembler dump.
(gdb) disass key1
Dump of assembler code for function key1:
0x00008cd4 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008cd8 <+4>: add r11, sp, #0
0x00008cdc <+8>: mov r3, pc
0x00008ce0 <+12>: mov r0, r3
0x00008ce4 <+16>: sub sp, r11, #0
0x00008ce8 <+20>: pop {r11} ; (ldr r11, [sp], #4)
0x00008cec <+24>: bx lr
End of assembler dump.
(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.
(gdb) disass key3
Dump of assembler code for function key3:
0x00008d20 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008d24 <+4>: add r11, sp, #0
0x00008d28 <+8>: mov r3, lr
0x00008d2c <+12>: mov r0, r3
0x00008d30 <+16>: sub sp, r11, #0
0x00008d34 <+20>: pop {r11} ; (ldr r11, [sp], #4)
0x00008d38 <+24>: bx lr
End of assembler dump.
(gdb)
可以清楚地看到,key1 函数返回值为 PC:0x00008ce4;key2 函数返回值为 PC + 4: 0x00008d08 + 4 = 0x00008d0c;key3 函数返回值为LR:0x00008d80。
这三个数相加后结果为 0x0001a770 = 108400(d) 。
输入后即可看到flag:
/ $ ./leg
Daddy has very strong arm! : 108400
Congratz!
My daddy has a lot of ARMv5te muscle!