1 反抓包绕过
通过扫描洗衣机二维码,尝试抓包获取软件读取设备的逻辑时,发现启动系统道理抓包的情况加,软件扫描不跳转,猜测存在反抓包机制。
使用apkchecker检查软件,扫描提示未检测到加固特征,但是却又输出了大量的root检测,反调试检测的报告。
- 检测类型: ROOT(true) 模拟器(true) 反调试(true) 代理(true) SDK(true) 硬编码(false) 证书(true)
- 最大文件大小: 500 MB
- 递归扫描: true
- 加固特征扫描结果
- 未发现加固特征
- 安全检测特征扫描结果
- ROOT检测特征
- classes11.dex -> /data/local/bin/su (SU二进制文件常见路径)
- classes11.dex -> /data/local/su (SU二进制备用路径)
- classes11.dex -> /data/local/xbin/su (Xposed框架SU路径)
- classes11.dex -> /sbin/su (系统分区SU文件)
- classes11.dex -> /su/bin/su (Systemless SU路径)
- classes11.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes11.dex -> /system/bin/failsafe/su (故障安全模式SU)
- classes11.dex -> /system/bin/su (系统内置SU)
- classes11.dex -> /system/sbin/su (系统分区备用SU路径)
- classes11.dex -> /system/sd/xbin/su (SD卡扩展SU路径)
- classes11.dex -> /system/xbin/su (常见SU存放路径)
- classes11.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes11.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes11.dex -> /system/xbin/su (常见SU存放路径)
- classes11.dex -> /vendor/bin/su (厂商分区SU文件)
- classes11.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes11.dex -> /vendor/bin/ (厂商Root工具目录(分段检测))
- classes12.dex -> /system/bin/su (系统内置SU)
- classes12.dex -> /system/xbin/su (常见SU存放路径)
- classes12.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes13.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes13.dex -> /system/bin/su (系统内置SU)
- classes13.dex -> /system/xbin/su (常见SU存放路径)
- classes13.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes13.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes14.dex -> /data/local/bin/su (SU二进制文件常见路径)
- classes14.dex -> /data/local/su (SU二进制备用路径)
- classes14.dex -> /data/local/xbin/su (Xposed框架SU路径)
- classes14.dex -> /sbin/.magisk (Magisk临时目录)
- classes14.dex -> /sbin/su (系统分区SU文件)
- classes14.dex -> /su/bin/su (Systemless SU路径)
- classes14.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes14.dex -> /system/bin/failsafe/su (故障安全模式SU)
- classes14.dex -> /system/bin/su (系统内置SU)
- classes14.dex -> /system/sbin/su (系统分区备用SU路径)
- classes14.dex -> /system/sd/xbin/su (SD卡扩展SU路径)
- classes14.dex -> /system/xbin/su (常见SU存放路径)
- classes14.dex -> /vendor/bin/su (厂商分区SU文件)
- classes14.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes14.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes14.dex -> /vendor/bin/ (厂商Root工具目录(分段检测))
- classes14.dex -> com.kingroot.kinguser (KingRoot主程序)
- classes14.dex -> me.weishu.exp (太极框架)
- classes15.dex -> /data/su (SU配置目录)
- classes15.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes15.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes15.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes15.dex -> /vendor/bin/ (厂商Root工具目录(分段检测))
- classes15.dex -> de.robv.android.xposed.installer (Xposed安装器)
- classes3.dex -> /system/bin/su (系统内置SU)
- classes3.dex -> /system/xbin/su (常见SU存放路径)
- classes3.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes4.dex -> /data/local/bin/su (SU二进制文件常见路径)
- classes4.dex -> /data/local/su (SU二进制备用路径)
- classes4.dex -> /data/local/xbin/su (Xposed框架SU路径)
- classes4.dex -> /sbin/su (系统分区SU文件)
- classes4.dex -> /su/bin/su (Systemless SU路径)
- classes4.dex -> /system/bin/failsafe/su (故障安全模式SU)
- classes4.dex -> /system/bin/su (系统内置SU)
- classes4.dex -> /system/sd/xbin/su (SD卡扩展SU路径)
- classes4.dex -> /system/xbin/su (常见SU存放路径)
- classes4.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes5.dex -> /data/local/bin/su (SU二进制文件常见路径)
- classes5.dex -> /data/local/su (SU二进制备用路径)
- classes5.dex -> /data/local/xbin/su (Xposed框架SU路径)
- classes5.dex -> /sbin/su (系统分区SU文件)
- classes5.dex -> /su/bin/su (Systemless SU路径)
- classes5.dex -> /system/app/Kinguser.apk (Kingroot安装包)
- classes5.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes5.dex -> /system/bin/failsafe/su (故障安全模式SU)
- classes5.dex -> /system/bin/su (系统内置SU)
- classes5.dex -> /system/sbin/su (系统分区备用SU路径)
- classes5.dex -> /system/sd/xbin/su (SD卡扩展SU路径)
- classes5.dex -> /system/xbin/su (常见SU存放路径)
- classes5.dex -> /vendor/bin/su (厂商分区SU文件)
- classes5.dex -> Kinguser.apk (Kingroot安装包(分段检测))
- classes5.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes5.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes5.dex -> /vendor/bin/ (厂商Root工具目录(分段检测))
- classes5.dex -> com.chelpus.lackypatch (Lucky Patcher工具)
- classes5.dex -> com.dimonvideo.luckypatcher (Lucky Patcher官方包名)
- classes5.dex -> com.koushikdutta.rommanager (Rom Manager刷机工具)
- classes5.dex -> com.koushikdutta.superuser (Koush's Superuser)
- classes5.dex -> com.noshufou.android.su (Superuser官方包名)
- classes5.dex -> com.noshufou.android.su.elite (Superuser付费版)
- classes5.dex -> com.ramdroid.appquarantine (应用隔离工具(需root))
- classes5.dex -> com.thirdparty.superuser (第三方Superuser应用)
- classes5.dex -> com.yellowes.su (早期SuperSU变种)
- classes5.dex -> com.zachspong.temprootremove (临时Root工具)
- classes5.dex -> eu.chainfire.supersu (Chainfire SuperSU)
- classes5.dex -> de.robv.android.xposed.installer (Xposed安装器)
- classes6.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes6.dex -> /system/bin/su (系统内置SU)
- classes6.dex -> /system/xbin/su (常见SU存放路径)
- classes6.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes6.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes9.dex -> /data/local/bin/su (SU二进制文件常见路径)
- classes9.dex -> /data/local/su (SU二进制备用路径)
- classes9.dex -> /data/local/xbin/su (Xposed框架SU路径)
- classes9.dex -> /dev/com.koushikdutta.superuser.daemon/ (Superuser守护进程socket)
- classes9.dex -> /sbin/su (系统分区SU文件)
- classes9.dex -> /su/bin/su (Systemless SU路径)
- classes9.dex -> /system/app/Superuser.apk (Superuser安装包)
- classes9.dex -> /system/bin/failsafe/su (故障安全模式SU)
- classes9.dex -> /system/bin/su (系统内置SU)
- classes9.dex -> /system/etc/init.d/99SuperSUDaemon (SuperSU守护进程脚本)
- classes9.dex -> /system/sd/xbin/su (SD卡扩展SU路径)
- classes9.dex -> /system/xbin/daemonsu (SuperSU守护进程)
- classes9.dex -> /system/xbin/su (常见SU存放路径)
- classes9.dex -> Superuser.apk (Superuser安装包(分段检测))
- classes9.dex -> /system/xbin/ (常见Root工具目录(分段检测))
- classes9.dex -> com.koushikdutta.superuser (Koush's Superuser)
- classes9.dex -> com.koushikdutta.superuser (Koush's Superuser)
- classes9.dex -> com.noshufou.android.su (Superuser官方包名)
- classes9.dex -> com.thirdparty.superuser (第三方Superuser应用)
- classes9.dex -> com.topjohnwu.magisk (Magisk Manager)
- classes9.dex -> com.yellowes.su (早期SuperSU变种)
- classes9.dex -> com.kingroot.kinguser (KingRoot主程序)
- classes9.dex -> com.alephzain.framaroot (Framaroot工具)
- classes9.dex -> eu.chainfire.supersu (Chainfire SuperSU)
- 模拟器检测特征
- classes11.dex -> /dev/socket/qemud (QEMU守护进程socket)
- classes11.dex -> /dev/qemu_pipe (QEMU管道通信接口)
- classes11.dex -> 000000000000000 (模拟器默认IMEI)
- classes11.dex -> goldfish (Android模拟器内核标识)
- classes11.dex -> ro.kernel.qemu (QEMU内核属性标识)
- classes11.dex -> test-keys (测试版系统特征)
- classes12.dex -> 000000000000000 (模拟器默认IMEI)
- classes12.dex -> eth0 (模拟器网络接口)
- classes13.dex -> emulator (模拟器标识)
- classes13.dex -> 000000000000000 (模拟器默认IMEI)
- classes13.dex -> 000000000000000 (模拟器默认IMEI)
- classes13.dex -> emulator (模拟器标识)
- classes13.dex -> emulator (模拟器标识)
- classes13.dex -> emulator (模拟器标识)
- classes13.dex -> generic_x86 (模拟器常见ABI)
- classes13.dex -> goldfish (Android模拟器内核标识)
- classes14.dex -> /dev/socket/qemud (QEMU守护进程socket)
- classes14.dex -> /dev/qemu_pipe (QEMU管道通信接口)
- classes14.dex -> generic_x86 (模拟器常见ABI)
- classes14.dex -> emulator (模拟器标识)
- classes14.dex -> goldfish (Android模拟器内核标识)
- classes14.dex -> test-keys (测试版系统特征)
- classes15.dex -> emulator (模拟器标识)
- classes15.dex -> /dev/socket/qemud (QEMU守护进程socket)
- classes15.dex -> /dev/qemu_pipe (QEMU管道通信接口)
- classes15.dex -> emulator (模拟器标识)
- classes15.dex -> eth0 (模拟器网络接口)
- classes15.dex -> generic_x86 (模拟器常见ABI)
- classes15.dex -> goldfish (Android模拟器内核标识)
- classes15.dex -> ro.kernel.qemu (QEMU内核属性标识)
- classes15.dex -> test-keys (测试版系统特征)
- classes3.dex -> emulator (模拟器标识)
- classes4.dex -> ro.kernel.qemu (QEMU内核属性标识)
- classes4.dex -> test-keys (测试版系统特征)
- classes5.dex -> 000000000000000 (模拟器默认IMEI)
- classes5.dex -> eth0 (模拟器网络接口)
- classes5.dex -> emulator (模拟器标识)
- classes5.dex -> eth0 (模拟器网络接口)
- classes5.dex -> goldfish (Android模拟器内核标识)
- classes5.dex -> test-keys (测试版系统特征)
- classes7.dex -> emulator (模拟器标识)
- classes7.dex -> goldfish (Android模拟器内核标识)
- classes9.dex -> 000000000000000 (模拟器默认IMEI)
- classes9.dex -> emulator (模拟器标识)
- classes9.dex -> emulator (模拟器标识)
- classes9.dex -> emulator (模拟器标识)
- classes9.dex -> goldfish (Android模拟器内核标识)
- classes9.dex -> test-keys (测试版系统特征)
- 反调试检测特征
- classes14.dex -> XposedBridge.jar (Xposed桥接文件检测)
- classes14.dex -> com.android.internal.os.ZygoteInit (Zygote初始化检测)
- classes14.dex -> com.saurik.substrate.MS$2 (Substrate框架检测)
- classes14.dex -> com.saurik.substrate (Substrate框架检测)
- classes14.dex -> de.robv.android.xposed.XposedBridge (Xposed框架检测)
- classes14.dex -> ro.debuggable (系统调试属性检测)
- classes15.dex -> /proc/self/status (TracerPid状态检测)
- classes15.dex -> XposedBridge.jar (Xposed桥接文件检测)
- classes15.dex -> com.android.internal.os.ZygoteInit (Zygote初始化检测)
- classes15.dex -> com.saurik.substrate.MS$2 (Substrate框架检测)
- classes15.dex -> de.robv.android.xposed.XposedBridge (Xposed框架检测)
- classes15.dex -> com.saurik.substrate (Substrate框架检测)
- classes5.dex -> /proc/self/status (TracerPid状态检测)
- classes5.dex -> XposedBridge.jar (Xposed桥接文件检测)
- classes5.dex -> com.saurik.substrate (Substrate框架检测)
- classes5.dex -> de.robv.android.xposed.XposedBridge (Xposed框架检测)
- classes5.dex -> ptrace (Ptrace调试检测)
- classes5.dex -> ro.debuggable (系统调试属性检测)
- classes9.dex -> de.robv.android.xposed.XposedBridge (Xposed框架检测)
- classes9.dex -> ro.debuggable (系统调试属性检测)
- 代理检测特征
- classes10.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes11.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes12.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes13.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes14.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes14.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes15.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes5.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes6.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes6.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes6.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- classes6.dex -> Lokhttp3/internal/proxy/NullProxySelector; (OkHttp空代理选择器)
- classes9.dex -> Ljavax/net/ssl/X509TrustManager; (自定义证书信任管理器)
- 第三方SDK特征扫描结果
- Alibaba
- 金融级实人认证 SDK -> lib/arm64-v8a/libaliyunaf.so
- 金融级实人认证 SDK -> lib/arm64-v8a/libfacedevice.so
- 金融级实人认证 SDK -> lib/arm64-v8a/libtoyger.so
- 金融级实人认证 SDK -> lib/arm64-v8a/libzkfv_tj.so
- 阿里聚安全 -> lib/arm64-v8a/libsgcore.so
- Aliyun
- 日志服务 SLS -> lib/arm64-v8a/libsls_producer.so
- Android
- C++ 共享库 -> lib/arm64-v8a/libc++_shared.so
- ByteDance
- Pangle SDK -> lib/arm64-v8a/libpanglearmor.so
- Pangle SDK -> lib/arm64-v8a/libpangleflipped.so
- Pangle SDK -> lib/arm64-v8a/libtobEmbedEncrypt.so
- Google
- Jetpack Graphics -> lib/arm64-v8a/libandroidx.graphics.path.so
- Huawei
- HMS Scan Kit -> lib/arm64-v8a/libscannative.so
- Tencent
- MMKV -> lib/arm64-v8a/libmmkv.so
- Mars -> lib/arm64-v8a/libmarsstn.so
- Mars -> lib/arm64-v8a/libmarsxlog.so
- 腾讯地图 SDK -> lib/arm64-v8a/libtencentloc.so
- Umeng
- 移动统计分析 -> lib/arm64-v8a/libumeng-spy.so
- WebRTC
- WebRTC -> lib/arm64-v8a/libjingle_peerconnection_so.so
- aaalgo
- xnn -> lib/arm64-v8a/libxnn.so
- xnn -> lib/arm64-v8a/libxnnloader.so
- opendesigndev
- liboctopus -> lib/arm64-v8a/liboctopus.so
- 杭州艾狄墨搏信息服务有限公司
- Tianmu SDK -> lib/arm64-v8a/libnative-tianmu-common.so
- Tianmu SDK -> lib/arm64-v8a/libnative-tianmu-lib.so
- 银联
- 银联 SDK -> lib/arm64-v8a/libentryexpro.so
- 银联 SDK -> lib/arm64-v8a/libuptsmaddon.so
- 高德
- 高德 SDK -> lib/arm64-v8a/libapssdk.so
- 证书扫描结果
- 未发现证书文件
猜测是最新的加固特征还未更新写入checker,导致未检测到加固特征。
直接使用dsh扫描,输出结果如下:
app 集成了字节火山引擎 MobSec 安全 SDK(com.volcengine.mobsecBiz.matrix.pgla 生成 SSLContext)、
阿里反作弊(aliagainstcheatingId)、
爱加密加固(libijiami_1011.so)。
继续push ai分析反抓包逻辑
1.1 反抓包机制分析
核心是软件仅信任系统证书,不信任用户证书
res/xml/network_security_config.xml 配置如下:
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" /> <!-- 只信任系统 CA 证书 -->
</trust-anchors>
</base-config>
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" /> <!-- 仅 debuggable 时额外信任用户证书 -->
</trust-anchors>
</debug-overrides>
</network-security-config>
关键点:
- base-config 的 trust-anchors 只包含
system,没有 user。
- 抓包工具(Reqable / Charles / Fiddler 等)的根证书只能以「用户证书」身份安装到手机(非 root 无法写系统证书库)。
- App 是 release 包(
android:debuggable 未设置 = false),所以 debug-overrides(信任 user)不生效。
- 结论:TLS 握手时,App 拒绝信任抓包工具的中间人证书 → HTTPS 请求全部失败或被静默丢弃,抓不到明文。
1.2 反抓包绕过
既然 App 只信任系统证书,就修改 App 的 networkSecurityConfig,让它额外信任用户证书;再配合 VPN 模式抓包绕过 Proxy.NO_PROXY。
| 方案 |
是否需 root |
原理 |
| WiFi 代理 + 用户证书 |
否 |
代理 + 用户证书 |
| 改包 + VPN 抓包(采用) |
否 |
改 networkSecurityConfig 信任 user 证书 + Reqable VPN 透明抓包 |
| 装系统证书 |
是 |
把 CA 写进系统信任库 |
| LSPosed/JustTrustMe hook |
是 |
hook 绕过证书校验 |
被次采用直接修改apk+reqable vpn模式实现反抓包绕过。
解包确认位置:
# 解包(-s 跳过 smali,保留原始 dex,加速)
apktool d -s pangguai.apk -o apktool_out
# 确认反抓包配置
cat apktool_out/res/xml/network_security_config.xml
修改 res/xml/network_security_config.xml,在 base-config 的 trust-anchors 中追加 user 证书:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" /> <!-- ★ 新增:信任用户证书 -->
</trust-anchors>
</base-config>
apktool 解码复合 Gravity 值存在 bug,会生成非法 layout_gravity="0x0",导致 aapt2 报错:
res/layout/act_my_info.xml:33: '0x0' is incompatible with attribute layout_gravity
修复:把 android:layout_gravity="0x0" 改为合法值(如 center_horizontal)。
注意:重打包路径必须为纯英文(aapt2 对中文路径会乱码报 failed to open directory),需把解包目录复制到英文路径再执行 apktool b。
重打包+对其+签名
apktool b D:\temp\pgwork -o pangguai_patched.apk
zipalign -f -p 4 pangguai_patched.apk pangguai_aligned.apk
apksigner sign --ks %USERPROFILE%\.android\debug.keystore \
--ks-pass pass:android --key-pass pass:android \
--out pangguai_signed.apk pangguai_aligned.apk
apksigner verify --print-certs pangguai_signed.apk # 验证签名
随后奖手机上的apk卸载重新安装,避免签名冲突
随后使用reqable抓包,顺利抓到设备读取的全流程流量
2 设备读取流程分析
抓包截图如下:
简单的程序流程为:
扫描洗衣机二维码 → 获取设备信息 → 判断设备可用性 → 选择洗涤项目(SKU) → 下单支付 → 设备启动运行
2.1 请求中的设备标识字段
所有 userapi.qiekj.com 请求携带统一身份/设备信息。核心字段与取值:
| 字段 |
实测值 |
含义 |
来源 |
deviceId |
** |
OAID(匿名设备标识),非 IMEI |
CacheUtil.INSTANCE.getOaid() |
token |
*** |
登录态 token |
CacheUtil.getToken() |
brand / phoneBrand |
xxx(手机品牌) |
设备品牌 |
Build.BRAND |
model |
xxxx |
设备型号 |
Build.MODEL |
os |
1 |
操作系统(1=Android) |
常量 |
channel |
android_app |
渠道 |
应用配置 |
2.2 进入选择项目界面
「选择项目」界面 ,即 扫描设备后展示洗涤项目(SKU)列表供用户选择。完整调用链如下:
- 扫码解析设备
POST /goods/scan/v2
请求体: NQT=3d********************&token=6******************
NQT = 洗衣机二维码内容(UUID 格式)
- 响应返回设备归属:
{"code":0,"data":{
"id":"11*******55", // goodsId
"shopId":2********,
"categoryCode":"00",
"categoryName":"洗衣机",
"useModel":"share" // 共享模式
}}
- 拉去设备详情
POST /goods/normal/details
请求体: goodsId=1101849555&token=...
响应
{"code":0,"data":{
"name":"**号楼*层*号洗衣机",
"deviceId":52******3, // 设备编号(数字)
"imei":"8**********0", // 洗衣机 IMEI
"machineId":"2************9",
"communication":"serial", // 串口通信
"isBluetooth":0,
"payment":"before", // 先付款后使用
"deviceErrorCode":null, // ★ 设备状态核心字段(null=空闲可用)
"deviceErrorMsg":null,
"remainTime":0, // 剩余运行时间(0=空闲)
"soldState":1,
"stockType":102
}}
- 可用性判断来去可选项目
com.qiekj.user.ui.activity.scan.LockingAct(扫码后锁定/选择页)根据 deviceErrorCode 分流:
// LockingAct.createObserver$lambda$3 核心逻辑
if (deviceErrorMsg == null || deviceErrorMsg.isEmpty()
|| (deviceErrorCode.equals("4204") && isBluetooth==1 && !payment.equals("before"))) {
// ★ 设备正常 → 拉取可用项目列表
((ScanCodeViewModel) getMViewModel()).canUseList(goodsDetail.getGoodsId());
} else {
// 设备异常 → 跳转 DeviceFaultAct(故障页)
DeviceFaultAct.startAction(...);
}
canUseList(goodsId) 对应接口 POST /appointNew/canUseList(查询当前设备可用项目)
- 最终展示项目列表的接口为
POST /goods/normal/skus,返回洗涤项目 SKU:
{"code":0,"data":[
{"skuId":1058411528,"name":"单脱","price":"0.00","function":{"state":null,"faultMessage":null}},
{"skuId":1058411529,"name":"大物洗","price":"4.00","function":{"state":null}},
{"skuId":1058411530,"name":"标准洗","price":"3.5","function":{"state":null}},
...
]}
2.3 设备状态判断
设备运行/空闲/异常状态的唯一权威来源是 goods/normal/details 响应中的 deviceErrorCode 字段。逆向确认的完整映射(LockingAct):
| deviceErrorCode |
含义 |
提示文案 |
null / 空 |
✅空闲可用 |
进入「选择项目」界面 |
"2" |
⏳设备工作中(运行中) |
"设备工作中,请更换设备使用" |
"7" |
📅 设备被预约 |
"设备被预约,请更换设备使用" |
"-100" |
⚠️ 连接超时 |
"连接超时了" |
"4000" |
🔗 设备未绑定 |
"设备未绑定,请联系商家绑定后再使用" |
"4107" |
🔧 设备故障 |
"设备故障,请联系商家处理" |
"4111" |
⛔ 设备已停用 |
"设备已停用,请联系商家处理" |
"4204" |
📴 设备离线 |
"设备离线,请检查设备是否通电(若刚通电需等待约3分钟)" |
"5023" |
❗ 其他故障 |
"故障码【5023】"+ deviceErrorMsg |
辅助字段:
remainTime:设备剩余运行时间(分钟)。0 = 空闲;>0 = 正在运行,表示还需多久结束。
soldState:售卖/上架状态(1=正常售卖)。
stockType:库存类型(102)。
supportAppUserFinish:是否支持用户在 App 端提前结束。
判断流程整体如下:
扫码 → /goods/normal/details 返回 GoodsDetail
│
├─ deviceErrorCode == null/空 → 空闲 → 进入选择项目 → 下单 → 设备启动
├─ deviceErrorCode == "2" → 运行中(占用) → 提示"设备工作中"
├─ deviceErrorCode == "7" → 被预约 → 提示更换设备
├─ deviceErrorCode == "4204" → 离线 → 提示检查通电
└─ 其他("4107"/"4111"/...) → 故障/停用 → 跳转故障页
3 签名算法逆向
抓包可以看到每个请求都携带了签名
随意必须获取到sign的生成算法
请求体中和sign相关的字段有两个
一个是时间戳timestamp,为13毫秒级;一个为sign,64 位小写 hex(SHA-256)
反编译apk后搜索关键词
逆向技巧:签名逻辑几乎必然写在 Interceptor 里(因为要统一给每个请求加签),搜索 Interceptor + MessageDigest 是最快的定位路径。
搜索关键词:
搜索词:sign / Sign / Interceptor / timestamp / MessageDigest / SHA
有这两个文件命中:
com/qiekj/user/http/interceptor/HeadInterceptor.java ← header 签名
com/qiekj/user/http/interceptor/SignInterceptor.java ← body 签名
HeadInterceptor.intercept() 反编译代码(关键部分,已做混淆还原注释):
public Response intercept(Interceptor.Chain chain) {
// 1. 硬编码密钥:Base64 解码
String secret = new String(Base64.decode(
"bkZVOXBiRzhZUW9BZTFrRmgrRTdleXJkbFNMZ2x3RUplQTB3d0hCMWo1bz0=", 0));
// 2. 当前毫秒时间戳
String valueOf = String.valueOf(System.currentTimeMillis()); // = timestamp
// 3. 计算 SHA-256
MessageDigest messageDigest = MessageDigest.getInstance(x.dW); // x.dW = "SHA-256"
messageDigest.update(
("appSecret=" + secret
+ "&channel=android_app"
+ "×tamp=" + valueOf
+ "&token=" + token
+ "&version=" + AppUtils.getAppVersionName() // "1.141.0"
+ "&" + request.url().encodedPath() // 如 "/goods/normal/details"
).getBytes(StandardCharsets.UTF_8));
String str = byte2HexSHA(messageDigest.digest()); // 小写 hex
// 4. 写入请求头
Request.Builder header = request.newBuilder()
.header("Authorization", token)
.header("Version", version)
.header("channel", "android_app")
.header("phoneBrand", brand)
.header("deviceId", oaid)
.header("timestamp", valueOf) // a.k 实为 "timestamp"
.header("sign", str); // f.Y 实为 "sign"
...
}
由此还原出 header 签名算法:
timestamp = 当前毫秒时间戳
signString = "appSecret=" + secret
+ "&channel=android_app"
+ "×tamp=" + timestamp
+ "&token=" + token
+ "&version=1.141.0"
+ "&" + 接口路径
sign = SHA256(signString).toLowerCaseHex()
对于混淆的常量,不必逐个去翻第三方 SDK 源码,直接用抓包里的真实 header 名/值反推,再用回算验证即可。
| 混淆引用 |
真实值 |
来源确认 |
x.dW(com.huawei.openalliance.ad.constant.x) |
"SHA-256" |
sign 为 64 位 hex + 回算验证 |
f.Y(com.anythink.core.common.m.f) |
"sign" |
抓包 header 名 |
a.k(com.alipay.sdk.m.w.a) |
"timestamp" |
抓包 header 名 |
e.g(com.alipay.sdk.m.s.e) |
"Version" |
抓包 header 名 |
然后去寻找appSecret
String secret = new String(Base64.decode("bkZVOXBiRzhZUW9BZTFrRmgrRTdleXJkbFNMZ2x3RUplQTB3d0hCMWo1bz0=", 0));
解码得到:
appSecret = nFU9pbG8YQoAe1kFh+E7eyrdlSLglwEJeA0wwHB1j5o=
最终伪签名代码为:
import hashlib, time, requests
BASE_URL = "https://userapi.qiekj.com"
TOKEN = "62171*******************************0695e156ddd"
SECRET = "nFU9pbG8YQoAe1kFh+E7eyrdlSLglwEJeA0wwHB1j5o="
CHANNEL = "android_app"
VERSION = "1.141.0"
DEVICE_ID= "2ad789**********************************82b86e32b8eb23f915fe"
BRAND = "****"
UA = ("QEUser/1.141.0 (com.qiekj.user; build:273; Android 16; "
"userChannel:android_app; version:1.141.0) OkHttp/4.12.0")
def call(path: str, body: dict) -> dict:
ts = str(int(time.time() * 1000))
sign_str = (f"appSecret={SECRET}&channel={CHANNEL}×tamp={ts}"
f"&token={TOKEN}&version={VERSION}&{path}")
sign = hashlib.sha256(sign_str.encode("utf-8")).hexdigest()
headers = {
"Authorization": TOKEN,
"Version": VERSION,
"channel": CHANNEL,
"phoneBrand": BRAND,
"deviceId": DEVICE_ID,
"timestamp": ts,
"sign": sign,
"User-Agent": UA,
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
}
# body 里统一补 token
body = {**body, "token": TOKEN}
r = requests.post(BASE_URL + path, data=body, headers=headers, timeout=10)
return r.json()
4 hono框架开发私有化网站实现设备状态查询
相关代码在:https://github.com/HEUdbh/pg_hono
使用hono框架,一键部署cloudfare,实现全流程免费建站,再去白嫖一个二级域名即可,全程免费哦!