Mist520 发表于 2023-11-19 22:41

去4某99盒子强制升级

Java层hook初体验(五)
app:4e 44 4d 35 4f 65 61 34 75 4f 61 49 6a 2b 65 62 6b 75 57 74 6b 41 3d 3d(base64+hex)
android:versionCode="1664" android:versionName="6.2.5.30"
工具:httpCanary,frida14.2.18,webstorm 2021.1,jadx
设备:root的pixel
本文所有的注入均是spawn方式注入的。
打开app是这样的(第一次打开是没有叉号的,是一个强制升级的弹窗,点击升级,我立马退出之后,再进来就成这样了)


点击叉掉,直接闪退,还不是强制升级,背景一看敬请期待,看来不能光hook弹窗,要返回相应的值了。
怎么办呢?
jadx反编译一下,搜一下更新,发现很多,但没有零流量更新。
那就抓个包看看吧,很不错的是发现

除了738,不知道是什么之外,但估计也是个版本号,其余的不就是我们的versionCode versionName吗
一开始我还没注意到versionName,就直接开始搜versionCode,找到和包名相关的,多次尝试之后(发现调用了此函数)。

let GameCenterConfig = Java.use("com.m4399.gamecenter.GameCenterConfig");
GameCenterConfig["getVersionCode"].implementation = function () {
    // console.log('getVersionCode is called');
    return this.getVersionCode();
};
会发现确实走了该函数,且其返回值是1664,改成多少呢。查找该函数的用例。

追进去,看到一个lastversioncode,非常符合我的想象,直接hook


let AppUpgradeProvider = Java.use("com.upgrade.provider.AppUpgradeProvider");
AppUpgradeProvider["getLastVersionCode"].implementation = function () {
    console.log('getLastVersionCode is called');
    let ret = this.getLastVersionCode();
    console.log('getLastVersionCode ret value is ' + ret);
    return ret;
};

那么1664的修改值也得到了。

此时弹窗已经消失,但没法使用,此外登录,福利等界面都是空的

还得继续,那么738从哪来呢,继续搜versioncode

虽然都是versioncode,但很明显感觉这个和之前取的不是一个值,通过hook发现确实经过这里。
let PluginPackage = Java.use("com.m4399.plugin.PluginPackage");
PluginPackage.getVersionCode.implementation = function () {
    // console.log('getVersionCode is called');
    console.log(this.getVersionCode());
    return this.getVersionCode();
};

那最新的versioncode怎么找呢?也试一下last?发现没找到,最后我尝试了,安装最新版,但最新版明显有检测,frida注入几秒,就被结束进程,使用了葫芦娃改过的frida也无效,,抓包虽然可以抓,但内容明显被混淆过了,但很巧的是刚好可以执行之前获取versioncode的代码
let PluginPackage = Java.use("com.m4399.plugin.PluginPackage");
PluginPackage.getVersionCode.implementation = function () {
// console.log('getVersionCode is called');
console.log(this.getVersionCode());
return this.getVersionCode();
};
返回的值是914.那么return 914
卸掉新app,装回之前老的,这次总该拿下了吧
let PluginPackage = Java.use("com.m4399.plugin.PluginPackage");
PluginPackage.getVersionCode.implementation = function () {
    // console.log('getVersionCode is called');
    // console.log("PluginPackage.getVersionCode:",this.getVersionCode());
    return 914;
};
let GameCenterConfig = Java.use("com.m4399.gamecenter.GameCenterConfig");
GameCenterConfig["getVersionCode"].implementation = function () {
    // console.log('getVersionCode is called');
    // console.log(this.getVersionCode());
    return 2033;
};
一进去,果然没弹窗,也不再是敬请期待,还可以下载游戏,




就在高兴的时候,点到我,还是报错。当时忘了还有version name,就思考了很久是不是还有别的检测点。

这一看是toast ,尝试hook,发现确实是,但没打印出太多有效的
var toast=Java.use("android.widget.Toast");
toast.show.implementation=function (){
    showStack();
    console.log("toast.show:");
    return this.show;
}

一筹莫展的时候,突然想到app进入时候弹出来的7.9.1.16,就想到了包名。那根据老套路就是getVersionName,一搜还真是
GameCenterConfig["getVersionName"].implementation = function () {
    console.log('getVersionName is called');

    return this.getVersionName();
};
输出就是6.2.5.30
改成“7.9.1.16”,想着这下应该结束了。然而事情并没有结束。

还是没内容,有点费解了,再抓一次包

这里面不都改了吗继续往下看,还是没改全


还有什么地方取值呢,抱着猜测的想法就搜索getvalue,检索和包名相关最好还带有http类似字眼。
果不其然定位到很符合想象的函数

