首页 > 其他分享 >APP逆向 day24unidbg上

APP逆向 day24unidbg上

时间:2024-07-30 13:26:20浏览次数:15  
标签:逆向 day24unidbg String java APP 参数 unidbg so com

一.前言

今天开始讲app逆向最后一个也是最重要的unidbg,这已经是从初级进阶到中级的了,我会讲unidbg,讲三节课,分为上中下来和大家讲(由简单到难逐步),这节课主要是和大家讲unidbg的介绍并且会结合之前讲的简单案例来让大家理解,如果过程中不太记得之前的位置定位,可以去看之前的课程,在学习工程中遗忘是难免的,这也是我做教学的初心,希望大家点赞关注加收藏。

二.unidbg的介绍和使用

2.1 unidbg 是什么

unidbg是一个Java开源项目,可以帮助我们去模拟一个安卓或IOS设备,用于去执行so文件中的算法,从而不需要再去逆向他内部的算法
它是一个基于 unicorn 的逆向工具,可以直接调用Android和iOS中的 so 文件

Allows you to emulate an Android native library, and an experimental iOS emulation
允许您模拟 Android native library 和 实验性的 iOS 模拟

 而在什么时候使用unidbg呢?

当加密位置是在so文件的时候,而so文件破解难度大,我们就会使用unidbg,我们之前也教过大家其他两种硬核破解so文件的,分别是frida-rpc和自己编写app来调用,但是问题就是我们不方便交付,特别的麻烦,所以我们可以使用unidbg,再把unidbg的java代码编写成jar包,通过python来调用jar包就好(当然今天我们讲不到这里),后面会讲的,这就有点类似于js逆向时python调用js文件一样!

2.2 下载和使用

这里给出下载地址

Releases · zhkl0228/unidbg · GitHubicon-default.png?t=N7T8https://github.com/zhkl0228/unidbg/releases打开这个网址选择最新版下载就好,下载好解压完,使用idea打开

注意打开时解压后里面的这一层目录

然后我们运行一下

正常出值了就说明没问题,比如我最开始运行就发现报错,排除半天才发现jdk版本错误,当时用的版本是jdk1.7,后来换成1.8就ok了,这个代码是安居客sign的测试代码,运行成功就说明环境没问题了

2.3 关于unidbg的补环境

1 unidbg 模拟了手机设备--》so文件进行加密---》so文件加密时,有两种方式
    - 加密算法,都在so层,全是用c实现的     大姨妈--》不需要补环境
    - 加密算法,在so层--》so又调用了java层--》返回so层继续逻辑--》唯品会--》需要补环境
    
    
2 所谓的补环境--》就是补c层调用java时候的一些类
    unidbg使用java写的---》c调用java的时候---》unidbg是没有对应app的java的代码---》c中调用java时,缺java的这些类---》我们需要把缺的java类补上

所以说,unidbg补环境只在so层调用java的时候才需要补上,也就是补上那些java中的类

三.车智赢案例

刚才我们介绍了一下unidbg,现在我就带大家讲一下之前的unidbg,忘了的话可以去看一下之前的案例

3.1 回顾当时so加密

APP逆向 day13 逆向某智赢登录-CSDN博客文章浏览阅读1k次,点赞23次,收藏17次。pwd 就是对密码进行md5加密udid就是将几个值拼接起来进行des加密,最后再第61个位置加上空格(可忽略)_sign 对载荷进行拼接后 前面加上一串字符,后面加上一串字符进行md5。https://blog.csdn.net/weixin_74178589/article/details/140250795?spm=1001.2014.3001.5501当时我们逆向udid的时候发现执行力des加密,而我们当时get3deskey是直接hook得来的

我们今天用unidbg带大家跑出来这个key是什么

3.2 unidbg的使用步骤

(1)在java/com下创建一个包和类,名字随便取

 (2)设置初始化

这里先给大家截图,讲完思路之后会给大家代码的,这些基本都是固定的

可以发现我们还要单独创建一个目录来导入apk和so文件

这样就创建好了

 这些初始化写好之后就运行一下,代码基本都是固定的,后续只要自己修改包名那些就好了

 运行不报错了

package com.che_des3key;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.AbstractJni;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.memory.Memory;

import java.io.File;

