jar脱壳_软件脱壳 - Rannie` - 博客园
什么是 dex 文件
他是Android系统的可执行文件,包含应用程序的全部操作指令以及运行时数据。
由于dalvik是一种针对嵌入式设备而特殊设计的java虚拟机,所以dex文件与标准的class文件在结构设计上有着本质的区别
当java程序编译成class后,还需要使用dx工具将所有的class文件整合到一个dex文件,目的是其中各个类能够共享数据,在一定程度上降低了冗余,同时也是文件结构更加经凑,实验表明,dex文件是传统jar文件大小的50%左右
可以看见:
dex将原来class每个文件都有的共有信息合成一体,这样减少了class的冗余
数据结构
类型
含义
u1
unit8_t,1字节无符号数
u2
unit16_t,2字节无符号数
u4
unit32_t,4字节无符号数
u8
unit64_t,8字节无符号数
sleb128
有符号LEB128,可变长度1~5
uleb128
无符号LEB128,
uleb128p1
无符号LEB128值加1,
dex文件结构
首先从宏观上来说 dex 的文件结构很简单,实际上是由多个不同结构的数据体以首尾相接的方式拼接而成。如下图:
数据名称
解释
header
dex文件头部,记录整个dex文件的相关属性
string_ids
字符串数据索引,记录了每个字符串在数据区的偏移量
type_ids
类似数据索引,记录了每个类型的字符串索引
proto_ids
原型数据索引,记录了方法声明的字符串,返回类型字符串,参数列表
field_ids
字段数据索引,记录了所属类,类型以及方法名
method_ids
类方法索引,记录方法所属类名,方法声明以及方法名等信息
class_defs
类定义数据索引,记录指定类各类信息,包括接口,超类,类数据偏移量
data
数据区,保存了各个类的真是数据
link_data
连接数据区
header
简单记录了dex文件的一些基本信息,以及大致的数据分布。长度固定为0x70,其中每一项信息所占用的内存空间也是固定的,好处是虚拟机在处理dex时不用考虑dex文件的多样性
字段名称
偏移值
长度
说明
magic
0x0
8
魔术字段,值为"dex\n035\0"
checksum
0x8
4
校验码
signature
0xc
20
sha-1签名
file_size
0x20
4
dex文件总长度
header_size
0x24
4
文件头长度,009版本=0x5c,035版本=0x70
endian_tag
0x28
4
标示字节顺序的常量
link_size
0x2c
4
链接段的大小,如果为0就是静态链接
link_off
0x30
4
链接段的开始位置
map_off
0x34
4
map数据基址
string_ids_size
0x38
4
字符串列表中字符串个数
string_ids_off
0x3c
4
字符串列表基址
type_ids_size
0x40
4
类列表里的类型个数
type_ids_off
0x44
4
类列表基址
proto_ids_size
0x48
4
原型列表里面的原型个数
proto_ids_off
0x4c
4
原型列表基址
field_ids_size
0x50
4
字段个数
field_ids_off
0x54
4
字段列表基址
method_ids_size
0x58
4
方法个数
method_ids_off
0x5c
4
方法列表基址
class_defs_size
0x60
4
类定义标中类的个数
class_defs_off
0x64
4
类定义列表基址
data_size
0x68
4
数据段的大小,必须4k对齐
data_off
0x6c
4
数据段基址
magic
标识一个有效的dex文件,他的固定值为:64 65 78 0a 30 33 35 00,转换为字符串为dex.035.
在电子取证中也称“文件签名”
checksum
他是整个头部的校验和。它被用来校验头部是否损坏
signature
二次打包时的签名
file_size
记录包括dexHeader在内的整个dex文件大小,用来计算偏移和方便定位某区段(section),他也有诸如唯一的标识dex,因为他是dex文件中计算sha-1区段的一个组成部分
header_size
存放整个DexHeadeer结构体的长度,它也可用来计算下一个区段在文件中的起始位置,目前值为0x70
脱壳原理
什么是软件脱壳?
软件脱壳,顾名思义,就是对软件加壳的逆操作,把软件上存在的壳去掉
加固是如何运行起来的?
-->APP启动
-->壳dex先加载起来
-->壳负责把源dex文件读出来
-->壳把源dex文件解密
-->把解密后的dex加载进内存 源dex运行起来
原理:
源dex文件最终会加载进内存
Hook加载Dex的函数,把Dex从内存中dump出来
Hook DexFile::OpenMemory()
DexFile::OpenMemory(const uint8_t* base,
size_t size,
const std::string& location,
uint32_t location_checksum,
MemMap* mem_map,//nullptr
const OatDexFile* oat_dex_file,
std::string* error_msg)
脱壳方案
方案一:Xposed + Fdex2
方案二:Frida 脱壳
1、启动手机内的 frida-server 并进行端口转发。27043 27042
2、导出 Android 的 /system/lib/libart.so 到本地。然后使用 IDA 查看 OpenMemory 对应的签名函数名。我这里对应的是 _ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_
import frida
import sys
package = 'com.iCitySuzhou.suzhou001'
def on_message(message, data):
if message['type'] == 'send':
print(f"[*] {message['payload']}")
else:
print(message)
# OpenMenory 在 libart.so 中,art 虚拟机(安卓5),davlink 虚拟机(安卓4)
# Hook OpenMemory 的导出方法
# 用 IDA 打开 libart.so ,查看 OpenMemory 的到处方法名
# OpenMemory 的第一个参数是 dex 文件在内存中的其实位置
# 根据 dex 文件格式,从其实位置开始第32个字节是该 dex 文件的大小
# 知道 dex 起始位置和整个文件大小,只需要把这段内存 dump 出来即可
# 使用于 安卓6 7 8 9
src = """
var openMemory_address = Module.findExportByName("libart.so", "_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_")
Interceptor.attach(openMemory_address, {
onEnter: function(args){
// dex 文件的起始位置
var dex_begin_address = args[1]
//dex 文件的前 8 个字节是 magic 字段
// 打印 magic (会显示“dex 035”)三个字符,可以验证是否为 dex 文件
console.log("magic:" + Memory.readUtf8String(dex_begin_address))
// 把地址转换成整形,再加32
//因为 dex 文件的第32个字节处存放的是 dex 文件的大小
var address = parseInt(dex_begin_address, 16) + 0x20
// 把 address 地址指向的内存值读出来,该值就是 dex 的文件大小
// ptr(address)转换的原因是 frida 只接受 NativePointer 类型指针
var dex_size = Memory.readInt(ptr(address))
console.log("dex_size:" + dex_size)
//frida 写入文件,把内存中的数据写到本地
var timestamp = new Date().getTime();
var file = new File("/data/data/%s/" + timestamp + ".dex", "wb")
// Memory.readByteArray(begin, length)
// 把内存里的数据读出来,从 begin 开始读,取 length 长度
file.write(Memory.readByteArray(dex_begin_address, dex_size))
file.flush()
file.close()
send("dex begin address: "+parseInt(dex_begin_address,16))
send("dex file size:" +dex_size)
},
onLeave: function (retval) {
if (retval.toInt32() > 0){
}
}
});
"""%(package)
print(f"dex 导出目录为: /data/data/{package}")
device = frida.get_remote_device()
pid = device.spawn(package)
session = device.attach(pid)
script =session.create_script(src)
script.on("message", on_message)
script.load()
device.resume(pid)
sys.stdin.read()
输出:
D:\Python\python.exe E:/wx_h5/frida_dev.py
dex 导出目录为: /data/data/com.iCitySuzhou.suzhou001
magic:dex
035
dex_size:5993048
[*] dex begin address: 3760596376
[*] dex file size:5993048
magic:dex
035
dex_size:292
[*] dex begin address: 4111687680
[*] dex file size:292
magic:dex
035
dex_size:292
[*] dex begin address: 4098458380
[*] dex file size:292
magic:dex
035
dex_size:5542488
[*] dex begin address: 3761046936
[*] dex file size:5542488
magic:dex
035
dex_size:143416
[*] dex begin address: 3729728852
[*] dex file size:143416
magic:dex
035
dex_size:5432740
[*] dex begin address: 3697659272
[*] dex file size:5432740
magic:dex
035
dex_size:74656
[*] dex begin address: 3723183372
[*] dex file size:74656
magic:dex
035
dex_size:358828
[*] dex begin address: 3536693200
[*] dex file size:358828
magic:dex
035
dex_size:358828
[*] dex begin address: 3536693200
[*] dex file size:358828
到手机上看,脱壳成功
然后使用 adb 命令 pull 到本地,用 jadx 打开
需要将手机里的目录加上权限
chmod -R 777 目标文件夹
jar脱壳_软件脱壳 - Rannie` - 博客园相关推荐
- 限制会话id服务端不共享_会话控制 - able-woman - 博客园
会话控制是什么? cookie和session都是跟踪整个会话过程的技术手段.而会话,就是用户通过浏览器和服务器的一次通话. 为什么要有会话控制? 因为HTTP协议是无状态的,服务器不知道用户上一次做 ...
- java代码画樱花飘落_一行代码引入博客园樱花飘落特效
前言 博客园作为面向大众的博客, 个性新颖可以博得一赞, 简约美观也不失阅读体验, 本文对樱花特效js进行了解读, 发现作者的设计确实秒不可言, 即使没有注释, 思路展示的也很清晰. 那就废话不多说, ...
- python博客园_用Python向博客园发布新文章
最近在开发一个博客系统,经常把写的东西放在自己网站的博客上(之前写在Onenote),然后我在博客园也申请了一个博客,就有了同样一篇文章,我需要复制粘贴排版分别提交两次的情况.于是我就想能不能在我的网 ...
- java 粒子滤波_粒子滤波 - gary_123 - 博客园
跟着博主http://blog.csdn.net/heyijia0327/article/details/40899819一起学习 尽管利用高斯逼近能有效解决许多滤波问题,但当滤波分布为多模型或某些状 ...
- mysql与串口通信_串口通信 - ShawnXie - 博客园
1.并行通信 2.串口通信 (1)同步通信(synchronous data communication,SYNC) 指在约定的通信速率下,发送端和接收端的时钟信号频率和相位始终保持一致(同步),保证 ...
- java数字常量_数字常量 - javawebsoa - 博客园
数字常量 shell脚本在默认情况下都是把数字作为10进制数来处理, 除非这个数字采用了特殊的标记或者前缀. 如果数字以0开头的话那么就是8进制数. 如果数字以0x开头的话那么就是16进制数. 如果数 ...
- java计算雷达扫描范围_雷达扫描 - linyinmobayu - 博客园
1.设计思想 雷达扫描图,在影视作品中见到较多,比如飞机雷达.舰艇雷达,有一个扫描线转圈代表雷达一周旋转或一个批次的收发,发现目标就在表盘上标记位置.和汽车仪表盘类似,汽车仪表盘有底盘背景图.同圆.刻 ...
- java 熔断_熔断理解 - THISISPAN - 博客园
服务熔断的理解 服务熔断也称服务隔离,来自于Michael Nygard 的<Release It>中的CircuitBreaker应用模式,Martin Fowler在博文Circuit ...
- java元类_元类 - 一心不乱 - 博客园
我们使用class机制产生的类,然后在通过类产生的对象 而类实际上都是通过type来实现的 首先确定type里需要添加哪些元素 class_name = 'A' 类名 class_base = ( ...
- 斯特林数 java实现_斯特林数 - BILL666 - 博客园
第一类斯特林数 定义 \(\left[\begin{matrix}n\\m\end{matrix}\right]\) 表示将\(n\)个带标号的元素放入\(m\)个不带标号的环的方案数 递推式 \[\ ...
最新文章
- 优秀的PHP程序员至少应该了解PHP代码的优缺点(转)
- android view flipper,安卓控件——ViewFlipper
- Android:ListView常见错位之CheckBox错位
- 节能prru进入深度休眠节能_2021-2024年中国工业节能行业深度调研及投资前景预测报告...
- Java消息服务~消息属性
- 理解 JavaScript 的 async/await
- 文学系列:《叶之震颤》读书笔记
- Debian 8 Jessie desktop on arm
- 漫话:如何给女朋友解释什么是反向代理、正向代理?
- 感知机算法的对偶形式
- 怎样找回W ndows7密钥,怎么找到windows7密钥
- 使用UCSC基因组浏览器可视化测序深度分布数据
- Cython使用技巧
- dubbo官网最新版导航
- 市场营销问题 (二):产品属性的效用函数
- 青少年CTF-弱口令实验室招新赛部分wp复现步骤
- c语言录入信息后无法显示桌面,输入法在桌面不显示,怎么修改能显示在桌面任 – 手机爱问...
- 支付宝手机网页唤醒app支付
- Win10 下安装Mathtype6.9 + office2013+EndNote-x8
- linux递归替换目下所有文件的某个特定字符串
热门文章
- 8.5 专业的“对口” ——《逆袭大学》连载
- 程序员应知必会的思维模型之 13 侯世达定律 (Hofstadter‘s Law)
- 如何选择和阅读科技论文
- 软工网络15团队作业4——Alpha阶段敏捷冲刺之Scrum 冲刺博客(Day6)
- “做自己擅长又有兴趣的事情,是最幸福最快乐的” – 记我的大学老师
- IT大学生成长周报 | 第 4 期
- 如何制定一份测试工程师年度计划
- 共享文件问题: 你可能没有权限使用网络资源。请与这台服务器的管理员联系以查明你是否有访问权限。
- vue报错 | Duplicate keys detected: ‘0’. This may cause an update error.
- 坚持十年博客写作,不忘初心,方得始终