什么是 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` - 博客园相关推荐

  1. 限制会话id服务端不共享_会话控制 - able-woman - 博客园

    会话控制是什么? cookie和session都是跟踪整个会话过程的技术手段.而会话,就是用户通过浏览器和服务器的一次通话. 为什么要有会话控制? 因为HTTP协议是无状态的,服务器不知道用户上一次做 ...

  2. java代码画樱花飘落_一行代码引入博客园樱花飘落特效

    前言 博客园作为面向大众的博客, 个性新颖可以博得一赞, 简约美观也不失阅读体验, 本文对樱花特效js进行了解读, 发现作者的设计确实秒不可言, 即使没有注释, 思路展示的也很清晰. 那就废话不多说, ...

  3. python博客园_用Python向博客园发布新文章

    最近在开发一个博客系统,经常把写的东西放在自己网站的博客上(之前写在Onenote),然后我在博客园也申请了一个博客,就有了同样一篇文章,我需要复制粘贴排版分别提交两次的情况.于是我就想能不能在我的网 ...

  4. java 粒子滤波_粒子滤波 - gary_123 - 博客园

    跟着博主http://blog.csdn.net/heyijia0327/article/details/40899819一起学习 尽管利用高斯逼近能有效解决许多滤波问题,但当滤波分布为多模型或某些状 ...

  5. mysql与串口通信_串口通信 - ShawnXie - 博客园

    1.并行通信 2.串口通信 (1)同步通信(synchronous data communication,SYNC) 指在约定的通信速率下,发送端和接收端的时钟信号频率和相位始终保持一致(同步),保证 ...

  6. java数字常量_数字常量 - javawebsoa - 博客园

    数字常量 shell脚本在默认情况下都是把数字作为10进制数来处理, 除非这个数字采用了特殊的标记或者前缀. 如果数字以0开头的话那么就是8进制数. 如果数字以0x开头的话那么就是16进制数. 如果数 ...

  7. java计算雷达扫描范围_雷达扫描 - linyinmobayu - 博客园

    1.设计思想 雷达扫描图,在影视作品中见到较多,比如飞机雷达.舰艇雷达,有一个扫描线转圈代表雷达一周旋转或一个批次的收发,发现目标就在表盘上标记位置.和汽车仪表盘类似,汽车仪表盘有底盘背景图.同圆.刻 ...

  8. java 熔断_熔断理解 - THISISPAN - 博客园

    服务熔断的理解 服务熔断也称服务隔离,来自于Michael Nygard 的<Release It>中的CircuitBreaker应用模式,Martin Fowler在博文Circuit ...

  9. java元类_元类 - 一心不乱 - 博客园

    我们使用class机制产生的类,然后在通过类产生的对象 而类实际上都是通过type来实现的 首先确定type里需要添加哪些元素 class_name = 'A'   类名 class_base = ( ...

  10. 斯特林数 java实现_斯特林数 - BILL666 - 博客园

    第一类斯特林数 定义 \(\left[\begin{matrix}n\\m\end{matrix}\right]\) 表示将\(n\)个带标号的元素放入\(m\)个不带标号的环的方案数 递推式 \[\ ...

最新文章

  1. 优秀的PHP程序员至少应该了解PHP代码的优缺点(转)
  2. android view flipper,安卓控件——ViewFlipper
  3. Android:ListView常见错位之CheckBox错位
  4. 节能prru进入深度休眠节能_2021-2024年中国工业节能行业深度调研及投资前景预测报告...
  5. Java消息服务~消息属性
  6. 理解 JavaScript 的 async/await
  7. 文学系列:《叶之震颤》读书笔记
  8. Debian 8 Jessie desktop on arm
  9. 漫话:如何给女朋友解释什么是反向代理、正向代理?
  10. 感知机算法的对偶形式
  11. 怎样找回W ndows7密钥,怎么找到windows7密钥
  12. 使用UCSC基因组浏览器可视化测序深度分布数据
  13. Cython使用技巧
  14. dubbo官网最新版导航
  15. 市场营销问题 (二):产品属性的效用函数
  16. 青少年CTF-弱口令实验室招新赛部分wp复现步骤
  17. c语言录入信息后无法显示桌面,输入法在桌面不显示,怎么修改能显示在桌面任 – 手机爱问...
  18. 支付宝手机网页唤醒app支付
  19. Win10 下安装Mathtype6.9 + office2013+EndNote-x8
  20. linux递归替换目下所有文件的某个特定字符串

热门文章

  1. 8.5 专业的“对口” ——《逆袭大学》连载
  2. 程序员应知必会的思维模型之 13 侯世达定律 (Hofstadter‘s Law)
  3. 如何选择和阅读科技论文
  4. 软工网络15团队作业4——Alpha阶段敏捷冲刺之Scrum 冲刺博客(Day6)
  5. “做自己擅长又有兴趣的事情,是最幸福最快乐的” – 记我的大学老师
  6. IT大学生成长周报 | 第 4 期
  7. 如何制定一份测试工程师年度计划
  8. 共享文件问题: 你可能没有权限使用网络资源。请与这台服务器的管理员联系以查明你是否有访问权限。
  9. vue报错 | Duplicate keys detected: ‘0’. This may cause an update error.
  10. 坚持十年博客写作,不忘初心,方得始终