//必须继承AbstractJni
public class CheZhiYing extends AbstractJni {
    public static AndroidEmulator emulator;  // 静态属性,以后对象和类都可以直接使用
    public static Memory memory;
    public static VM vm;
    public static Module module;
    // 1 构造方法--》用来初始化
    public CheZhiYing(){
        // 1.创建设备(32位或64位模拟器), 具体看so文件在哪个目录。 在armeabi-v7a就选择32位
        // 传进设备时,如果是32位,后面so文件就要用32位,同理需要用64位的
        // 这个名字可以随便写,一般写成app的包名    以后可能会动
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.che168.autotradercloud").build();

        // 2.获取内存对象(可以操作内存)
        memory = emulator.getMemory();

        //3.设置安卓sdk版本(只支持19、23)
        memory.setLibraryResolver(new AndroidResolver(23));

        // 4.创建虚拟机(运行安卓代码需要虚拟机,就想运行py代码需要python解释器一样)    以后会动
        vm = emulator.createDalvikVM(new File("apks/che/che3.32.1.apk"));
        vm.setJni(this); // 后期补环境会用,把要补的环境,写在当前这个类中,执行这个代码即可,但是必须继承AbstractJni
        //vm.setVerbose(true); //是否展示调用过程的细节

        // 5.加载so文件
        DalvikModule dm = vm.loadLibrary(new File("apks/che/libnative-lib.so"), false);   // 以后会动
        dm.callJNI_OnLoad(emulator); // jni开发动态注册,会执行JNI_OnLoad,如果是动态注册,需要执行一下这个,如果静态注册,这个不需要执行,车智赢案例是静态注册

        // 6.dm代表so文件,dm.getModule()得到module对象,基于module对象可以访问so中的成员。
        module = dm.getModule(); // 把so文件加载到内存后,后期可以获取基地址,偏移量等,该变量代指so文件
    }

    //2 sign 成员方法--》主要用来解密
    public void sign(){

    }

    // 3 main方法---》右键直接运行
    public static void main(String[] args) {
        CheZhiYing che=new CheZhiYing();
        che.sign();
    }
}

(3)执行签名

 

jni签名

 因为content是android中的方法,所以这个比较特殊,所以写成了android/content/Context,正常都是根据这个表对应来写就好

代码给出如下

public void sign(){
        // 1 找到java类中jni的类  native方法,找的时候是固定写法
        // com.autohome.ahkit.jni.CheckSignUtil-->.写成 / 形式
        DvmClass CheckSignUtil = vm.resolveClass("com/autohome/ahkit/jni/CheckSignUtil");

        // 2 找到类中的方法--》使用签名的方式找【参数签名和返回值签名】--》固定写法
        // Landroid/content/Context; 就是参数,这个只有一个content类型 要用jni中对应的类型来写
        // Ljava/lang/String 就是返回值,也要用jni中对应的类型来写
        // 之前在jni开发中给过一张对应图了
        String method = "get3desKey(Landroid/content/Context;)Ljava/lang/String;";

        // 3 执行方法,传入参数
        // 第一个参数是:设备对象
        // 第二个参数是:方法
        // 再往后的参数,就是这个方法的参数
        StringObject obj = CheckSignUtil.callStaticJniMethodObject(
                emulator,
                method,
                // 相当于 new 了个contex传入了,但是这个context是空的
                // 具体类型一会讲
                vm.resolveClass("android/content/Context").newObject(null)
        );

        // 4 打印结果
        String result=obj.getValue();
        System.out.println(result);
        
    }

现在再右键

 

可以发现出值了,而这个值就是key,和我们之前的一结果一致

3.3 调用方法--传参和返回值

相信大家在刚才的传参和返回值那里应该都挺蒙蔽的,那我们现在就来具体讲一下,讲完这个就接着和大家讲案例让大家深入理解

使用unidbg调用 jni 中Navite方法时,传入的参数和返回值,不是java的类型,需要是unidgb提供的类型,我们反编译回来的代码是这样:

public static native String get3desKey(Context context);

而我们写unidbg的代码是这样:

StringObject obj = CheckSignUtil.callStaticJniMethodObject(
                        emulator,
                        method,
                        vm.resolveClass("android/content/Context").newObject(null)
                );

因为在使用unidbg时要有包裹概念,要把参数进行包裹再传给unidbg使用,这里是传参包裹的规则