看来参数的传递直接是return的,更为不错的是,其他参数都可以写死。
那就直接替换返回。
let GameCenterHttpAgent = Java.use("com.m4399.gamecenter.GameCenterHttpAgent");
GameCenterHttpAgent["getHttpRequestAgent"].implementation = function () {
    // console.log('getHttpRequestAgent is called');
    let ret = this.getHttpRequestAgent();
    if(ret==="4399GameCenter/6.2.5.30(android;Pixel;10;1080x1794;WIFI;1664.914;upgrade)")
    {
      return "4399GameCenter/7.9.1.16(android;Pixel;10;1080x1794;WIFI;2033.914;upgrade)";
    }
    // console.log('getHttpRequestAgent ret value is ' + ret);

    return ret;
};
再来尝试一下。



终于没问题了,刷新也可以返回正常的界面了。
至此,去强制升级结束。
Java.perform(function (){
    function showStack() {
      console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
    }
    var str=Java.use("java.lang.String");
    str.getBytes .overload().implementation=function () {
      var result = this.getBytes();
      var strnew = str.$new(result);

      if (strnew.equals("6.2.5.30"||"738")) {
            // showStack();
            // console.log("getBytes.overload():",strnew);
      }

            return result;

    }

    str.getBytes.overload('java.lang.String').implementation=function (a){
      var result =this.getBytes(a);
      var strnew=str.$new(result,a);
      if (strnew.equals("6.2.5.30"||"738")) {
            // console.log("getBytes.overload('java.lang.String'):",strnew);
                       
      }
            return result;
    }
    let PluginPackage = Java.use("com.m4399.plugin.PluginPackage");
    PluginPackage.getVersionCode.implementation = function () {
      // console.log('getVersionCode is called');
      // console.log("PluginPackage.getVersionCode:",this.getVersionCode());
      return 914;
    };
    let GameCenterConfig = Java.use("com.m4399.gamecenter.GameCenterConfig");
    GameCenterConfig["getVersionCode"].implementation = function () {
      // console.log('getVersionCode is called');
      // console.log(this.getVersionCode());
      return 2033;
    };


    GameCenterConfig["getVersionName"].implementation = function () {
      console.log('getVersionName is called');
      return "7.9.1.16";
    };
    let GameCenterHttpAgent = Java.use("com.m4399.gamecenter.GameCenterHttpAgent");
    GameCenterHttpAgent["getHttpRequestAgent"].implementation = function () {
      // console.log('getHttpRequestAgent is called');
      let ret = this.getHttpRequestAgent();
      if(ret==="4399GameCenter/6.2.5.30(android;Pixel;10;1080x1794;WIFI;1664.914;upgrade)"){
            return "4399GameCenter/7.9.1.16(android;Pixel;10;1080x1794;WIFI;2033.914;upgrade)";
      }
      // console.log('getHttpRequestAgent ret value is ' + ret);

      return ret;
    };
   
    // let AppUpgradeProvider = Java.use("com.upgrade.provider.AppUpgradeProvider");
    // AppUpgradeProvider["getLastVersionCode"].implementation = function () {
    //   console.log('getLastVersionCode is called');
    //   let ret = this.getLastVersionCode();
    //   console.log('getLastVersionCode ret value is ' + ret);
    //   return ret;//2033
    // };
    // var toast=Java.use("android.widget.Toast");
    // toast.show.implementation=function (){
    //   showStack();
    //   console.log("toast.show:");
    //   return this.show;
    // }

})
总结:
感觉这次java层的hook有些神奇,打印的堆栈有些不准确,更多的靠的猜测有运气和一定的经验,有些地方还是没有hook全的,但正常使用没问题

正己 发表于 2023-11-20 18:55

frida的代码用代码块包裹一下会比较美观

jnb20000 发表于 2023-11-20 12:30

童年回忆啊

Mecamodore 发表于 2023-11-20 12:36

感谢分享,奇怪的知识增加了

北京夜未眠 发表于 2023-11-20 12:36

楼主继续加油

wmwgi84 发表于 2023-11-20 13:13

膜拜,期待成功

seanall 发表于 2023-11-20 13:32

继续加油!!!

areplay 发表于 2023-11-20 14:24

看不懂,但是感觉很牛X!!

forever96 发表于 2023-11-20 15:53

看不懂,但是感觉很牛X!!

RiverGod 发表于 2023-11-20 15:58

感谢分享

Kkkkkkky 发表于 2023-11-20 16:37

真不错,支持一下
页: [1] 2 3 4 5
查看完整版本: 去4某99盒子强制升级