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

得到结果:

时间: 2024-11-03 12:23:57

pwnable.kr leg之write up的相关文章

【pwnable.kr】leg

pwnable从入门到放弃第八题. Download : http://pwnable.kr/bin/leg.cDownload : http://pwnable.kr/bin/leg.asm ssh [email protected] -p2222 (pw:guest) 先下载这两个文件:leg.c #include <stdio.h> #include <fcntl.h> int key1(){ asm("mov r3, pc\n"); } int key2

【LINUX】pwnable.kr cmd1 writeup

[email protected]:~$ ls cmd1  cmd1.c  flag [email protected]:~$ cat cmd1.c #include <stdio.h> #include <string.h> int filter(char* cmd){ int r=0; r += strstr(cmd, "flag")!=0; r += strstr(cmd, "sh")!=0; r += strstr(cmd, &quo

【pwnable.kr】bof

pwnable从入门到放弃,第三题. Download : http://pwnable.kr/bin/bofDownload : http://pwnable.kr/bin/bof.c Running at : nc pwnable.kr 9000 很简单的一道栈溢出题目. 依然先读代码: #include <stdio.h> #include <string.h> #include <stdlib.h> void func(int key){ char overfl

【PWN】pwnable.kr echo1 writeup

#Exploit for [email protected] #@Windcarp 2015.07.23 from pwn import * #init context(arch = 'amd64', os = 'linux') local=False if local: p = process("./echo1") libc = ELF("/lib/x86_64-linux-gnu/libc-2.19.so") else: p = remote("pwn

【pwnable.kr】 asm

一道写shellcode的题目, #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/mman.h> #include <seccomp.h> #include <sys/prctl.h> #include <fcntl.h> #include <unistd.h> #define LENGTH 128 void sa

【pwnable.kr】 codemap

pwnable新的一题. download: http://pwnable.kr/bin/codemap.exe ssh [email protected] -p2222 (pw:guest) 这道题虽然是在pwnable下,但是是一道逆向题... //前web狗膜一发二进制大佬 根据提示,需要查看 0x403E65 运行时,寄存器 EAX,EBX 的内容. 先不考虑运行的内容,先看程序.首先这个程序没有加壳,直接可以用ida查看内容. 然后可以看到程序的框架,在main函数中,默默按下F5..

pwnable.kr的passcode

前段时间找到一个练习pwn的网站,pwnable.kr 这里记录其中的passcode的做题过程,给自己加深印象. 废话不多说了,看一下题目, 看到题目,就ssh连接进去,就看到三个文件如下 看了一下我们的用户名,并不能直接查看flag这个文件.查看passcode.c的源码看一下 #include <stdio.h> #include <stdlib.h> void login(){ int passcode1; int passcode2; printf("enter

pwnable.kr bof之write up

这一题与前两题不同,用到了静态调试工具ida 首先题中给出了源码: 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 void func(int key){ 5 char overflowme[32]; 6 printf("overflow me : "); 7 gets(overflowme); // smash me! 8 if(key == 0xcafebabe

pwnable.kr之passcode

passcode 下载下来的源代码 从源代码分析看出来,在scanf的时候passcode1和passcode2没有加地址符号,因此会存在题目中所说的警告. 这道题木一共两个函数,welcome和Login,在welcome中输入了name字符串,然后在Login中输入了passcode1和passcode2,在passcode1=338150(0x528E6)并且passcode2=13371337(0xCC07C9)的时候返回shell,得到flag. 想当然地: 竟然发现段错误.什么鬼.于