java类型                        包裹                                
字符串:'justin'                 StringObject("justin")                
字节数组:{11,12}            ByteArray({11,22})                 
----------------------------布尔-数字-空-----------------------
布尔:True/False           True/False                      
数字:19                        19                                    
空:null                          null                                   
----------------------------自定义类型----------------------------------------
自定义类型:Info         cls = vm.resolveClass("com/nb/utils/Info");
                                     cls.newObject(对象)

                  可以直接写成vm.resolveClass("com/nb/utils/Info").newObject(new出来的对象)

而我们刚才这么写:

vm.resolveClass("android/content/Context").newObject(null)

是因为content是安卓中的方法,java中没有,而我们这个方法恰巧没有使用content里面的值,如果有的案例需要这个值,那我们就要补环境了

返回值就比较简单

返回值--》被unidbg包裹的对象--》通过getValue得到真正的字符串对象
如果返回字符串 需要用 StringObject 类型接受---》拿到真正的字符串 需要 obj.getValue() 

四.大姨妈案例 

这里给出当时案例的地址,不记得的话可以去看看(前几天的案例要是看过了但是忘了就该打!)

APP逆向 day21大姨妈逆向-CSDN博客文章浏览阅读813次,点赞26次,收藏29次。今天知识点有点多,主要是给大家说了一下绕过root检测,frida-rpc和安卓编写调用so,这个其实后期用的不多,主要是做个了解,后期遇到难读的so我们会用unidbg,还差两个知识点就能讲到了,讲完那个我们的基础课程也算是结束了,大家就到了app逆向入门了,好了,到时候再说吧,晚安!https://blog.csdn.net/weixin_74178589/article/details/140716482?spm=1001.2014.3001.5501

当时我们传入三个参数,第一个参数是0,第二个参数是sb,第三个参数是sb的长度 

这里我们随便拿之前hook到的模拟一下

j2=0
str=64e6176e45397c5989504e76f98ecf2e63b2679euser/login18953675221WA89qByLlDeaGjmVNzXm/w==
j3=85

那我们就来c一下代码嘛,改个包名和文件名就好了

c好的代码修改了如上面,我们运行一下

 

发现运行报错

 还记得这里嘛,说明我们c的是64位的so文件,那我们改一下就好了

改好之后运行不报错了,我这里真的是想办法帮你们把所有坑都排掉,别太感动!!点赞关注加收藏就好 

我们现在来编写sign中的内容,sign中的内容也可以复制然后修改就好,最后我会给出代码的

这个就是之前我们写的类似,注意的是包名中间的.都换成/,参数之间不用分割,中间那个;是因为jni中string对应的后面有分号 

   public void sign(){

        // 1 找到java类中jni的类  native方法,找的时候是固定写法
        // 找到包,找到类
        DvmClass CheckSignUtil = vm.resolveClass("com/yoloho/libcore/util/Crypt");

        // 2 找到类中的方法--》使用签名的方式找【参数签名和返回值签名】--》固定写法
        // 第一个参数: J  long类型对应
        // 第二个参数: Ljava/lang/String; string类型对应
        // 第三个参数: J long类型对应
        // 返回值: Ljava/lang/String;
        // 注意:参数和参数之间不用; 或者,分割 直接写就行了
        String method = "encrypt_data(JLjava/lang/String;J)Ljava/lang/String;";
        // 3 执行方法,传入参数
        // 第一个参数是:设备对象
        // 第二个参数是:方法
        // 再往后的参数,就是这个方法的参数
        StringObject obj = CheckSignUtil.callStaticJniMethodObject(
                emulator,
                method,
                0,
                new StringObject(vm,"64e6176e45397c5989504e76f98ecf2e63b2679euser/login18953675221WA89qByLlDeaGjmVNzXm/w=="),
                85

        );


        // 4 打印结果
        String result=obj.getValue();
        System.out.println(result);

    }

运行结果

 

五.得物案例 

这里给出之前案例的地址

APP逆向 day15 某物逆向_得物app逆向-CSDN博客文章浏览阅读1.8k次,点赞44次,收藏12次。这次讲的很长,主要是学习技术和概念。_得物app逆向https://blog.csdn.net/weixin_74178589/article/details/140303850?spm=1001.2014.3001.5501 

 

