第一次ctf比赛的赛后复现记录

五月份,这是我第一次参加实际意义上的线下赛,真的感触良多,也发现了自己学习的知识的薄弱,这次misc标题下的题目虽然只有两道,但是我也只写出了一道,这道题考的是vim 编译器中ESC与CR在其中的格式关系,但我也其实算是侥幸通过吧,恰好这次比赛能联网,恰好然我查找到了这之间的格式关系。另外的就是这次比赛中还有一个溯源取证类方向的题目,啊啊啊啊,我做不出开,就是感觉自己像站在巨浪下面的海草,后面看了wp才弄清楚,也逐渐去了解了一些知识,感觉这些算是基础的吧,如果之前自己好好的去了解过的话,道路还长,加油啊,挺有意思的,感觉像探秘一样,大侦探的成长之路,欧耶。

查看wp,发现直接在终端输入find / -name "*.php" | xargs grep "eval(",然后就去了解了一下这串命令的含义。find / -name "*.php"的意思是从根目录(/)开始递归查找所有扩展名为.php的文件,如果目标是Web服务器或个人网站,PHP是常见的攻击载体(尤其是通过eval()动态执行恶意代码),PHP 的 eval()、system()、exec() 等函数允许动态执行代码,黑客可以利用它们实现 远程代码执行(RCE) 或植入 WebShell(一种网页后门)。

|是管道,将前一个命令(find)的输出作为后一个命令(xargs grep)的输入。

xargs:将输入数据转换为命令行参数。

grep "eval(":搜索包含eval(字符串的内容。

然后就找到了插入木马所在的目录/usr/var/www/html/.ssl.php

这个在终端输入cat /usr/var/www/html/.ssl.php,查看完整的代码

现在来分析这串代码:

发现一个URL编码:$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");则//lapUCm=n1zb/ma5\vt0i28-pxuqy*6lrkdg9_ehcswo4+f37j

然后可以看到eval(YwzIst("此处是一串base64编码",然后将其解码得到uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelm

M9jWAfxqnT2UYjLKi9qw1DFYNISW2isyYk1yYk1ZhU2K10PBNf/mx====";

eval('?>'.YwzIst(OxirhK(YpAUWC(uWcdaA,rVkKjU\*2),YpAUWC(uWcdaA,rVkKjU,rVkKjU),YpAUWC(uWcdaA,0,rVkKjU))));

YwzIst是通过拼接 $SlapUCm 的某些字符生成的,然后由于PHP中字符串索引从 0 开始。结合PHP解析参数特性。

YwzIst = lapUCm[3].lapUCm\[6\].lapUCm[33].$lapUCm[30]; // "b"+"a"+"s"+"e" = "base"

OxirhK = lapUCm[33].lapUCm\[10\].lapUCm[24].lapUCm\[10\].lapUCm[24]; // "s"+"6"+"4"+"6"+"4" = "s6464" → 实际是"base64_decode"

YpAUWC = OxirhK[0].lapUCm\[18\].lapUCm[3].OxirhK\[0\].OxirhK[1].$lapUCm[24]; // "s"+"u"+"b"+"s"+"6"+"4" = "subs64" → 实际是"substr"

rVkKjU = lapUCm[7].$lapUCm[13]; // "v"+"t" = "vt" → 但作为数字使用时,PHP会转换为0,所以实际是36。

那么最后的eval串就是eval(base64_decode(substr(UWcdA, 72), substr(UWcdA, 36, 36), substr($UWcdA, 0, 36)));

  1. substr($UWcdA, 0, 36) - 获取字符串前36个字符
  2. substr($UWcdA, 36, 36) - 获取中间36个字符(从36开始,长度36)
  3. substr($UWcdA, 72) - 获取从72开始到末尾的所有字符

标准的 base64_decode() 只有一个参数,但这里传入了三个参数。这是PHP的一个非标准用法,实际上只有第一个参数会被处理,其余参数会被忽略。

然后查看官方wp,发现要用个工具PHP,后面也是将它合PHP解析参数特性,秘钥为Aka]qiuqiu.66或Aka[qiuqiu.6

/etc/passwd 文件:存储所有用户的基本信息(如用户名、UID、Shell 等)。格式为:username:x:UID:GID:描述:家目录:登录Shell。

/etc/shadow 文件:存储用户的加密密码和账户有效期。

然后看其他大佬的题解的时候,发现它们使用的不是cat /etc/passwd,而是nl /etc/passwwd,了解了才发现两者没什么太大区别,只是nl 这个命令更为直观。

命令 输出示例 用途
cat /etc/passwd root:x:0:0:root:/root:/bin/bash 直接显示内容,无行号。
nl /etc/passwd 1 root:x:0:0:root:/root:/bin/bash 带行号显示,方便定位异常用户

然后就在49行发现了端倪,Shell 为 /bin/sh :允许用户登录(如果是 /usr/sbin/nologin 则无害)。那么用户名就是hxctf。

用命令echo -n "hxctf" | md5sum,得到MD5值667b76fc7858372b9c266af1eab826bf。

  • 其中echo 命令用于输出字符串。
  • -n 选项表示不输出末尾的换行符。
  • |:管道符号,将前一个命令的输出作为后一个命令的输入。
  • md5sum :计算输入数据的 MD5 哈希值。

这道题目查看wp,说使用tcpdump抓取流量时会发生错误,那么尝试一下,看一下会是什么样的错误,wp给出的命令为tcpdump -i ens33 -w 1.pcap,分析一下,tcpdump 是抓包工具,-i ens33-i 指定监听的网络接口(interface),ens33 是常见的 虚拟网卡名称。 -w 1.pcap -w 表示将抓到的数据包 写入文件( 1.pcap 是文件名)

说明劫持写在so共享库中,那么就来查看错误日志。

命令:grep "libx.so" /var/log/syslog,那么来分析一下:

grep :Linux 下的文本搜索工具,用于在文件或输入中匹配特定模式(字符串或正则表达式)

"libx.so" :搜索的关键字,即动态链接库文件名 libx.so

**/var/log/syslog:**系统主日志文件,记录内核、服务、应用程序等的运行信息(Ubuntu/Debian 系系统)

再进行抓包,可以找到外联地址和端口117.72.37.20433636

看到大佬的wp里使用了命令:crontab -l,crontab -l 是一个用于 列出当前用户的定时任务(cron jobs) 的 Linux/Unix 命令。

crontab:cron 表的管理工具,用于创建、编辑、列出或删除定时任务。

-l:list 的缩写,表示列出当前用户的 cron 任务。

那么结合上题可知,源头的绝对路径/usr/lib/libu.so

(题外话:五月份写的,今天才发,然后这中间学到了蛮多,回看这篇文章的时候倒还是平增了几分狂气,也不是像刚接触那样无所下手了,还真是学到了好多好多,继续加油!)