脱dex核心文件dump_dex.js

核心函数

function dump_dex() {
var libart = Process.findModuleByName("libart.so");
var addr_DefineClass = null;
var symbols = libart.enumerateSymbols();
for (var index = 0; index < symbols.length; index++) {
var symbol = symbols[index];
var symbol_name = symbol.name;
//这个DefineClass的函数签名是Android9的
//_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE
if (symbol_name.indexOf("ClassLinker") >= 0 &&
symbol_name.indexOf("DefineClass") >= 0 &&
symbol_name.indexOf("Thread") >= 0 &&
symbol_name.indexOf("DexFile") >= 0) {
console.log(symbol_name, symbol.address);
addr_DefineClass = symbol.address;
}
}
var dex_maps = {};
var dex_count = 1; console.log("[DefineClass:]", addr_DefineClass);
if (addr_DefineClass) {
Interceptor.attach(addr_DefineClass, {
onEnter: function(args) {
var dex_file = args[5];
//ptr(dex_file).add(Process.pointerSize) is "const uint8_t* const begin_;"
//ptr(dex_file).add(Process.pointerSize + Process.pointerSize) is "const size_t size_;"
var base = ptr(dex_file).add(Process.pointerSize).readPointer();
var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt(); if (dex_maps[base] == undefined) {
dex_maps[base] = size;
var magic = ptr(base).readCString();
if (magic.indexOf("dex") == 0) { var process_name = get_self_process_name();
if (process_name != "-1") {
var dex_dir_path = "/data/data/" + process_name + "/files/dump_dex_" + process_name;
mkdir(dex_dir_path);
var dex_path = dex_dir_path + "/class" + (dex_count == 1 ? "" : dex_count) + ".dex";
console.log("[find dex]:", dex_path);
var fd = new File(dex_path, "wb");
if (fd && fd != null) {
dex_count++;
var dex_buffer = ptr(base).readByteArray(size);
fd.write(dex_buffer);
fd.flush();
fd.close();
console.log("[dump dex]:", dex_path); }
}
}
}
},
onLeave: function(retval) {}
});
}
}
原理是:通过hook libart ,然后开始枚举符号表,根据符号名称找到DefineClass函数,通过DefineClass的地址来得到它的入参中的DexFile对象
# /art/runtime/class_linker.cc

 mirror::Class* ClassLinker::DefineClass(Thread* self,
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) { ......
}
DexFile 数据结构为
 struct DexFile {
/* directly-mapped "opt" header */
const DexOptHeader* pOptHeader; /* pointers to directly-mapped structs and arrays in base DEX */
const DexHeader* pHeader;
const DexStringId* pStringIds;
const DexTypeId* pTypeIds;
const DexFieldId* pFieldIds;
const DexMethodId* pMethodIds;
const DexProtoId* pProtoIds;
const DexClassDef* pClassDefs;
const DexLink* pLinkData; /*
* These are mapped out of the "auxillary" section, and may not be
* included in the file.
*/
const DexClassLookup* pClassLookup;
const void* pRegisterMapPool; // RegisterMapClassPool /* points to start of DEX file data */
const u1* baseAddr; /* track memory overhead for auxillary structures */
int overhead; /* additional app-specific data structures associated with the DEX */
//void* auxData;
}; struct DexOptHeader {
u1 magic[8]; /* includes version number */ u4 dexOffset; /* file offset of DEX header */
u4 dexLength;
u4 depsOffset; /* offset of optimized DEX dependency table */
u4 depsLength;
u4 optOffset; /* file offset of optimized data tables */
u4 optLength; u4 flags; /* some info flags */
u4 checksum; /* adler32 checksum covering deps/opt */ /* pad for 64-bit alignment if necessary */
};
根据DexFile的数据结构可以得出 dexOffset 就是dex的偏移 ,dexLength 就是dex的大小, 这样就可以将dex整体dump出了
var base = ptr(dex_file).add(Process.pointerSize).readPointer();
var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt();