我们这里大致回忆一下,当时我们,当时他执行了getByteValues,然后再进行下面的操作,最后把生成的字符串传入 再执行encodeByte,这两个都是jni方法,当时我们只看了encodeByte的参数和返回值,并没有怎么读上面的逻辑,因为读so太麻烦了,而这次我们用jni完整的把这两个方法都搞出来,我们还是先c一下并修改初始化的代码

我们运行一下

 

这个不是报错,只是内部打印的日志

 这个就比前两个要复杂,他要调用两次jni方法,但是殊途同归,可以发现,这样子的好处就是,遇到java中的逻辑代码,我们能够直接复制,稍微修改一点点了,记得当时我们硬核破解so的时候,就在想这个取反之后的字符串为什么没有用到,为啥会没有用,还会在想会不会用错了,但是当我们使用jni的时候完全不会觉得用错了,能够十分自信,而且更加的方便马,这就是用unidbg的好处,简单好破解,这里给出sign中的代码

public void sign(){
        // 内部调用了两次jni方法
        // 1 找到类
        DvmClass AESEncrypt = vm.resolveClass("com/duapp/aesjni/AESEncrypt");
        //2 找到方法
        // 没有参数
        String method = "getByteValues()Ljava/lang/String;";
        // 3 调用
        StringObject byteValues = AESEncrypt.callStaticJniMethodObject(
                emulator,
                method
        );
        // 4 拿到真正的字符串
        String byteValuesString = byteValues.getValue();

        // 5 按照反编译的逻辑执行java代码
        // 直接复制就行了
        StringBuilder sb = new StringBuilder();
        for (int i2 = 0; i2 < byteValuesString.length(); i2++) {
            if (byteValuesString.charAt(i2) == '0') {
                sb.append('1');
            } else {
                sb.append('0');
            }
        }
        String sbString = sb.toString();
        System.out.println(sbString);

        // 6 找到第二个方法
        // 第一个参数: [B 对应字节数组
        // 后面我就不多说了
        String methodEncodeBytes = "encodeByte([BLjava/lang/String;)Ljava/lang/String;";


        // 7 执行方法
        String body="abRecReason0abRectagFengge0abTypesocial_brand_strategy_v454abValue1abVideoCover2deliveryProjectId0lastIdlimit20loginTokenplatformandroidtimestamp1715346585009uuidee13885e68d76ed4v4.74.5";
        StringObject data = AESEncrypt.callStaticJniMethodObject(
                emulator,
                methodEncodeBytes,
                // 按照前面说的包裹好
                new ByteArray(vm, body.getBytes()),
                new StringObject(vm, sbString)
        );

        //8 打印结果
        System.out.println(data.getValue());


    }

运行结果

六.海南航空案例

讲了几个之前的案例,我们这就来讲一个新的案例,担心大家记不清之前的案例了还不愿意回去看,这就完整的和大家讲一个

版本选择 v9.0.0

6.1 抓包分析

我们今天就不完全给他全部破出来,而是只用unidbg破解这一个参数:hnairSign

6.2 找到加密位置 

我们搜索hnairSign

找到一个位置,我们点进去

 

发现在这里,我们再点进去

 

i.p().get(0)-->i.p执行结果是列表ArrayList,取了列表的第0个位置

HNASignature.getHNASignature()--》执行结果是字符串

然后对其进行分割取第0个位置,我们点进去

6.3 hook得到加密参数

 发现在这里是个jni方法,那我们接下来就是hook参数并且找到其对应的so文件 

这里给出hook代码

Java.perform(function () {
    var HNASignature = Java.use("com.rytong.hnair.HNASignature");
    HNASignature.getHNASignature.implementation = function (str,str2,str3,str4,str5) {
        console.log("---------------------")
        console.log("参数1",str);
        console.log("参数2",str2);
        console.log("参数3",str3);
        console.log("参数4",str4);
        console.log("参数5",str5);
        var res = this.getHNASignature(str,str2,str3,str4,str5);
        console.log("返回值=",res);
        return res;
    }
});


//frida -U -f com.rytong.hnair -l hook.js

我们清除数据执行一下,通过抓包的数据搜索

发现参数和返回值

