吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 609|回复: 0
收起左侧

[Android 原创] 某乖逻辑分析签名逆向与开发云查询设备情况系统

  [复制链接]
xingtuyu01 发表于 2026-10-29 19:46

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 设备读取流程分析

抓包截图如下:

reqable抓包截图1.png

简单的程序流程为:

扫描洗衣机二维码 → 获取设备信息 → 判断设备可用性 → 选择洗涤项目(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)列表供用户选择。完整调用链如下:

  1. 扫码解析设备
POST /goods/scan/v2
请求体: NQT=3d********************&token=6******************
  • NQT = 洗衣机二维码内容(UUID 格式)
  • 响应返回设备归属:
{"code":0,"data":{
  "id":"11*******55",              // goodsId
  "shopId":2********,
  "categoryCode":"00",
  "categoryName":"洗衣机",
  "useModel":"share"               // 共享模式
}}
  1. 拉去设备详情
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
}}
  1. 可用性判断来去可选项目

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,实现全流程免费建站,再去白嫖一个二级域名即可,全程免费哦!

免费评分

参与人数 1吾爱币 +1 收起 理由
buluo533 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-11-5 10:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表