逆向一个app, 其核心算法是通过反射调用的, 反编译软件中无法找到该类, 并且也无法hook.

Java.perform(function(){
Java.enumerateClassLoaders({
onMatch:function(loader){
try{
if(loader.loadClass("com.xxxxx")){
console.log("================="+loader);
Java.classFactory.loader=loader;
var app=Java.use("com.xxxxx");
console.log(app); // app.sayHello.implementation=function(){
// return "bye";
// }
}else{
console.log("NOT HAS CLASS");
}
}catch(error){ }
},
onComplete:function(){ }
});
});

Java.enumerateClassLoaders使用枚举classloader, 可以找到该类使用的classloader是

InMemoryDexClassLoader动态加载的,如何逆向呢?

dalvik.system.InMemoryDexClassLoader[DexPathList[[dex file "InMemoryDexFile[cookie=[473962364016, 473425978352]]"],nativeLibraryDirectories=[/data/app/~~ZljW8Ol47mfWsrqYu4qjCQ==/xyz.be.customer-oh7iq9v-8TFeIWPLBt2Pow==/lib/arm64, /data/app/~~ZljW8Ol47mfWsrqYu4qjCQ==/xyz.be.customer-oh7iq9v-8TFeIWPLBt2Pow==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64, /product/lib64]]]

学习下动态加载dex 加固(正向)

https://blog.csdn.net/zzx410527/article/details/51673908

思路一(不可行): 使用objection wallbreak

plugin wallbreaker classsearch com.xxx.internal.xxxx$1101

这里有个bug 就是有$的 他无法dump需要处理下

wallbreak的原理是通过调用Java.enumerateLoadedClassesSync()

来枚举所有已经加载的Java 类, 然后再通过java反射获取class的属性\方法\等整体结构, 但是无法获得方法的内容.

我们来试试

Java.perform(function() {
var packagename = "com.appsflyer.internal";
console.log("\n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(_className) {
if (_className.startsWith(packagename)) {
console.log("[*] found class: " + _className);
}
},
onComplete: function() {
console.log("[*] class enuemration complete");
}
});
});

frida -U -f xxxx -l _fcagent.js

注意hook时机, 使用延时调用setImmediate(myjs.myjs, 10000);

ok, 成功捕获到改包名下的所有class文件

然后, 再通过反射来获取

获取类的基本信息java.lang.Class

获取类的实例java.lang.Class和java.lang.reflect.Constructor

操作实例的属性java.lang.reflect.Field

调用实例的方法java.lang.reflect.Method

但是他并不能获取到真正的方法内容, 所以只适合用来查看类的结构, 还有用他的objectdump打印object的值

思路二(可行):可以通过遍历内存中的dex文件特征来dump 所有dex

了解下dex 头文件

struct header_item {
uchar[8] magic; // 魔数,用于标识文件类型
uint checksum; // Alder32 校验和,用于验证文件完整性
uchar[20] signature; // 文件剩余部分的 SHA-1 签名
uint file_size; // 文件总大小,以字节为单位
uint header_size; // 头部大小,以字节为单位
uint endian_tag; // 字节序标记,标识文件的字节序
uint link_size; // 链接部分的大小
uint link_off; // 链接部分的文件偏移量
uint map_off; // map 列表的文件偏移量
uint string_ids_size; // 字符串 ID 列表中的字符串数量
uint string_ids_off; // 字符串 ID 列表的文件偏移量
uint type_ids_size; // 类型 ID 列表中的类型数量
uint type_ids_off; // 类型 ID 列表的文件偏移量
uint proto_ids_size; // 方法原型 ID 列表中的项数
uint proto_ids_off; // 方法原型 ID 列表的文件偏移量
uint field_ids_size; // 字段 ID 列表中的字段数量
uint field_ids_off; // 字段 ID 列表的文件偏移量
uint method_ids_size; // 方法 ID 列表中的方法数量
uint method_ids_off; // 方法 ID 列表的文件偏移量
uint class_defs_size; // 类定义列表中的类数量
uint class_defs_off; // 类定义列表的文件偏移量
uint data_size; // 数据部分的大小,以字节为单位
uint data_off; // 数据部分的文件偏移量
};
字段详细解释:
magic 类型: uchar[8]
描述: 魔数,通常为 "dex\n035\0" 或 "dex\n036\0",用于标识文件类型。
checksum 类型: uint
格式: 十六进制
描述: Alder32 校验和,用于验证文件除校验和字段外的其余部分的完整性。
signature 类型: uchar[20]
描述: 文件剩余部分的 SHA-1 签名,用于验证文件内容的完整性。
file_size 类型: uint
描述: 文件总大小,以字节为单位。
header_size 类型: uint
描述: 头部大小,以字节为单位。通常是 0x70 (112)。
endian_tag 类型: uint
格式: 十六进制
描述: 字节序标记,用于标识文件的字节序,通常为 0x12345678 (小端) 或 0x78563412 (大端)。
link_size 类型: uint
描述: 链接部分的大小。
link_off 类型: uint
描述: 链接部分的文件偏移量。
map_off 类型: uint
描述: map 列表的文件偏移量。
string_ids_size 类型: uint
描述: 字符串 ID 列表中的字符串数量。
string_ids_off 类型: uint
描述: 字符串 ID 列表的文件偏移量。
type_ids_size 类型: uint
描述: 类型 ID 列表中的类型数量。
type_ids_off 类型: uint
描述: 类型 ID 列表的文件偏移量。
proto_ids_size 类型: uint
描述: 方法原型 ID 列表中的项数。
proto_ids_off 类型: uint
描述: 方法原型 ID 列表的文件偏移量。
field_ids_size 类型: uint
描述: 字段 ID 列表中的字段数量。
field_ids_off 类型: uint
描述: 字段 ID 列表的文件偏移量。
method_ids_size 类型: uint
描述: 方法 ID 列表中的方法数量。
method_ids_off 类型: uint
描述: 方法 ID 列表的文件偏移量。
class_defs_size 类型: uint
描述: 类定义列表中的类数量。
class_defs_off 类型: uint
描述: 类定义列表的文件偏移量。
data_size 类型: uint
描述: 数据部分的大小,以字节为单位。
data_off 类型: uint
描述: 数据部分的文件偏移量。