【Android逆向】脱壳项目frida_dump 原理分析的更多相关文章

  1. android脱壳之DexExtractor原理分析[zhuan]

    http://www.cnblogs.com/jiaoxiake/p/6818786.html内容如下 导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的 ...

  2. android脱壳之DexExtractor原理分析

    导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的原理,使用这种方法脱壳的有2个缺点: 1.  需要动态调试 2.  对抗反调试方案 为了提高工作效率, ...

  3. Android视图SurfaceView的实现原理分析(示例,出错代码)

    在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面.由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独 ...

  4. Android DecorView 与 Activity 绑定原理分析

    一年多以前,曾经以为自己对 View 的绘制已经有了解了,事后发现也只是懂了些皮毛而已.经过一年多的实战,Android 和 Java 基础都有了提升,时机成熟了,是时候该去总结 View 的绘制流程 ...

  5. Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题

    一.故事背景 现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时.就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的.相比较短视频有 ...

  6. Android 65K问题之Multidex原理分析及NoClassDefFoundError的解决方法

    Android 65K问题相信困惑了不少人,尽管AS的出来能够通过分dex高速解决65K问题,可是同一时候也easy由于某些代码没有打包到MainDex里引起NoClassDefFoundError. ...

  7. Android SoundPool 的使用以及原理分析

    好吧,我们今天来聊聊SoundPool这东西. 据说这个东西是冰激凌(Android4.0)里才引入的一个新东西.按照官方的意思大多数情况下是给游戏开发用的,比如一个游戏10关,它能在游戏开始前一次加 ...

  8. 【转载】Android 的 Handler 机制实现原理分析

    handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段.使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息.但是,有没有 ...

  9. Android中线程间通信原理分析:Looper,MessageQueue,Handler

    自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...

  10. Android视图SurfaceView的实现原理分析

    http://blog.csdn.net/luoshengyang/article/details/8661317

随机推荐

  1. [转帖]7.5 TiKV 磁盘空间占用与回收常见问题

    https://book.tidb.io/session4/chapter7/compact.html TiKV 作为 TiDB 的存储节点,用户通过 SQL 导入或更改的所有数据都存储在 TiKV. ...

  2. [转帖]TiDB Control 使用说明

    https://docs.pingcap.com/zh/tidb/stable/tidb-control TiDB Control 是 TiDB 的命令行工具,用于获取 TiDB 状态信息,多用于调试 ...

  3. [转帖]PostgreSQL 慢查询SQL跟踪

    https://www.cnblogs.com/VicLiu/p/12017704.html PostgreSQL 开启慢SQL捕获在排查问题时是个很有效的手段.根据慢SQL让我在工作中真正解决了实际 ...

  4. rclone 的下载地址-官方网站

    Downloads Rclone is single executable (rclone, or rclone.exe on Windows) that you can simply downloa ...

  5. 学习: Linux的 date 命令

    date 命令非常好用 多用 date --h 还是非常好的 获取 今天是今年的第多少天 最简单的办法 就是 date +%j 以后需要多学习 多利用 linux的帮助才可以呢. Usage: dat ...

  6. Codeforces round 919 (div2)

    Problem - A - Codeforces 暴力枚举 就可以: #include <bits/stdc++.h> #define int long long using namesp ...

  7. 窗口管理器 dwm安装

    上一篇博文中,已经完成了archlinux的安装,但是进去仅仅是一个冰冷冷的交互式命令窗口.没有图像,也无法打开浏览器.离日常使用还差的很远,接下来首先需要做的就是安装桌面环境.这里我不打算使用诸如g ...

  8. 深入浅出Java多线程(一):进程与线程

    引言 大家好,我是你们的老伙计秀才. 在计算机系统的发展历程中,早期的计算机操作模式十分单一和低效.用户只能逐条输入指令,而计算机则按照接收指令的顺序逐一执行,一旦用户停止输入或进行思考,计算机会处于 ...

  9. numpy数组拼接方法介绍(concatenate)---一次性完成多个数组的拼接

    1.数组拼接方法一 思路:首先将数组转成列表,然后利用列表的拼接函数append().extend()等进行拼接处理,最后将列表转成数组. 示例1: >>> import numpy ...

  10. Python使用Paramiko实现SSH管理

    paramiko 是一个用于在Python中实现SSHv2协议的库,它支持对远程服务器进行加密的通信.目前该模块支持所有平台架构且自身遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接,你 ...