DEX文件解析--3、dex文件字符串解析
一、前言
前两篇文章链接:
1、DEX文件头解析
2、DEX文件校验和解析
PS:前几天检查文件夹的时候发现DEX文件解析还只写了开头,正好找点事情来做,就去接着解析DEX文件其余部分了。。。。。(还得多亏了一波疫情,不然都忘了还有这回事了。。。)
二、DEX文件中的字符串
1、DEX文件大致上可以粗略的分为3个部分:文件头、索引区以及数据区。而文件头一般来说占了整个DEX文件0x70个字节(还不了解DEX文件头的可以看一下我前面两篇文章),在文件头中,关于字符串的相关信息一共有8个字节,分别位于0x38(4 Bytes)和0x3c(4 Bytes)处,前者说明了该DEX文件包含了多少个字符串,后者则是字符串索引区的起始地址,但是需要注意的是,DEX存储是以小端序存储的(通俗一点的说就是从后往前读),如下所示:

2、前面我们通过文件头知道了字符串数量和字符串索引区起始地址等信息,接下来我们就来具体看一下字符串索引区。字符串索引区存储的是字符串真正存储在数据区的偏移地址,以4个字节为一组,表示一个字符串在数据区的偏移地址,所以索引区一个占字符串数量 X 4个字节那么多,同样的,索引区也采用的是小端序存储,所以我们在读取地址时,需要与小端序的方式来读取真正的地址,如下所示:

3、从上面我们已经知道了如何找到字符串在数据区的偏移地址,接下来我们需要做的就是解析这些数据区的字节。通过偏移地址我们可以在数据区找到代表字符串的这些字节,在DEX文件中,字符串是通过MUTF-8编码而成的(至于mutf-8是什么编码,我会将一些相关博客链接贴在文末),在MUTF-8编码中,第一个字节代表了这个字符串所需要用到的字节数目(不包括最后一个代表终结的字节),最后一个字节为0x00,表示这个字符串到此结束,跟c语言有点类似,中间部分才是一个字符串的具体内容,如下所示:(PS:mutf-8第一个字节还经过uleb128编码,所以简单的进行进制换算得到的字节数很多人奇怪对不上,由于比较复杂,就不过多解释了,想进一步了解更深的可以去看一下安卓源码中对DEX文件解析出字符串这一部分)

三、解析代码:
PS:我电脑运行环境--python3.6
代码如下:
import binascii
import os
import sys
def getStringsCount(f):
f.seek(0x38)
stringsId = f.read(4)
a = bytearray(stringsId)
a.reverse()
stringsId = bytes(a)
stringsId = str(binascii.b2a_hex(stringsId),encoding='UTF-8')
count = int(stringsId,16)
print('[+] stringSize ==> ' + str(count))
return count
def getStringByteArr(f,addr):
byteArr = bytearray()
f.seek(addr + 1)
b = f.read(1)
b = str(binascii.b2a_hex(b),encoding='UTF-8')
b = int(b,16)
index = 2
while b != 0:
byteArr.append(b)
f.seek(addr + index)
b = f.read(1)
b = str(binascii.b2a_hex(b),encoding='UTF-8')
b = int(b,16)
index = index + 1
return byteArr
def BytesToString(byteArr):
try:
bs = bytes(byteArr)
stringItem = str(bs,encoding='UTF-8')
print('[*] str = ' + stringItem)
return stringItem
except:
pass
def getAddress(addr):
address = bytearray(addr)
address.reverse()
address = bytes(address)
address = str(binascii.b2a_hex(address),encoding='UTF-8')
address = int(address,16)
return address
def getStrings(f,stringAmount):
stringsList = []
f.seek(0x3c)
stringOff = f.read(4)
Off = getAddress(stringOff)
f.seek(Off)
for i in range(stringAmount):
addr = f.read(4)
address = getAddress(addr)
byteArr = getStringByteArr(f,address)
stringItem = BytesToString(byteArr)
stringsList.append(stringItem)
Off = Off + 4
f.seek(Off)
if __name__ == '__main__':
filename = str(os.path.join(sys.path[0])) + '\\1.dex'
f = open(filename,'rb',True)
stringsCount = getStringsCount(f)
getStrings(f,stringsCount)
f.close()
运行截图:


四、一些总结
其实也没有什么好总结的,因为本身这没有什么难点之处,就记录一些遇见的问题吧!!!最开始解析字符串的时候发现MUTF-8编码的时候好不容易弄懂了的时候,发现还经过uleb128,所以最开始一直没办法通过第一个字节计算出需要编码的字节个数,最后取了个巧,从第二个字节开始读取知道读取到0x00为止;然后是怎么编码这些字节显示字符串,后来看了一下姜维大佬写的解析代码,发现直接用的是utf-8进行编码,转念一想,mutf-8也是utf-8的变种,所以大部分解析出来基本没有问题。写完代码后本来打算去看一下安卓源码是怎么解析这一块的再来模仿一下,但是这疫情让我已经耍了这么久了,实在没精神去看了,我还是接着去微博上蹲在@四川教育吧,看源码什么的还是开学了再说吧!!!
五、一下链接和附件
1、相关知识链接:
MUTF-8编码:https://blog.csdn.net/Roland_Sun/article/details/46716965
uleb128:https://blog.csdn.net/Roland_Sun/article/details/46708061
2、样本及代码下载链接:
百度网盘链接:https://pan.baidu.com/s/1_CQP7Zrj9LHcLOIjdGD95A;提取码:yc9y
DEX文件解析--3、dex文件字符串解析的更多相关文章
- plist文件、NSUserDefault 对文件进行存储的类、json格式解析
========================== 文件操作 ========================== Δ一 .plist文件 .plist文件是一个属性字典数组的一个文件: .plis ...
- XML文件解析并利用SimpleAdapter将解析结果显示在Activity中
首先创建一个实体类 Mp3Info用来存储解析的XML文件中的内容: public class Mp3Info implements Serializable{ private static fina ...
- C语言解析Ini格式文件
引用别人的博文: http://www.open-open.com/lib/view/open1402278076447.html 可以解析 INI 格式的字符串.解析文件.保存到文件. 下面是头文件 ...
- Java使用正则表达式解析LRC歌词文件
LRC歌词是一种应用广泛的歌词文件,各主流播放器都支持. lrc歌词文本中含有两类标签: 1.标识标签(ID-tags) [ar:艺人名] [ti:曲名] [al:专辑名] [by:编者(指编辑LRC ...
- 全面解析Linux数字文件权限
全面解析Linux数字文件权限 来源: 时间:2013-09-04 20:35:13 阅读数:11433 分享到:0 [导读] 在刚开始接触Linux时对于文件权限的理解并不是很透彻,这里详细 ...
- JavaWeb实现文件上传下载功能实例解析
转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...
- boost.spirit之解析C++头文件
环境:win7_64旗舰版,VS2008 场景:C++与lua交互是比较繁琐的,当我们编写一个C++类后,如果要给lua使用,就必须写一个lua包装类,将lua与原始C++类关联起来.其实这部分代码编 ...
- POI使用:解析xls/xlsx文件(兼容office2003/2007/2010版本)
package cn.eguid; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; imp ...
- C语言解析WAV音频文件
C语言解析WAV音频文件 代码地址: Github : https://github.com/CasterWx/c-wave-master 目录 前言 了解WAV音频文件 什么是二进制文件 WAV的二 ...
随机推荐
- 使用python求解向量值函数的雅各比(Jacobian)矩阵
考虑一个向量值函数$R^m \rightarrow R^n$,即$\textbf{y} = f(\textbf{x})$,它的雅各比(Jacobian)矩阵定义如下. 下面记录下一段使用python求 ...
- 【译】Announcing Entity Framework Core 5.0 Preview 5
今天我们宣布EF Core 5.0发布第五个预览版. 1 先决条件 EF Core 5.0 的预览版要求 .NET Standard 2.1.这意味着: EF Core 5.0 在 .NET Cor ...
- VScode Doxygen与Todo Tree插件的使用与安装
VScode Doxygen与Todo Tree插件的使用与安装 引言 程序中代码注释的规范和统一性是作为工程人员必不可少的技能,本文在Visual Studio Code的环境下简单介绍Doxyge ...
- java之FTP上传下载
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import ...
- java 中的 自定义viewUtils框架
在前面学习的基础上,我们自己编写一个ViewUtils注解框架类,不清楚的原理看前面的源代码 package im.weiyuan.com.viewutils; import android.supp ...
- 代码静态测试(java)
工欲善其事,必先利其器 环境 jdk1.8 IntelliJ IDEA 1.静态代码检查 1.1工具 阿里代码规范检测工具 安装教程:阿里代码规范检查工具 1.2规范等级 在 Snoar 中对代码规则 ...
- Android Studio 插件 ADBWifi 无线调试真机
长话短说,步骤如下 Android Studio 安装插件 ADB Wifi.这一步可以选择AS->Settings->Plugins->Market搜索:或者可以选择去插件官网下载 ...
- python将列表按行写入csv
import csv rows2 = ['abc1/ab1c','N'] for n in range(10): f = open("ok.csv", 'a',newline='' ...
- 如何在 asp.net core 3.x 的 startup.cs 文件中获取注入的服务
一.前言 从 18 年开始接触 .NET Core 开始,在私底下.工作中也开始慢慢从传统的 mvc 前后端一把梭,开始转向 web api + vue,之前自己有个半成品的 asp.net core ...
- 一张PDF了解JDK9 GC调优秘籍-附PDF下载
目录 简介 Oracle中的文档 JDK9中JVM参数的变化 废弃的JVM选项 不推荐(Deprecated)的JVM选项 被删除的JVM参数 JDK9的新特性Application Class Da ...