参数1 {}
参数2 {}
参数3 {"abuild":"64249","akey":"184C5F04D8BE43DCBD2EE3ABC928F616","aname":"com.rytong.hnair","atarget":"standard","aver":"9.0.0","caller":"AD_H5","did":"d3e4ffe477e86d99","dname":"Google_Pixel 3","gtcid":"","hver":"9.0.0.35417.7ac
793f2e.standard","mchannel":"huawei","schannel":"AD","slang":"zh-CN","sname":"google\/blueline\/blueline:11\/RQ3A.211001.001\/7641976:user\/release-keys","stime":"1722284925093","sver":"11","system":"AD","szone":"+0800","riskToken":"66a7fb7adXzZGwi8Bf8b3o9WpWYvTtyQMM7ewnx3"}
参数4 21047C596EAD45209346AE29F0350491
参数5 F6B15ABD66F91951036C955CB25B069F
返回值= E3B7A590F71E7C8292165B26BE54814C7F56653E>>64249184C5F04D8BE43DCBD2EE3ABC928F616com.rytong.hnairstandard9.0.0AD_H5d3e4ffe477e86d99Google_Pixel 39.0.0.35417.7ac793f2e.standardhuawei66a7fb7adXzZGwi8Bf8b3o9WpWYvTtyQMM7ewnx3ADzh-CNgoogle/blueline/blueline:11/RQ3A.211001.001/7641976:user/release-keys172228492509311AD+0800>>F6B15ABD66F91951036C955CB25B069F

6.4 找到加密位置 

这个发现找不到我们想要的so文件的位置,之前我们在b站案例中给我一个找到动态注册的so文件以及偏移量直接找到加密方法,这里再次给出

function hook_RegisterNatives() {
    //1 加载安卓手机底层包,系统自带的库,我们hook的RegisterNatives在这个包中
    var symbols = Module.enumerateSymbolsSync("libart.so");
    //2 定义一个变量,用来接收一会找到的addrRegisterNatives的地址
    var addrRegisterNatives = null;
    // 3 循环找到RegisterNatives的地址,赋值给变量
    //注意:此处可能找出多个RegisterNatives的地址,由于咱们是for循环,会把之前的覆盖掉,所有如果hook没反应,尝试加break,使用第一个找到的
    for (var i = 0; i < symbols.length; i++) {
        var symbol = symbols[i];
        if (symbol.name.indexOf("art") >= 0 &&
            symbol.name.indexOf("JNI") >= 0 &&
            symbol.name.indexOf("RegisterNatives") >= 0 &&
            symbol.name.indexOf("CheckJNI") < 0) {
            addrRegisterNatives = symbol.address;
            console.log("RegisterNatives is at ", symbol.address, symbol.name);
            break
        }

    }
    // 4 找到后开始hook
    if (addrRegisterNatives != null) {
        Interceptor.attach(addrRegisterNatives, {
            // 4.1 当进入RegisterNatives时执行
            // RegisterNatives(env, 类型, Java和C的对应关系,个数)
            onEnter: function (args) {
                // 4.2 第0个参数是env
                var env = args[0];
                // 4.3 第1个参数是类型
                var java_class = args[1];
                 // 4.4 通过类型得到具体的类名
                var class_name = Java.vm.tryGetEnv().getClassName(java_class);
                //console.log(class_name);
                // 只有类名为com.bilibili.nativelibrary.LibBili,才打印输出
                var taget_class = "com.rytong.hnair.HNASignature";
                if (class_name === taget_class) {
                    //4.5  只有类名为com.bilibili.nativelibrary.LibBili,再取出第四个参数
                    console.log("\n[RegisterNatives] method_count:", args[3]);
                    // 4.6 第2个参数是:Java和C的对应关系,我们转成指针
                    /*
                    static JNINativeMethod gMethods[] = {
                            {"add", "(III)I", (void *) plus},
                            {"add", "(II)I", (void *) plus},
                            {"add", "(II)I", (void *) plus},
                    };
                     */
                    var methods_ptr = ptr(args[2]);
                    // 4.7 java和c函数对应关系的个数
                    var method_count = parseInt(args[3]);
                    // 4.8 我们循环这个个数,依次移动指针methods_ptr,通过readPointer,往后读取 {"add", "(III)I", (void *) plus},依次读出Java中函数名字,签名和C中的函数指针
                    for (var i = 0; i < method_count; i++) {
                        // 4.8.1 读取Java中函数名字的
                        var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                        // 4.8.2 读取签名, 参数和返回值类型
                        var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                        // 4.8.3 读取 C中的函数指针
                        var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));

                        // 4.8.4 读取java中函数名 字符串名
                        var name = Memory.readCString(name_ptr);
                        // 4.8.5 参数和返回值类型 字符串名
                        var sig = Memory.readCString(sig_ptr);
                        // 4.5.6 根据C中函数指针获取模块
                        var find_module = Process.findModuleByAddress(fnPtr_ptr); // 根据C中函数指针获取模块


                        // 4.8.7 得到该函数的偏移量:ptr(fnPtr_ptr)函数在内存中的地址   减去   该so文件的基地址(find_module.base)====得到偏移量
                        // 地址:函数在内存中的地址
                        // 偏移量:后期单独打开so文件后,可以根据偏移量 定位到函数位置
                        // 基地址:当前so文件从那个位置开始算地址
                        var offset = ptr(fnPtr_ptr).sub(find_module.base)
                        // console.log("[RegisterNatives] java_class:", class_name);
                        // 4.8.8 输出 函数名      参数和返回值类型    模块    偏移量
                        console.log("name:", name, "sig:", sig, "module_name:", find_module.name, "offset:", offset);

                    }
                }
            }
        });
    }
}

