Unidbg使用指南

news2024/9/20 22:50:11

Unidbg使用指南

  • 简介
  • 使用
  • Unidbg补环境
    • 仅含C语言
    • C调用 Java
  • 实操——车智赢+在unidbg实现执行so中的方法
  • 附——关于引用数据类型的转换
  • 附——静态注册和动态注册模板
    • 静态注册
    • 动态注册

现在很多的app使用了so加密,以后会越来越多。爬虫工程师可能会直接逆向app,看java代码,完成java层的算法破解,但是如果遇到so该怎么办呢?可能你会直接破解so,但是真的会有很多爬虫工程师会去破解so吗?有时候我们可以不用破解so,利用很多大佬写好的轮子即可完成so的调用。

说到调用,就有很多方法了,比如用frida+rpc、xposed+andserver、再者就是unicorn+web框架等等,今天要说的并不是这些,而是unidbg,这框架有什么好的地方呢?看看简介。

简介

unidbg是一个Java项目,可以帮助我们去模拟一个安卓或IOS设备,用于去执行so文件中的算法,从而不需要再去逆向他内部的算法。
关于so的解决方法:

  • 硬核分析+调试+破解
  • frida-rpc
  • unidbg

使用

  1. 在github上开源的项目:unidbg
    在这里插入图片描述
  2. 打开项目
    由于unidbg项目是由java编写的,所以需要用 Intellij IDEA 打开并操作。
    导入项目后我们运行下测试代码,看看我们的环境是否有问题
    在这里插入图片描述
    当我们运行测试代码后能出现sign值说明环境是没问题的。

Unidbg补环境

unidbg在运行so文件时会出现两类情况:

  • so算法都基于C语言实现,
  • so算法中还会读取Java中成员,

仅含C语言

这种直接基于unidbg来进行so文件即可。

在这里插入图片描述

C调用 Java

这种就需要补环境,将C中调用的Java中的功能给补上,这样so中的代码才能正常执行。
所谓的unidbg补环境,其实补的就是这个。

在这里插入图片描述

实操——车智赢+在unidbg实现执行so中的方法

在这里插入图片描述
在这里插入图片描述

  1. 创建类
    在这里插入图片描述

  2. 设备初始化
    在这里插入图片描述

    package com.com.demo;
    
    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.*;
    import com.github.unidbg.memory.Memory;
    
    import java.io.File;
    
    public class che extends AbstractJni{
        public static AndroidEmulator emulator;
        public static Memory memory;
        public static VM vm;
        public static DalvikModule dm;
        public static Module module;
    
        che() {
            // 1.创建设备(32位或64位模拟器), 具体看so文件在哪个目录。 在armeabi-v7a就选择32位
            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("unidbg-android/apks/che/atc282.apk"));
            vm.setJni(this);
            //vm.setVerbose(true); //是否展示调用过程的细节
    
            // 5.加载so文件
            DalvikModule dm = vm.loadLibrary(new File("unidbg-android/apks/che/libnative-lib.so"), false);
            //dm.callJNI_OnLoad(emulator);
    
            // 6.dm代表so文件,dm.getModule()得到module对象,基于module对象可以访问so中的成员。
            module = dm.getModule();
    
        }
    
        public static void main(String[] args) {
            che obj = new che();
        }
    }
    
  3. 执行签名

    public void sign() {
        // 找到java中native所在的类,并加载
        DvmClass CheckSignUtil = vm.resolveClass("com/autohome/ahkit/jni/CheckSignUtil");

        // 方法的符号表示
        String method = "get3desKey(Landroid/content/Context;)Ljava/lang/String;"; //JNI签名
                                    //导入的包					返回值
        // 执行类中的静态成员
        StringObject obj = CheckSignUtil.callStaticJniMethodObject(
                emulator,
                method,
                vm.resolveClass("android/content/Context").newObject(null)
        );
        String keyString = obj.getValue();
        System.out.println(keyString);
    }

在这里插入图片描述

通过上述操作我们就完成了在unidbg实现执行so中的方法。

附——关于引用数据类型的转换

在这里插入图片描述

附——静态注册和动态注册模板

静态注册

  • 根据函数名将Java代码中的native方法与so中的JNI方法一一对应,当Java层调用so层的函数时,如果发现其上有JNIEXPORT和JNICALL两个宏定义声明时,就会将so层函数链接到对应的native方法上。
  • 而native方法和so方法对应规则是:以字符串“Java”为前缀,并且用“_”下划线将包名、类名以及native方法名连接起来就是对应的JNI函数名了。
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();

            if (funcName.indexOf("getHNASignature") !== -1) {
                console.log(module.name);
                console.log('\t', funcName);
            }
            return retval;
        }
    })
});


