高中生

- 金币
- 211
- 好评
- 10
- 信誉
- 100
|
本帖最后由 LivedForward 于 2026-2-10 11:13 编辑
保卫萝卜3 apk自校验:
1.Native C++ JIT(Shellcode)校验多个classes.dex文件的checksum值。
2.PackageInfo类的CREATOR静态字段是否被篡改。
3.Java层使用PackageManager获取自身apk
包名的PackageInfo,再从PackageInfo中获取
签名数组(Signature[])。
一.去校验
apktool2.4.0-250812版本 Native C++层使用的是SECCOMP_IOCTL_NOTIFY模式拦截Linux syscall系统调用。
Java层是使用Java动态代理来拦截PMS的签名获取方法以及重写Parcelable.Creator<PackageInfo>替换CREATOR字段来过签。
所以去除保卫萝卜3自校验先使用apktool2.4.0-250812版本删除签名校验功能,勾选上添加原始apk来检查完整性。
然后在最后一个dex文件里面定位到.method private static killPM(Ljava/lang/String;Ljava/lang/String;)V方法,
在方法体里面第一行(.registers声明之后)添加return-void保存即可,这样便去除了自校验。(注意:这只是删除替换CREATOR这种去签方式,Java动态代理PMS还是存在,在.method private initProxy(Landroid/content/Context;)V方法里面)
二.定位内购联网查询订单状态代码
1.先注入日志,再注入文件提供器,签名apk。
2.去保卫萝卜3里面多内购取消几次,然后打开日志文件,发现日志里面最多的就是com.u8.sdk.utils.U8HttpUtils
->httpPost(0270.java:2)
log=,调用U8HttpUtils类的httpPost方法。
这里log=后面的字符串是使用的URL Encode编码方式,解码一下:
然后去classes.dex文件里面定位com.u8.sdk.utils.U8HttpUtils类的httpPost方法,
发现com.u8.sdk.utils.U8HttpUtils类的httpPost方法被三个类(包含一个内部类)所调用,但是前面
两个是与log日志有关,不是重点,直接点进去U8Proxy类,发现是
method public static check(Lcom/u8/sdk/PayParams;)Lcom/u8/sdk/verify/UCheckResult;
方法调用了com.u8.sdk.utils.U8HttpUtils类的httpPost方法,
反编译一下U8Proxy这个类,看看method public static check(Lcom/u8/sdk/PayParams;)Lcom/u8/sdk/verify/UCheckResult;
方法里面有什么实现和操作:大概就是实例化一个HashMap,然后往里面存放一些内购的下单参数,以Key=Value形式存放。
注意一下这三个部分的代码,和UCheckResult这个类。
- String str2 = "";
- if (TextUtils.isEmpty(str2)) {
- return null;
- }
- try {
- JSONObject jSONObject = new JSONObject(str2);
- return new UCheckResult(jSONObject.optInt("suc", 0), jSONObject.optInt("state", 0));
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
复制代码
那么这个方法method public static check(Lcom/u8/sdk/PayParams;)Lcom/u8/sdk/verify/UCheckResult;
又是哪个方法在调用呢?是这个类Lcom/u8/sdk/U8SDKSingle;这个类里面有一个匿名内部类和两个内部类继承了AsyncTask类,
就是在线程里面调用U8Proxy.check方法,do{}while()循环,每隔3000ms调用一次,总共调用10次。
然后回调U8SDKSingle.access$200(this.a, this.b, uCheckResult);方法,access$200和access$300
又去分别调用Lcom/u8/sdk/U8SDKSingle;->onPayCheckResult和Lcom/u8/sdk/U8SDKSingle;->onPayCheckRetryResult
两个方法。
现在反编译一下Lcom/u8/sdk/U8SDKSingle;
就是判断第二个参数UCheckResult uCheckResult的int类型的state私有成员变量的
值是否等于U8SDKSingle.STATE_PAY_SUC这个私有的静态final int型变量(1)。
那现在如何让它的后台校验内购结果走向成功,很简单,把UCheckResult类的getState()I方法强制
返回1,或者在U8Proxy.check方法里面实例化一个UCheckResult,并将构造器第二个int类型的值
(state)传入1:
1.修改UCheckResult.getState()I
const/4 v0, 1
2.修改U8Proxy.check(Lcom/u8/sdk/PayParams;)Lcom/u8/sdk/verify/UCheckResult;
const/4 v1, 0x0
const/4 p0, 0x1
new-instance v3, Lcom/u8/sdk/verify/UCheckResult;
invoke-direct {v3, v1, p0}, Lcom/u8/sdk/verify/UCheckResult;-><init>(II)V
:try_end_115
.catch Ljava/lang/Exception; {:try_start_8 .. :try_end_115}
:catch_133
return-object v3
注意,还需要修改U8SDKSingle$c.doInBackground方法,它这个联网获取内购支付
结果的逻辑是UCheckResult check变量不等于null而且UCheckResult.getState()返回1
才break退出循环,我们需要修改使其轮询1次就退出,将const-wide/16 v1, 0xbb8改为
const-wide/16 v1, 1000(每隔1000ms查询一次内购支付结果),
:cond_3e
const/16 v1, 0xa改为1(总共循环1次)
到此为止,就完成了后台联网校验内购结果的修改。
三.修改内购结果
修改Lcom/u8/sdk/luobo/LuoboSDK; LuoboSDK类的.method public onPayResult(I)V方法,
去掉if-nez p1, :cond_e这条判断语句就行。
四.强制微信扫码登录
修改Lcom/u8/sdk/luobo/LuoboUser; LuoboUser类的loginCustom(Ljava/lang/String;)V 方法:
按照如下图所示位置,添加const-string p1, "2"。
四.登录
在此界面需要截屏,使用微信扫码登录:
成品:
https://www.123865.com/s/lN7UVv-vKRJ
另外,apktool SECCOMP_IOCTL_NOTIFY模式去签不是很稳定,推荐使用修改的保卫萝卜3先购买商品,
然后再安装官方版本使用即可。
别短时间内生成购买太多订单,我的两个号都解锁了飞行员和萌萌哒角色,有十五万砖石,号的状态都是正常的。
SECCOMP_IOCTL_NOTIFY模式仅支持Android15及以上。
SimpleHook版配置,直接安装小米渠道官方版即可,理论上支持Android5.0-16:
SimpleHook配置
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
-
查看全部评分
总评分:好评 +2
金币 +4
|