首页
社区
课程
招聘
[分享]pwnable.kr leg day7
发表于: 2021-1-8 14:13 1969

[分享]pwnable.kr leg day7

2021-1-8 14:13
1969

题目

解题过程

1. 下载附件查看源代码

附件包含两个文件,leg.c 是 c 语言源码,leg.asm 是 gdb 反汇编的结果。

leg.c 源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#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;
}

可以看到为了能够读取 flag,我们手动输入的 key 值需等于 key1(),key2(),key3() 返回值的和。
key1(),key2(),key3() 都是内联 arm 汇编。
arm 用寄存器 r0 传递返回值

2. 结合 leg.asm 与 leg.c 分析上述三个函数汇编代码中 r0 的值

key1()

arm 的体系结构中,需注意 arm 状态与 thumb 状态。arm 状态下指令长度为 4 字节,thumb 状态下指令长度为 2 字节。它们之间通过 bx 指令切换。bx 利用 Rn 寄存器中目的地址值的最后一位来判断跳转后的状态。当最后一位为 0 时,表示转移到 arm 状态;当最后一位为 1 时,表示转移到 thumb 状态。
arm 处理器复位后开始执行代码时总是只处于 arm 状态

 

可以看到 r0 的值 与 r3 和 pc 有关。
此时处于 arm 状态,寄存器 pc(r15) 指向当前指令地址 +(2 * 指令长度 = 8) 处,执行了 0x00008cdc 后,r3 = pc = 0x00008ce4。
紧接着 r3 的值赋给了 r0,所以 r0 = 0x00008ce4。

key2()


可以看到 r0 的值与 r3,pc,r6 有关。
在对 r6 赋值时,处于 arm 状态,r6 = pc + 1 = 0x8cfc + 2 4 + 1 = 0x8d05
紧接着执行 bx r6,此时 r6 的最后一位(二进制)是 1,接下来的指令处于 thumb 状态,指令长度为 2。
然后将 pc 的值赋予 r3,此时 pc 指向当前指令地址 +(2
指令长度 = 4) 处,在执行 0x8d04 后, r3 = pc = 0x8d08
随后 r3 的值加 4,变为 0x8d0c
然后将 r3 的值赋予给 r0,所以 r0 = 0x8d0c。
最后执行 bx lr,完成子程序调用的返回并切换到 arm 状态

key3()


r0 的值与 r3,lr 有关
lr 在 arm 体系结构中有两种特殊用途:一是用来保存子程序返回地址;二是当异常发生时,lr 中保存的值等于异常发生时 pc 的值减 4(或者减2)。
由 main 中的

1
2
0x00008d7c <+64>:    bl    0x8d20 <key3>
0x00008d80 <+68>:    mov    r3, r0

可知,lr = 0x8d80
所以 r0 = r3 = lr = 0x8d80

计算 key 值

key = key1() + key2() + key3() = 0x00008ce4 + 0x8d0c + 0x8d80 = 0x1a770 = 108400
转换成十进制的原因是因为 main() 中的 scanf() 中要求格式为 %d

PWN

输入计算的 key,获得 flag,即红框里的内容

参考文献

  • 72dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3P5i4W2Y4M7$3A6Q4x3V1k6H3i4K6u0r3y4e0b7J5z5o6f1H3x3q4)9J5k6h3S2@1L8h3H3`.
  • 9f1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3y4*7k6K6p5K6y4e0b7^5z5e0x3H3x3e0R3$3i4K6u0r3j5i4u0@1K9h3y4D9k6g2)9J5c8X3c8W2N6r3q4A6L8s2y4Q4x3V1j5%4z5o6j5@1x3K6b7@1y4b7`.`.

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回