pwnable.kr leg之write up

看代码:

 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

得到结果:

 

posted @ 2017-08-03 11:34  S_s_s  阅读(727)  评论(0编辑  收藏  举报