### frida注入hook脚本脱壳
脚本地址:[https://github.com/r0ysue/frida\_dump](https://github.com/r0ysue/frida_dump)
#### 使用dump_so
```
frida -U packagename -l dump_so.js
```
```
____
/ _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
[LGE AOSP on HammerHead::packagename]-> dump_so("name.so")
[name]: name.so
[base]: 0x99adf000
[size]: 0x2d4000
[path]: /data/app/packagename-2/lib/arm/name.so
[dump]: /data/user/0/packagename/files/name.so_0x99adf000_0x2d4000.so
undefined
[LGE AOSP on HammerHead::packagename]->
```
#### 使用dump_dex
```
frida -U --no-pause -f packagename -l dump_dex.js
```
```
/ _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
Spawned `packagename`. Resuming main thread!
[Google Pixel XL::packagename]-> [dlopen:] libart.so
_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE 0x7ac6dc4f74
[DefineClass:] 0x7ac6dc4f74
[dump dex]: /data/data/packagename/files/7aab800000_8341c4.dex
```
#### 文件位置
dump 后的文件一般在手机里面

#### 脚本代码
dump_dex.js
```
function get_self_process_name() {
var openPtr = Module.getExportByName('libc.so', 'open');
var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
var readPtr = Module.getExportByName("libc.so", "read");
var read = new NativeFunction(readPtr, "int", ["int", "pointer", "int"]);
var closePtr = Module.getExportByName('libc.so', 'close');
var close = new NativeFunction(closePtr, 'int', ['int']);
var path = Memory.allocUtf8String("/proc/self/cmdline");
var fd = open(path, 0);
if (fd != -1) {
var buffer = Memory.alloc(0x1000);
var result = read(fd, buffer, 0x1000);
close(fd);
result = ptr(buffer).readCString();
return result;
}
return "-1";
}
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 = {};
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_path = "/data/data/" + process_name + "/files/" + base.toString(16) + "_" + size.toString(16) + ".dex";
console.log("[find dex]:", dex_path);
var fd = new File(dex_path, "wb");
if (fd && fd != null) {
var dex_buffer = ptr(base).readByteArray(size);
fd.write(dex_buffer);
fd.flush();
fd.close();
console.log("[dump dex]:", dex_path);
}
}
}
}
}, onLeave: function (retval) {
}
});
}
}
var is_hook_libart = false;
function hook_dlopen() {
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
//console.log("dlopen:", path);
if (path.indexOf("libart.so") >= 0) {
this.can_hook_libart = true;
console.log("[dlopen:]", path);
}
}
},
onLeave: function (retval) {
if (this.can_hook_libart && !is_hook_libart) {
dump_dex();
is_hook_libart = true;
}
}
})
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
//console.log("android_dlopen_ext:", path);
if (path.indexOf("libart.so") >= 0) {
this.can_hook_libart = true;
console.log("[android_dlopen_ext:]", path);
}
}
},
onLeave: function (retval) {
if (this.can_hook_libart && !is_hook_libart) {
dump_dex();
is_hook_libart = true;
}
}
});
}
setImmediate(hook_dlopen);
```
dump_so.js
```
function dump_so(so_name) {
Java.perform(function () {
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
var libso = Process.getModuleByName(so_name);
console.log("[name]:", libso.name);
console.log("[base]:", libso.base);
console.log("[size]:", ptr(libso.size));
console.log("[path]:", libso.path);
var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
Memory.protect(ptr(libso.base), libso.size, 'rwx');
var libso_buffer = ptr(libso.base).readByteArray(libso.size);
file_handle.write(libso_buffer);
file_handle.flush();
file_handle.close();
console.log("[dump]:", file_path);
}
});
}
```
- 开发环境
- 安装开发环境
- pip下载换源
- python 下载加速
- 安装多个版本的python
- 使用pypy解释器
- 使用pyston解释器
- 生成和安装requirements.txt依赖
- python 3.10.11
- 环境
- 资源
- python安装模块的几种方法
- 常用操作类
- py310_db_20231021
- 使用nuitka打包
- nuitka常用指令
- 请求封装
- 代理ip测试
- 使用pyjion加速
- 20240608环境
- 大牛资源复制
- 编译成so文件
- python基础
- 变量与基本数据类型
- 变量
- 基本数据类型
- 运算符
- 流程控制
- if 语句
- while 循环
- for循环
- break,continue,pass
- with...as 语句
- 列表与元组
- 列表的创建和访问
- 列表的运算
- 列表元素的操作
- 元组的创建和访问
- 列表和元组 推导式
- 字典与集合
- 字典的创建和访问
- 字典元素的操作
- 字典推导式
- 集合的创建,元素的操作
- 集合的运算
- 字典排序
- 字符串与编码
- 字符串编码
- 字符串操作
- 字符串格式化
- 面向对象编程
- 函数
- 类
- 类里面的常用的方法
- 反射
- 异常处理和调试
- 异常
- 异常处理
- 文件/IO 操作
- 创建和关闭文件
- 写入和读取
- IO操作图片
- HTTP网络编程
- requests请求封装模块(一)
- requests请求封装模块(二)
- requests请求封装模块(三)
- http请求表单 multipart/form-data
- httpbin
- http
- http请求模块
- 使用代理IP
- http 请求 单独cookie
- http请求模块 session cookies
- 数据库
- 安装mysql数据库
- 操作mysql数据库
- MySql数据库链接池操作类
- SQLite数据库操作
- SQLite查询元组转字典
- SQLite数据库操作类
- SQLite数据库操作类2
- SQLite数据库链接池操作类
- aiosqlite 异步数据库操作类
- sqlite 数据库操作类
- 使用DuckDB数据库
- DuckDB数据库操作类
- DuckDB插入重复数据替换
- apsw sqlite操作类
- peewee sqlite数据库操作类
- sqlite3 数据库操作类
- 字典模式 sqlite3 操作类
- 字典模式 peewee 操作类
- Berkeley DB数据库操作
- Firebird 数据库操作
- sqlite3 运算符
- sqlite的数据类型
- sqlite 语句分页
- sqlite数据库去重复
- 多协程
- 协程 Coroutine
- 生成器 yield
- 异步IO框架-asyncio
- 异步IO框架-asyncio(二)
- 异步IO框架-asyncio(三)
- 协程 greenlet
- 协程 gevent
- 协程池 gevent.Pool
- 多线程
- 使用多线程
- 多线程中常用的方法
- 线程同步(锁)和通信
- 线程同步(锁)和通信(二)
- 使用队列的线程通信
- 使用队列管理线程-线程池
- 线程池-threadpool
- 线程池-ThreadPoolExecutor
- 线程池-ThreadPoolExecutor(二)
- 线程池-ThreadPoolExecutor(三)
- 多线程获取
- 线程池kun
- multiprocessing 线程池
- 多进程
- 使用多进程
- 多进程中常用的方法
- 进程同步(锁)和通信
- 进程同步(锁)和通信(二)
- 进程池-multiprocessing.Pool
- 进程池-ProcessPoolExecutor
- Flask web开发
- 安装调试 flask 模块
- Flask的Http方法
- 宝塔部署 flask 项目
- 错误处理机制
- fastapi 开发
- 入门
- 路径和参数
- 请求体
- html模板渲染
- 静态文件设置
- html发起GET请求
- html发起POST请求
- 重写异常
- 设置公共部分
- Jinja2 教程
- 使用hypercorn服务器
- 使用uvicorn服务器
- 使用vue.js 渲染html
- fastapi 设置响应超时
- post请求接收表单数据
- fastapi 上传文件
- asyncio 防止堵塞
- 设置cookie鉴权
- swagger
- request 对象
- response 对象
- 提前创建 和 退出前关闭
- fastapi接口压力测试
- 中间件使用技巧
- 使用ssl证书变成https
- 加密解密
- Base64
- AES
- RSA
- DES
- 加密算法
- MD5 哈希算法加密
- RSA公钥解密[解密对应私钥的加密]
- HMAC-SHA1
- OCR图像识别
- muggle_ocr
- ddddocr
- easyocr
- cv2裁剪图片
- 处理url中常见的图片
- 使用cv2 匹配滑块缺口
- 安卓逆向
- adb 手机调试
- frida
- frida-server
- objection
- objection注入报错 双进程保护
- frida-dexdump 安卓app脱壳
- Android-apktool 脱壳
- frida注入hook脚本脱壳
- Jadx 反编译
- 在安卓模拟器上使用frida
- SimpleHook
- 应用伪装
- python frida
- 使用 hook 脚本
- 编写hook 脚本
- 枚举当前加载的模块及模块中方法
- 万能的hook Md5 脚本
- hook常用js函数封装
- frida工具-FridaInfoShow
- frida工具-fridaUiTools
- frida工具-appmon
- frida工具-ZenTracer-master
- frida工具-Dwarf
- frida工具-lamda
- frida抓包工具 r0capture
- 脱壳工具
- python调用浏览器
- 常用方法
- for while 循环显示进度
- 打印艺术字或者图案
- json.dumps()中文乱码
- 队列构造循环池
- 模糊匹配 in 关键词用法
- python中的编码声明
- 列表平均分割
- requests 不使用代理 防止抓包
- 递增矩阵算法
- 判断是否是中文
- 数组内的字典关键词排序
- 垃圾回收释放内存
- 打印异常程序不停止
- 判断json数据
- 判断url是否合法
- 字符串空格步长统一和数组转字符串
- 监控内存使用情况
- 监控cpu使用情况
- 获取机器码
- 取16个随机字符串加密
- parsel解析html
- 三元表达式
- py调用js函数
- js加密算法-护世界app
- 中国大学AES例子
- 字典转字符串
- 提取requests里面cookie
- MD5算法js还原
- 优学院app一个md5算法
- 字符串转字节和字节数组
- 池馆一个js-AES-CRT算法
- 屏蔽抓包工具
- request重定向
- 常用获取时间接口
- bs4解析html
- 递归例子
- bs4 查找匹配
- 使用socks5代理
- 检测代理ip
- json解析优化
- python代码可视化
- 读写文件操作技巧
- requests模块优化
- 模块优化
- bs4截取js里面字符串
- requests传递多个同名参数
- 压力测试
- gevent模块报错
- nuitka 查看所有插件
- nuitka
- nuitka打包指定插件位置
- 修改python中sqlite3版本
- 使用pyinstaller打包
- pyinstaller打包 exe 反编译逆向
- execjs执行js报错;UnicodeEncodeError: ‘gbk‘
- 截取html标签里面的字符串
- lxml解析网页
- lxml使用css选择器
- 常用排序
- 字典循环输出
- 模块包技巧
- 调用验证码接口
- bs4 技巧
- 查看对象大小
- 运行的时候不生成pyc
- requests慢 浏览器 postman正常
- 数组相同分配
- 常用的时间转换方法
- tcp网络调优
- 防止未知报错闪退
- bs4报错UnicodeEncodeError
- 多条件判断优化
- 判断字符串中是否包含中文
- 读取文件报错 UnicodeDecodeError: 'gbk' ...
- 常规数据正则匹配验证
- 题目字符串截取方案
- fastapi防止堵塞的方案分析
- 调试内存泄漏
- 判断字符串中英文
- 获取系统信息
- curl_cffi和request模块一样牛逼的模块
- js逆向
- 使用fiddler修改网页的js
- 浏览器hook算法