// Application(identifier="com.rytong.hnair", name="海南航空", pid=14958, parameters={})
// frida -U -f  com.rytong.hnair  -l static_find_so.js

动态注册

  • 在调用System.loadLibrary()时会在so层调用一个名为JNI_OnLoad()的函数,我们可以提供一个函数映射表,再在JNI_Onload()函数中通过JNI中提供的RegisterNatives()方法来注册函数。这样Java就可以通过函数映射表来调用函数,而不必通过函数名来查找对应函数。
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrRegisterNatives = null;
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);
    }
}
console.log("addrRegisterNatives=", addrRegisterNatives);

if (addrRegisterNatives != null) {
    Interceptor.attach(addrRegisterNatives, {
        onEnter: function (args) {
            var env = args[0];
            var java_class = args[1];
            var class_name = Java.vm.tryGetEnv().getClassName(java_class);
            // 只有类名为com.bilibili.nativelibrary.LibBili,才打印输出
            
            var taget_class = "com.xunmeng.pinduoduo.secure.DeviceNative";
            
            if (class_name === taget_class) {
                console.log("\n[RegisterNatives] method_count:", args[3]);
                var methods_ptr = ptr(args[2]);
                var method_count = parseInt(args[3]);

                for (var i = 0; i < method_count; i++) {
                    // Java中函数名字的
                    var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    // 参数和返回值类型
                    var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    // C中的函数指针
                    var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));

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

                    var offset = ptr(fnPtr_ptr).sub(find_module.base) // fnPtr_ptr - 模块基地址
                    // console.log("[RegisterNatives] java_class:", class_name);
                    console.log("name:", name, "sig:", sig, "module_name:", find_module.name, "offset:", offset);
                    //console.log("name:", name, "module_name:", find_module.name, "offset:", offset);

                }
            }
        }
    });
}

// frida -U -f  com.xunmeng.pinduoduo  -l dynamic_find_so.js

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2047768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑马前端——days09_css

案例 1 页面框架文件 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compati…

Ubuntu20.04如何安装配置JDK

资源准备 官方下载地址&#xff08;根据自己的系统版本选择不同版本进行下载即可&#xff09;&#xff1a;Java Downloads | Oracle 如无特殊需要可直接移步至下方JDK1.8安装包 https://download.csdn.net/download/qq_43439214/89646731 安装步骤 创建Java目录 sudo mkdir …

jmeter安装及环境变量配置、Jmeter目录介绍和界面详解

一 JMeter简介 Apache JMeter是100%纯JAVA桌面应用程序&#xff0c;被设计为用于测试客户端/服务端结构的软件(例如web应用程序)。它可以用来测试静态和动态资源的性能&#xff0c;例如&#xff1a;静态文件&#xff0c;Java Servlet,CGI Scripts,Java Object,数据库和FTP服务器…

【已解决】在进行模型量化推理的过程中遇到的错误以及解决方法

①在使用vLLM推理模型时&#xff0c;出现&#xff1a; Error in calling custom op rms_norm: _OpNamespace _C object has no attribute rms_norm 尝试众多解决方法之后&#xff0c;包括重新安装 pip install vllm0.5.0 对我有用的解决方法&#xff1a; 修改子目录下的vll…

【2024最新】Windows系统上NodeJS安装及环境配置图文教程

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;允许在服务器端运行 JavaScript 代码。它采用事件驱动、非阻塞 I/O 模型&#xff0c;非常适合构建高性能的网络应用程序。Node.js 提供了一系列内置模块&#xff0c;支持异步编程&#xff0c;易于扩展&…

机器学习:knn算法实现图像识别

1、概述 使用K-近邻&#xff08;K-Nearest Neighbors, KNN&#xff09;算法对手写数字进行识别的过程。通过读取一张包含多个手写数字的图片&#xff0c;将其分割成单独的数字图像&#xff0c;并将其作为训练和测试数据集。 2、数据处理思路 1、图像分割该数据有50行100列&am…

手机设备IP地址切换:方法、应用与注意事项

在当今数字化时代&#xff0c;手机已成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;手机都扮演着重要角色。然而&#xff0c;随着网络环境的日益复杂&#xff0c;有时我们需要切换手机设备的IP地址以满足特定的需求&#xff0c;如保护隐私、绕过地…

算法笔记:空间填充曲线

空间填充曲线&#xff08;Space-filling curve&#xff09;是一种数学曲线&#xff0c;它可以无间断地覆盖一个多维空间的每一个点&#xff0c;从而实现从一维到多维的映射。用以解决连续与离散空间之间的映射问题。空间填充曲线的应用广泛&#xff0c;包括图像处理、地理信息系…