setImmediate(hook_RegisterNatives);

// frida -U -f 包名 -l 16.通用脚本_获取动态注册对应关系.js




发现运行啥也没有,说明是静态注册,这里给出找到静态注册so文件的代码

Java.perform(function () {
    var dlsymadd = Module.findExportByName("libdl.so", 'dlsym');
    Interceptor.attach(dlsymadd, {
        onEnter: function (args) {
            this.info = args[1];

        }, onLeave: function (retval) {
            //那个so文件 module.name
            var module = Process.findModuleByAddress(retval);
            if (module == null) {
                return retval;
            }
            // native方法
            var funcName = this.info.readCString();
            // 后期只需要改这里,对应的java方法名
            if (funcName.indexOf("getHNASignature") !== -1) {
                console.log(module.name);
                console.log('\t', funcName);
            }
            return retval;
        }
    })
});


// frida -U -f  包名  -l 24.通用脚本_获取静态注册的so文件.js
// frida -U -f  com.rytong.hnair  -l 24.通用脚本_获取静态注册的so文件.js

 发现是libsignature.so,那我们现在就不用去so中读逻辑了,直接把apk改成zip,解压后把这个so文件和apk一起放入unidbg中就好

6.5 unidbg跑 

 

然后就是c一下那段代码了

 我们把该c好的c好,运行发现不报错,现在就开始写sign

直接写入参数就好了,这里给出代码

 public void sign(){

        // 1 找到类
        DvmClass HNASignature = vm.resolveClass("com/rytong/hnair/HNASignature");
        // 2 找到方法
        // 这里五个参数都是字符串,看起来有带你奇怪
        String method = "getHNASignature(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;";
        //3 执行方法
        StringObject obj = HNASignature.callStaticJniMethodObject(
                emulator,
                method,
                new StringObject(vm,"{}"),
                new StringObject(vm,"{}"),
                new StringObject(vm,"{\"abuild\":\"64249\",\"akey\":\"184C5F04D8BE43DCBD2EE3ABC928F616\",\"aname\":\"com.rytong.hnair\",\"atarget\":\"standard\",\"aver\":\"9.0.0\",\"caller\":\"AD_H5\",\"did\":\"d3e4ffe477e86d99\",\"dname\":\"Google_Pixel 3\",\"gtcid\":\"\",\"hver\":\"9.0.0.35417.7ac793f2e.standard\",\"mchannel\":\"huawei\",\"schannel\":\"AD\",\"slang\":\"zh-CN\",\"sname\":\"google\\/blueline\\/blueline:11\\/RQ3A.211001.001\\/7641976:user\\/release-keys\",\"stime\":\"1722284925093\",\"sver\":\"11\",\"system\":\"AD\",\"szone\":\"+0800\",\"riskToken\":\"66a7fb7adXzZGwi8Bf8b3o9WpWYvTtyQMM7ewnx3\"}"),
                new StringObject(vm,"21047C596EAD45209346AE29F0350491"),
                new StringObject(vm,"F6B15ABD66F91951036C955CB25B069F")
        );

        //4 打印结果
        System.out.println(obj.getValue());

    }

运行结果

 和刚才抓包结果一致,至此破解成功

七.总结