核心思路(参考frida dexdump):

 Process.enumerateRanges('r--').forEach(function (range: RangeDetails) {
try {
Memory.scanSync(range.base, range.size, "64 65 78 0a 30 ?? ?? 00").forEach(function (match) { //判断文件路径包含"/data/dalvik-cache/ 和system 则跳过
if (range.file && range.file.path
&& (range.file.path.startsWith("/data/dalvik-cache/") ||
range.file.path.startsWith("/system/"))) {
return;
}
//验证dex文件
if (verify(match.address, range, false)) {
const dex_size = get_dex_real_size(match.address, range.base, range.base.add(range.size));
result.push({
"addr": match.address,
"size": dex_size
}); const max_size = range.size - match.address.sub(range.base).toInt32();
if (deepSearch && max_size != dex_size) {
result.push({
"addr": match.address,
"size": max_size
});
}
}
}); if (deepSearch) {
Memory.scanSync(range.base, range.size, "70 00 00 00").forEach(function (match) {
const dex_base = match.address.sub(0x3C);
if (dex_base < range.base) {
return;
}
if (dex_base.readCString(4) != "dex\n" && verify(dex_base, range, true)) {
const real_dex_size = get_dex_real_size(dex_base, range.base, range.base.add(range.size));
if (!verify_ids_off(dex_base, real_dex_size)) {
return;
}
result.push({
"addr": dex_base,
"size": real_dex_size
});
const max_size = range.size - dex_base.sub(range.base).toInt32();
if (max_size != real_dex_size) {
result.push({
"addr": dex_base,
"size": max_size
});
}
}
})
} else {
if (range.base.readCString(4) != "dex\n" && verify(range.base, range, true)) {
const real_dex_size = get_dex_real_size(range.base, range.base, range.base.add(range.size));
result.push({
"addr": range.base,
"size": real_dex_size
});
}
} } catch (e) {
}
});
Process.enumerateRanges('r--').forEach(function (range: RangeDetails) {

遍历所有具有只读权限的内存范围

Memory.scanSync(range.base, range.size, "64 65 78 0a 30 ?? ?? 00").forEach(function (match) {

扫描 DEX 文件头的标识 "dex\n035\0" 或 "dex\n036\0" 为基础进行扫描。匹配的模式为 "64 65 78 0a 30 ?? ?? 00",其中 64 65 78 0a 是 "dex\n",30 ?? ?? 00 是版本号和一个字节的结尾。

具体可参考:https://mp.weixin.qq.com/s/n2XHGhshTmvt2FhxyFfoMA

逆向动态加载Dex(内存加载class)的更多相关文章

  1. [转载] Android动态加载Dex机制解析

    本文转载自: http://blog.csdn.net/wy353208214/article/details/50859422 1.什么是类加载器? 类加载器(class loader)是 Java ...

  2. android加固系列—6.仿爱加密等第三方加固平台之动态加载dex防止apk被反编译

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5402599.html ] 此方案的目的是隐藏源码防止直接性的反编译查看源码,原理是加密编译好的 ...

  3. java动态编译类文件并加载到内存中

    如果你想在动态编译并加载了class后,能够用hibernate的数据访问接口以面向对象的方式来操作该class类,请参考这篇博文-http://www.cnblogs.com/anai/p/4270 ...

  4. Android应用安全之外部动态加载DEX文件风险

    1. 外部动态加载DEX文件风险描述 Android 系统提供了一种类加载器DexClassLoader,其可以在运行时动态加载并解释执行包含在JAR或APK文件内的DEX文件.外部动态加载DEX文件 ...

  5. Unity动态加载和内存管理(三合一)

    原址:http://game.ceeger.com/forum/read.php?tid=4394#info 最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Re ...

  6. Android 插件技术:动态加载dex技术初探

    1.Android动态加载dex技术初探 http://blog.csdn.net/u013478336/article/details/50734108 Android使用Dalvik虚拟机加载可执 ...

  7. GDB调试工具、动态加载、内存管理(day04)

    一.程序中的错误处理 在系统中定义了一个全局变量errno.在这个全局变量中存放着系统调用或者库函数出错的信息(错误编号).然后根据错误编号获取错误信息. 举例说明: 打开一个文件,如果这个文件不存在 ...

  8. 浅析dex文件加载机制

    我们可以利用DexClassLoader来实现动态加载dex文件,而很多资料也只是对于DexClassLoader的使用进行了介绍,没有深入讲解dex的动态加载机制,我们就借助于Android4.4的 ...

  9. [转]全面理解Unity加载和内存管理

    [转]全面理解Unity加载和内存管理 最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质 ...

  10. [WP8.1UI控件编程]Windows Phone大数据量网络图片列表的异步加载和内存优化

    11.2.4 大数据量网络图片列表的异步加载和内存优化 虚拟化技术可以让Windows Phone上的大数据量列表不必担心会一次性加载所有的数据,保证了UI的流程性.对于虚拟化的技术,我们不仅仅只是依 ...

随机推荐

  1. shell脚本的调试

    参数: -n :读一遍脚本中的命令但不执行,用于检查脚本中的语法错误 -v :一边执行脚本,一边将执行过的脚本命令打印到标准错误输出 -x :提供跟踪执行信息,将执行的每一条命令和结果依次打印出来 使 ...

  2. 利用 Helm 在各类 Kubernetes 中安装 Rainbond

    利用 Helm 安装 Rainbond 好雨科技技术团队一直致力于让用户更方便的安装 Rainbond 这款产品. 不久前,我们刚刚推出了在一个容器中部署 Rainbond 的快速安装方式,这种方式覆 ...

  3. firewall防火墙基础配置

    Firewalld防火墙 Centos7 中集成了防火墙管理工具, Firewall系统动态防火墙管理器是作为默认的防火墙工具. 它支持规则动态更新,并加入zone区域概念. Firewalld防火墙 ...

  4. 抖音abogus逆向分析

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 目标网站 aHR0cHM6 ...

  5. ETL工具-nifi干货系列 第一讲 揭开nifi神秘面纱

    1.nifi简介 Apache NiFi 是基于流程编程概念的数据流系统.它支持强大且可扩展的数据路由.转换和系统中介逻辑的有向图.NiFi具有基于Web的用户界面,用于设计.控制.反馈和监控数据流. ...

  6. 开机启动VM WARE 某台虚拟机

    新建一个批处理,内容如下: set vm_root=C:\Program Files (x86)\VMware\VMware Workstation "%vm_root%\vmrun.exe ...

  7. 『手撕Vue-CLI』完善提示信息

    前言 经过『手撕Vue-CLI』自动安装依赖,已经实现了自动安装依赖的功能. 然而,虽然项目已复制并安装依赖,但其提示信息并不够友好,于是我试着去运行了一下vue create,发现其提示信息是这样的 ...

  8. 简单的css3头像旋转与3D旋转效果

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 简单的css3头像旋转与3D旋转效果 日期:2017-7- ...

  9. 从 Docker Hub 拉取镜像受阻?这些解决方案帮你轻松应对

    最近一段时间 Docker 镜像一直是 Pull 不下来的状态,感觉除了挂,想直连 Docker Hub 是几乎不可能的.更糟糕的是,很多原本可靠的国内镜像站,例如一些大厂和高校运营的,也陆续关停了, ...

  10. W801单片机入门开发环境设置

    W801单片机入门开发环境设置 开发软件下载 烧录工具和SDK 在 WinnerMicro的网站 https://www.winnermicro.com/html/1/156/158/558.html ...