基于微信小程序的诗词智能学习系统的设计与实现(全网独一无二,24年最新定做)

文章目录 前言&#xff1a; 博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为…

dos攻击漏洞思路小结

前言 想挖掘src拒绝服务类型的漏洞&#xff0c;搜索了一圈社区相关文章较少&#xff0c;这里根据自己的一些实战案例归纳思路来抛砖引玉&#xff0c;希望能对各位师傅有所帮助&#xff01; 从黑盒视角搭配实际场景&#xff0c;说明如何具体操作能够快速的挖掘拒绝服务漏洞。 …

vue3中使用useStore(),返回undefined的踩坑记录

vue3中使用useStore()&#xff0c;返回undefined&#xff0c;排查后&#xff0c;记录一下的踩坑记录。 总结为&#xff0c;三检查&#xff1a; 1、一检查版本 在package.json中检查&#xff0c;vuex是否正常引入&#xff1a; 版本也要确认一下&#xff1a; vue3对应vuex4的…

使用光流进行相机运动估计

文章目录 基本相机移动区分动作的核心思想了解代码参考 基本相机移动 从我的非专业角度来看&#xff0c;尽管已知的摄像机运动有多种&#xff0c;但我们应该概述其中三种&#xff1a; 一种是将摄像机安装在轨道上并移动——卡车、移动式摄影车、基座摄像机停留在同一位置并旋…

MySQL中的distinct和group by哪个效率更高?

前言 大家好&#xff0c;我是月夜枫~~ 一、distinct和group by的区别 1.1.作用方式和应用场景 ‌group by和‌distinct的主要区别在于它们的作用方式和应用场景。 group by用于对数据进行分组和聚合操作&#xff0c;通常与聚合函数&#xff08;如COUNT、SUM、AVG等&#xf…

学习分享:微软Edge浏览器全解析(请按需收藏)

成长路上不孤单&#x1f60a;【14后小学生一枚&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;】 微软Edge浏览器是一款由微软开发的现代网页浏览…

Python(PyTorch)硅光电倍增管和量化感知训练亚光子算法验证

&#x1f3af;要点 &#x1f3af;亚光子光神经网络矩阵计算 | &#x1f3af;光学扇入计算向量点积 | &#x1f3af;表征测量确定不同光子数量下计算准确度 | &#x1f3af;训练全连接多层感知器基准测试光神经网络算法数字识别 | &#x1f3af;物理验证光学设备设置 | &#x…

【闭包】闭包知识点总结

一、什么是闭包&#xff1f; ——官方解释&#xff1a; 一个函数对周围状态的引用捆绑在一起&#xff0c;内层函数中访问到其外层函数的作用域 ——简单解释&#xff1a; &#x1f449; 闭包内层函数可以引用的外层函数的变量 ——闭包优势 可以保护内部变量&#xff0c;不让外…

黑马前端——days11_综合案例

文章目录 一、首页1、页面开头2、快捷导航2.1 页面框架2.2 格式文件 3、头部模块3.1 页面框架3.2 格式文件 4、导航栏4.1 页面框架4.2 格式文件 5、页面主模块5.1 页面框架5.2 格式文件 6、推荐模块6.1 页面框架6.2 格式文件 7、楼层模块7.1 页面框架7.2 格式文件 8、页面底部8…

webrtc学习笔记2

音视频采集和播放 打开摄像头并将画面显示到页面 1. 初始化button、video控件 2. 绑定“打开摄像头”响应事件onOpenCamera 3. 如果要打开摄像头则点击 “打开摄像头”按钮&#xff0c;以触发onOpenCamera事件的调用 4. 当触发onOpenCamera调用时 a. 设置约束条件&#xff0c…

虚幻UE5安装报错误代码:SU-PQR5

找到图标的快捷方式 “Epic Games Launcher”右键属性&#xff0c;在目标最后添加-SkipBuildPatchPrereq&#xff0c;如下图&#xff1a; 最后&#xff0c;见证奇迹成功打开软件&#xff0c;可以继续安装啦。 参考资料&#xff1a; 【图片】求教各位大佬--错误代码SU-PQR5【ep…

Linux网络编程—socket、bind

一、socket创建套接字 socket是用来创建网络通信或本地通信的套接字&#xff0c;跟文件有关&#xff1a;告诉系统&#xff0c;PCB&#xff08;进程控制块&#xff09;控制的数据应该向哪个套接字写入、或读取&#xff1b;这个套接字是在TCP/IP协议下运行的 #include <sys/t…