pwnable.kr之leg

Posted countfatcode

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pwnable.kr之leg相关的知识,希望对你有一定的参考价值。

查看原题代码:

#include <stdio.h>
#include <fcntl.h>
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;

知道我们只要使输入的值等于 key1()+key2()+key3() ,就能拿到flag

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.

核心代码为:

   0x00008cdc <+8>:    mov    r3, pc
   0x00008ce0 <+12>:    mov    r0, r3

意思是把pc寄存器的值传递给r3寄存器,再把r3寄存器的值传递给r0,然后r0寄存器的值作为函数的返回值

在ARM汇编指令中,寄存器pc的值为当前指令地址加8个字节,所以寄存器pc中的值为 0x00008cdc+8,则函数返回值为 0x00008cdc+8

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.

核心代码为:

   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

pc寄存器的值为:0x00008cfc+8 ,则r6寄存器的值为:pc+1=0x00008cfc+8+1,第二行指令  bx 是跳转指令,并且还会根据目标地址最低位判断是否更该处理的状态,此时 r6=0x00008cfc+8+1=0x00008d05,转化为二进制为 1000110100000101,最低位为1,所以应该转换为 Thumb状态。

由于转换状态,第三行汇编代码中pc=0x00008d04+4(注意:只增加4个字节),所以 r3=pc=0x00008d04+4

第四行,r3存储的值加4,值为 0x00008d04+4+4,按顺序执行下去可得最后 key2() 的返回值为:0x00008d04+4+4

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.

核心代码为:

   0x00008d28 <+8>:    mov    r3, lr
   0x00008d2c <+12>:    mov    r0, r3

lr寄存器存储的是当前函数执行完毕后的返回地址,故需要去main()函数中去找:

   0x00008d74 <+56>:    mov    r3, r0
   0x00008d78 <+60>:    add    r4, r4, r3
   0x00008d7c <+64>:    bl    0x8d20 <key3>
   0x00008d80 <+68>:    mov    r3, r0
   0x00008d84 <+72>:    add    r2, r4, r3
   0x00008d88 <+76>:    ldr    r3, [r11, #-16]
   0x00008d8c <+80>:    cmp    r2, r3

观察可知 lr的值为 0x00008d80,故key3()的返回值为: 0x00008d80

那么我们最后应该输入的值为 :0x00008cdc+8+0x00008d04+4+4+0x00008d80=1A770,由于题目要求输入十进制,故转化为十进制为 108400

flag为:My daddy has a lot of ARMv5te muscle!

  1. 知道C语言可以内嵌汇编代码,并了解了内嵌汇编的基本语法
  2. 学习了ARM汇编指令,在ARM汇编中,其寄存器是r0~r15,其中r13(别名:sp),它通常指向通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。lr(r14),存放的是函数的返回地址,一般调用子函数用的比较多,pc(r15),值为当前操作的地址
  3. 放几个写得比较好的博客:https://blog.csdn.net/bytxl/article/details/49883103

            https://blog.csdn.net/aguangg_6655_la/article/details/53613270

以上是关于pwnable.kr之leg的主要内容,如果未能解决你的问题,请参考以下文章

pwnable.kr blackjack之write up

pwnable.kr之passcode

pwnable.kr 之 passcode write up

pwnable.kr之leg

pwnable.kr lotto之write up

pwnable.kr bof之write up