今天讲的干活和内容很多,大家要仔细品味,发现unidbg也没有这么难,下一期会和大家讲中部分,稍微比这个案例难一点,但是也是之前讲过的,大家可以看看之前的案例,对比一下使用unidbg,多多体会

 补充

有需要源码的看我主页签名名字私信我,有求必应

 

 

 

 

标签:逆向,day24unidbg,String,java,APP,参数,unidbg,so,com
From: https://blog.csdn.net/weixin_74178589/article/details/140778060

相关文章

  • 基于SpringBoot+Vue+uniapp的竞赛报名系统的详细设计和实现(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • HarmonyOS APP应用开发项目- MCA助手(Day03持续更新中~)
    简言:gitee地址:https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5注:此App参照此教程进行二次修改:https://www.bilibi......
  • Django-APP及项目入门
    1.APP定义:Django中功能的细分,每个APP有独立的数据库、表结构、HTML模版、CSS。创建APPpythonmanage.pystartappapp01重要文件介绍views.py:常用文件,urls中的函数常常在此处定义。models.py:常用文件,对数据库进行操作。2.项目入门确保app也注册(settings.py)......
  • UniApp 原生插件接入步骤
    app插件主要分2种:原生语言插件原生语言插件有分为2类:(1)moduleAPI接口插件这种插件是API插件,有同步或异步API(2)UIcomponent组件插件这种插件是UI视图组件,使用到插件里的UI组件的页面要用nvueUTS插件uts集成步骤参考https://www.cnblogs.com/wenrisheng/p/183230......
  • App Inventor 2 低功耗蓝牙 BlueToothLE 拓展中文文档(完整翻译加强版)
    低功耗蓝牙,也称为蓝牙LE或简称BLE,是一种类似于经典蓝牙的新通信协议,不同之处在于它旨在消耗更少的功耗和成本,同时保持同等的功能。因此,低功耗蓝牙是与耗电资源有限的物联网设备进行通信的首选。BluetoothLE扩展需要Android5.0或更高版本。BlueToothLE拓展中文文档入口......
  • 微信小程序,web,uniapp-vue前端图片压缩思路-------uniapp-nvue如何压缩
    uniapp官方提供的压缩接口,只支持jpg的压缩,所以,直接放弃在非nvue的页面中,统一使用canvas获取图片信息,并重新绘制。存在一个问题,canvas必须指定宽高,不能动态给定,所以可能存在一些问题。nvue页面,又无法使用canvas,或者说,性能不是很好。一个隐藏的canvas只做图片处理使用,应该不会影......
  • 棋牌游戏app开发的具体过程是怎样的?
    棋牌游戏开发是一个涉及多个环节和技术的复杂过程,对于初次涉足此领域的创业者来说,了解并遵循正确的开发步骤至关重要。1.选择有市场的棋牌游戏:在选择棋牌游戏类型时,要进行市场调研,了解当前市场上哪些类型的游戏最受欢迎,哪些游戏具有持续的吸引力和盈利能力。考虑目标用户群体......
  • 基于Android平台开发,仿头条新闻app新闻分类分类列表实现(四)
    1.项目涉及到的技术点列表控件RecyclerView的使用调用API获取网络数据Glide加载图片Handler的使用okhttp的使用2.代码实现过程在上集中,已经使用TabLayout+ViewPager2把新闻分类滑动实现了,这集具体实现新闻列表新闻布局fragment_tab_news.xml<?xmlversion="1.0"en......
  • 仿微信im源码开源部署/社交聊天即时通讯im源码[PHP+uniapp]/直播+PC+安卓+IOS
    在数字化时代,即时通讯(InstantMessaging,IM)已成为人们日常生活中不可或缺的一部分,无论是工作协作、社交互动还是日常交流,IM应用都扮演着至关重要的角色。从早期的ICQ、MSN到如今的微信、WhatsApp、Telegram等,IM技术不断演进,为用户提供了更加丰富、便捷、安全的沟通体验。本文旨在......
  • Python逆向总结(Python反编译)
    目录第一种:直接反编译型第二种:打包成exe的py文件第三种: 给pyc字节码(类汇编形式)第四种:加花的pyc内容参考第一种:直接反编译型除了直接获得题目内容的python文件外,出题人也可以稍微加工一点点,给出题目python文件所对应的pyc文件,即python的字节码。PYC文件的定义pyc......