标题: decrypt_doublepulsar_traffic.py的BUG 创建: 2017-07-21 15:52 链接: https://scz.617.cn/windows/201707211552.txt Luke Jennings提供了一个脚本,用于解密还原发往Doublepulsar Backdoor的RunDLL 报文,还原得到的数据包括kernel shellcode+dll。作者还提供了用于验证的报文及 还原后的数据。 https://github.com/countercept/doublepulsar-c2-traffic-decryptor 最初只是想学习一下它的kernel shellcode,但在实测自己捕获的报文时,发现解密 还原的数据与作者提供的大相径庭,一度怀疑自己的Wireshark在丢包。后来折腾了 一番,发现作者提供的解密脚本有BUG,遂记之。 从Doublepulsar-1.3.1.xml中可以看到这个后门的一些功能: OutputInstall Only output the install shellcode to a binary file on disk Ping Test for presence of backdoor RunDLL Use an APC to inject a DLL into a user mode process RunShellcode Run raw shellcode Uninstall Remove's backdoor from system 现在比较流行的是RunDLL,RunShellcode则相对少见。 查看decrypt_doublepulsar_traffic.py源码,发往Doublepulsar Backdoor的SMB报 文中,有效载荷对应所有的"Trans2 SESSION_SETUP Request"。其中第一个 "Trans2 SESSION_SETUP Request"对应Ping,后续其他 "Trans2 SESSION_SETUP Request"对应RunDLL。 Ping的TCP数据区占82字节,SESSION_SETUP Parameters是12个\x00,没有 SESSION_SETUP Data。 RunDLL对应多个SESSION_SETUP Parameters+SESSION_SETUP Data,每个12字节的 SESSION_SETUP Parameters用途暂时不管,所有SESSION_SETUP Data合起来对应加密 后的kernel shellcode以及被注入的DLL。所有SESSION_SETUP Parameters+SESSION_SETUP Data 使用一个4字节XORKEY进行简单的循环异或加密。SESSION_SETUP Parameters其偏移8 开始的4字节是little-endian序的offset,指出对应的SESSION_SETUP Data应该位于 何处。因此,RunDLL的第一个SESSION_SETUP Parameters其偏移8开始的4字节加密前 是全零,根据异或的特性可知,捕获报文中此处正是XORKEY。 decrypt_doublepulsar_traffic.py试图从Wireshark抓包中解密kernel shellcode以 及被注入的DLL。这是个早期实现,作者可能后来有改进但没有公开。 $ pip install python-pcapng $ python decrypt_doublepulsar_traffic.py --pcapng inject-dll-wininet-into-calc.pcapng --output decrypted_data.bin 这里只认.pcapng格式,不认.pcap格式。 作者认为decrypted_data.bin是4885字节的kernel shellcode以及wininet.dll。 decrypt_doublepulsar_traffic.py有BUG,它假设MTU足够大,单个 "Trans2 SESSION_SETUP Request"不会被分成多个IP报文。 inject-dll-wininet-into-calc.pcapng中绝大多数 "Trans2 SESSION_SETUP Request"确实各自在单个IP报文中,但第一个 "Trans2 SESSION_SETUP Request"就被分成2个IP报文,按照 decrypt_doublepulsar_traffic.py的代码逻辑,14号报文不会被解密,生成的 decrypted_data.bin少了1258字节。 我改写了解密脚本中如下部分: -------------------------------------------------------------------------- with open( pcap_filename, 'rb' ) as read_fp, open( write_filename, 'wb' ) as write_fp : scanner = FileScanner( read_fp ) data = '' for block in scanner : if isinstance( block, EnhancedPacket ) : if "\xffSMB" in block.packet_data and "\x00\x0e\x00" in block.packet_data : offset = block.packet_data.index("\x00\x0e\x00") + 6 header = block.packet_data[offset:offset+12] data += block.packet_data[offset+12:] if xor_key is None : xor_key = header[8:12] print repr( xor_key ) else : data += block.packet_data[0x36:] decrypted_data = xor_decrypt( data, xor_key ) write_fp.write( decrypted_data ) -------------------------------------------------------------------------- 改写后的脚本不能直接用于inject-dll-wininet-into-calc.pcapng,它假设只会遇 见RunDLL对应的多个SESSION_SETUP Parameters+SESSION_SETUP Data,好处是可以 处理单个"Trans2 SESSION_SETUP Request"被分成多个IP报文的情形,实际上真实环 境中MTU一般是1500左右。 对原始捕获报文施以Display Filter (tcp.dstport == 445) && (ip.len > 512) 然后 Export Specified Packets->Displayed 假设保存成 inject-dll-wininet-into-calc_1.pcapng $ python decrypt_doublepulsar_traffic_scz_1.py --pcapng inject-dll-wininet-into-calc_1.pcapng --output decrypted_traffic_1.bin 用64位IDA反汇编decrypted_traffic_1.bin。 后来我自己捕了一个Doublepulsar_1_orig.pcap,用Display Filter处理得到 Doublepulsar_1.pcapng。 $ python decrypt_doublepulsar_traffic_scz_1.py --pcapng Doublepulsar_1.pcapng --output Doublepulsar_1.bin 用64位IDA反汇编Doublepulsar_1.bin。 实际是0x1800字节kernel shellcode+wininet.dll,如何知道0x1800这个数字呢?在 decrypted_traffic_1.bin、Doublepulsar_1.bin中搜索"4D 5A 90 00",就是PE文件 最开始的"MZ.."。 wininet.dll很可能不一样,我们比较一下kernel shellcode。 $ dd if=decrypted_traffic_1.bin count=1 bs=$[0x1800] of=kernel_shellcode_0.bin $ dd if=Doublepulsar_1.bin count=1 bs=$[0x1800] of=kernel_shellcode_1.bin dd的bs参数不直接支持16进制,只好依赖bash的处理。 $ fc /b kernel_shellcode_0.bin kernel_shellcode_1.bin 0000086F: 45 17 00000870: 12 25 000017F9: 36 08 000017FA: 12 25 居然只有4字节不同,在IDA中看了一下,就是两个预定义常量。是什么造成这种不同? 猜测是目标OS不同所致。kernel_shellcode_0.bin对应: Windows Server 2008 R2 Datacenter 7601 Service Pack 1 Windows Server 2008 R2 Datacenter 6.1 kernel_shellcode_1.bin对应: Windows 7 Ultimate 7601 Service Pack 1 Windows 7 Ultimate 6.1