Android应用逆向分析技术综述
软件逆向工程原理与实践第8章Android应用程序逆向分析

第8章 Android应用程序逆向分析
(3) AndroidManifest.xml:Android配置文件,编译过程 依然被转换为AXML格式;
第8章 Android应用程序逆向分析
8.2.1 APKTool APKTool是Google提供的APK反编译工具,可安装反编
译系统APK所需要的framework-res框架,能够反编译APK, 并且可以清理上次反编译文件夹。
安装和使用步骤如下: (1) 配置Java运行环境; (2) 下载并安装APKTool; (3) 打开Windows命令窗口;
APKTool的所有操作均在Windows命令窗口中输入 “apktool”命令来查看。操作完成后,可以得到应用程序的 资源文件,smali文件和Manifest.xml文件。直接点击 Manifest.xml文件可以在浏览器中查看相关信息。
第8章 Android应用程序逆向分析
8.2.2 dex2jar dex2jar也是一款开源软件。它集成了Java库,可将原本
第ali反汇编得到smali文件,阅读反汇编出 的smali文件。
(2) 使用dex2jar生成jar文件,再使用jd-gui生成Java源代 码,阅读生成的Java源代码。
(3) 使用JEB、APK Studio等高级工具。
第8章 Android应用程序逆向分析
第8章 Android应用程序逆向分析
4.反编译APK获取Java源码并分析 将应用程序反编译成可读的Java源码,然后审查该代码, 了解应用程序的所有行为。在此过程中,分析源码审查开放 的端口、共享/传输的数据,以及Socket连接等是关键的考量。 根据8.2节介绍的方法,首先对APK文件进行解压(或修改后 缀解压),从中提取出classes.dex文件;使用dex2jar工具,将 classes.dex文件转换成jar文件,如图8-11所示;然后,使用 jd-gui分析这个classes.jar文件,如图8-12所示。
app逆向分析总结

App逆向分析总结引言App逆向分析是指通过分析已发布的应用程序的代码和运行机制,了解其实现原理,甚至修改或破解应用的技术过程。
逆向分析在信息安全领域中被广泛使用,可以帮助开发者了解自己应用中存在的潜在安全隐患,并采取相应措施加以改进。
本文将总结App逆向分析的一般步骤和常用工具,以及对逆向分析的思考和建议。
逆向分析步骤App逆向分析通常包括以下几个步骤:1. 反编译首先,我们需要将App的安装文件反编译为源代码。
这一步可以让我们获取到应用程序的主要逻辑和实现细节。
常用的反编译工具包括Apktool和Jadx。
Apktool可以解开apk文件,还原出资源文件、smali文件和一些配置文件等等。
而Jadx可以将apk文件直接反编译为Java源代码,让我们更方便地阅读和分析。
2. 静态分析静态分析是指对反编译源代码的静态分析。
在这一步,我们可以阅读和分析应用程序的源代码,理解其功能和实现细节。
可以使用诸如IDE、文本编辑器等工具来进行静态分析。
此外,还可以使用工具来查找漏洞或敏感信息泄露,例如使用grep命令进行关键词搜索。
3. 动态分析动态分析是指对应用程序的运行时行为进行分析。
这一步可以通过模拟器、调试器或者hook技术来实现。
通过观察和记录应用程序在运行过程中的行为,可以更加深入地了解应用程序的工作原理。
例如,可以使用frida或Xposed框架来hook应用程序的函数,以监听和拦截特定的函数调用和参数。
4. 寻找漏洞在完成上述步骤后,我们可以根据静态和动态分析的结果来寻找应用程序中的漏洞。
这些漏洞可能包括未经授权的接口访问、弱加密算法使用、未对用户输入进行合理校验等。
一旦发现漏洞,我们需要及时通知开发者,并提供相应的建议和修复方案。
常用工具以下是一些常用的逆向分析工具:•Apktool:用于反编译和重新打包apk文件。
•Jadx:用于将apk文件反编译为Java源代码。
•Frida:用于hook应用程序的函数,以实现动态分析。
Android逆向之dex2oat的实现解析

Android逆向之dex2oat的实现解析⽬录简介dex2oat介绍为什么要使⽤dex2oat进⾏转换dex2oat代码1.dex2oat类定义2.OpenDexFiles函数定义3.dex2oat⼊⼝函数定义总结简介在Android系统5.0及以上系统开始逐渐丢弃Dalvik虚拟机,由于ART虚拟机对内存分配和回收都做了算法优化,降低了内存碎⽚化程度,回收时间也得以缩短,所有android系统5.0及以上都在主推ART虚拟机。
在ART虚拟机中ART则会将Dex通过dex2oat⼯具编译得到⼀个ELF⽂件,它是⼀个可执⾏的⽂件。
所以下⾯我们就针对ART的dex2oat实现进⾏做分析。
dex2oat介绍Dex2oat的全称是:dalvik excutable file to optimized art file,它是⼀个对 android系统下的dex⽂件,进⾏编译优化的程序。
通过dex2oat的编译优化,可以⼤⼤的提⾼android系统的启动的速度和使⽤⼿机过程的的流畅度。
dex2oat在安卓⼿机环境下的存放位置为/system/bin/dex2oatdex2oat在开源系统中的路径为\art\dex2oat\。
为什么要使⽤dex2oat进⾏转换在android系统中,Android 虚拟机可以识别到的是dex⽂件,App应⽤在使⽤过程中如果每次将dex⽂件加载进⾏内存,解释性执⾏字节码,效率就会变得⾮常低,从⽽影响到⽤户在使⽤安卓⼿机的体验。
通过利⽤dex2oat进⾏优化处理,那么可以在android系统运⾏之前,利⽤合适的时机将dex⽂件字节码,提前转化为虚拟机上可以执⾏运⾏的机器码,后续直接从效率更⾼的机器码中运⾏,则运⾏阶段更加流畅,优化⽤户体验。
dex2oat代码1.dex2oat类定义class Dex2Oat {public://创建函数,返回值为bool,static bool Create(Dex2Oat** p_dex2oat,Compiler::Kind compiler_kind,InstructionSet instruction_set,InstructionSetFeatures instruction_set_features,VerificationResults* verification_results,DexFileToMethodInlinerMap* method_inliner_map,size_t thread_count)SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {//判断参数传递进来的释放为空CHECK(verification_results != nullptr);CHECK(method_inliner_map != nullptr);//⽤智能指针⽅式进⾏去实例化dex2oatstd::unique_ptr<Dex2Oat> dex2oat(new Dex2Oat(&compiler_options,compiler_kind,instruction_set,instruction_set_features,verification_results,method_inliner_map,thread_count));if (!dex2oat->CreateRuntime(runtime_options, instruction_set)) {*p_dex2oat = nullptr;return false;}*p_dex2oat = dex2oat.release();return true;}//dex2oat的虚构函数,⽤于释放操作。
移动应用安全测试中的反调试与反逆向技术

移动应用安全测试中的反调试与反逆向技术随着移动应用的普及和发展,移动应用安全问题也逐渐受到人们的关注。
为了保护用户的隐私和数据安全,开发者需要加强对应用的安全性测试。
其中,反调试与反逆向技术作为移动应用安全测试的重要手段之一,能够有效提升应用的抗攻击性。
本文将介绍移动应用安全测试中的反调试与反逆向技术,并探讨其应用和意义。
一、什么是反调试技术反调试技术是一种用于阻止恶意用户对应用进行调试的技术。
在移动应用开发过程中,开发者经常需要对自己的应用进行调试以修复bug 或优化性能。
然而,黑客或破解者也可以利用调试器来分析应用的运行机制并窃取应用的敏感信息或修改应用的行为。
因此,开发者在发布应用时需要采取措施来防止应用被非法调试。
反调试技术可以采用多种手段来实现,例如运行时监测、检测调试器存在、检测调试器中的调试指令等。
这些技术可以检测到调试器的存在,并触发相应的反调试机制。
常见的反调试技术包括检测调试器标志位、检测调试器中的调试指令、检测调试器中的调试事件等。
二、什么是反逆向技术反逆向技术是一种用于防止应用被逆向工程分析的技术。
逆向工程是指通过分析应用的二进制代码或执行逻辑,还原出应用的源代码或运行过程。
黑客或破解者可以通过逆向工程来破解应用的加密算法、绕过应用的安全检测、修改应用的行为等,从而对应用进行非法操作。
为了保护应用的安全性,开发者需要采取一些措施来防止应用被逆向工程。
反逆向技术可以采用多种手段来实现,例如代码混淆、反调试技术、加密算法等。
这些技术可以增加逆向工程的难度,使黑客或破解者无法轻易分析应用的源代码或执行逻辑。
三、反调试与反逆向技术在移动应用安全测试中的应用反调试与反逆向技术在移动应用安全测试中起到了至关重要的作用。
移动应用安全测试旨在检测应用的漏洞、弱点或潜在安全风险,并提供相应的修复建议。
如果移动应用本身存在反调试或反逆向技术,那么安全测试人员需要先解决这些技术,才能对应用进行全面的安全测试。
《2024年Android恶意应用智能化分析方法研究综述》范文

《Android恶意应用智能化分析方法研究综述》篇一一、引言随着移动互联网的飞速发展,Android操作系统因其开放性和普及性,已成为全球范围内使用最广泛的移动平台之一。
然而,随之而来的安全问题也日益凸显,其中恶意应用的威胁尤为严重。
为了有效应对这一挑战,Android恶意应用的智能化分析方法成为了研究的热点。
本文旨在全面综述Android恶意应用智能化分析方法的研究现状、主要技术及发展趋势。
二、Android恶意应用概述Android恶意应用是指通过非法手段侵入用户设备,窃取用户信息、破坏系统功能或进行其他非法活动的应用程序。
这些应用往往隐藏在正规应用市场中,甚至通过伪造用户评价等方式欺骗用户下载安装。
因此,对Android恶意应用的智能化分析显得尤为重要。
三、Android恶意应用智能化分析方法1. 基于静态分析的技术静态分析是一种不执行代码而直接从代码本身提取信息的方法。
在Android恶意应用分析中,静态分析主要通过对APK文件进行反编译、提取代码特征等方式,识别出潜在的恶意行为。
这种方法具有速度快、效率高的特点,但易受代码混淆和加密技术的影响。
2. 基于动态分析的技术动态分析是通过在真实或模拟环境中执行应用程序,观察其行为并收集相关信息来识别恶意行为的方法。
这种方法可以有效地绕过代码混淆和加密技术,但需要较长的分析时间和较高的计算资源。
3. 基于机器学习的技术随着机器学习技术的发展,越来越多的研究开始将机器学习应用于Android恶意应用的智能化分析。
这种方法通过训练模型来识别恶意应用的特征和行为模式,具有较高的准确性和泛化能力。
目前,深度学习等先进的机器学习技术在该领域也得到了广泛应用。
四、主要技术及其研究进展1. 静态分析技术研究进展随着静态分析技术的不断发展,研究者们提出了许多新的算法和工具,如基于权限检查的静态分析工具、基于API调用的行为模式检测方法等。
这些方法可以有效提高对未知恶意应用的检测能力。
Android应用程序逆向工程和分析指南说明书

RECORDS ANY “SINKS” ENCOUNTERED
REVIEW COMMS
Combines the information gathered with manifest details for later use
Examines WebView configurations and provides templated HTML files for validation of vulnerabilities
CONTACT INFO
Tony Trummer • /in/tonytrummer
@SecBro1
Tushar Dalvi • /in/tdalvi
@tushardalvi
APK Structure
Android Manifest.xml Permissions Component exporting Name, version, etc
/res Resources not in resources.arsc
Images Layouts
classes.dex Dalvik Bytecode
Service
OnCreate() OnBind()
OnStartCommand() OnUnbind() OnDestroy()
Provider
.query() .update() .delete() .insert()
Receiver
.OnReceive()
COMMUNICATION
Multiple decompilers to provide better results
学习Android安全和逆向开发的路线总结
此篇整理了最完整的--Android逆向学习线路知识体系。
希望给迷糊的入门者指出一个明确的方向。
真心建议:先正向开发几年再搞逆向吧……正向都不会破解的是啥?不看代码只会脱壳?只会xposed ?远远不够,hook只是很小一部分技术,xposed 是hook功能众多框架中的一个而已。
相对于任何程序的开发来说,逆向知识点很少很少了,关键是基础知识,基础就是正向开发经验。
学习Android逆向之前,必备条件。
【必备,出去面试正经公司的安全岗位都会问的基础问题】•从事3-5年真实的Android开发工作,熟练使用C/C++,Java,kotlin,dart 等Android开发常用语言;•熟悉Android NDK开发和JNI技术,熟悉Log原理。
最好有几年FrameWork开发经验;•熟悉Android虚拟机机制,打包原理,系统启动流程,App启动流程;•了解ARM、Smali汇编语言,熟悉IPC原理,能够熟练搭建IPC框架;•熟练使用Fiddler和Charles抓包工具进行抓包;•最好熟悉Python基础语法,并能写简单的脚本和爬虫。
第一阶段:Android 基础知识回顾:•回顾Android 开发编程,深入理解Android系统原理和层次结构,深入分析Handler源码和原理;•回顾Java,C/C++,Kotlin、dart 在Android开发中必用的语言,熟悉一下几种语言混淆后的特性;•回顾Android IPC和JNI的底层原理和热更新技术回顾Native开发要点,使用C++结合NDK完成Android Native开发;•回顾Android开发中常用的 AMS、PMS、WMS原理和App启动中服务加载的流程;•回顾Android开发中必用的 Google的MVVM框架:DataBinding+LiveData+ViewModel;•回顾Android开发中必用的 Google的MVP框架:Dagger2;•回顾Android开发必用的网络架构:Okhttp3+RxJava2+Retrofit2+Rxdownload4+Rxcache+Glide;Android 逆向基础知识:•熟悉Android逆向工具的使用,如apktool,IDA,dex2jar,JEB,Androidkiller,Androguard等;•深入分析APK中包含的各文件格式,分析Android系统源码中解析APK的相关代码;学习和熟悉smali语言(重点);•仿微信写一个APP,并利用工具逆向出apk内的代码,并对比源码分析。
安卓应用反编译技术分析
安卓应用反编译技术分析随着智能手机的普及,移动设备应用程序也得到了大量关注和开发。
安卓应用程序在移动设备市场中占有重要地位。
在开发安卓应用程序的过程中,有可能存在一些安全问题。
因此,对于安卓应用反编译技术的研究也非常重要。
本文将对安卓应用反编译技术进行分析,并探讨其对安卓应用程序的安全和保护。
一、安卓应用的反编译1.1 安卓应用的工作原理安卓应用程序由多个componets组成,例如活动、服务、广播和内容提供者等。
这些组件可以单独工作,也可以相互协作完成应用程序的功能。
在安卓系统中,应用程序是在虚拟机中运行的。
Dalvik虚拟机是Google Android系统的基础。
而非Dalvik虚拟机的Java SE虚拟机已有20年历史,它们有一定的相似之处,但在代码格式和结构上有所不同。
Dalvik虚拟机采用的是一种被称为DEX(Dalvik执行文件格式)的编译格式,它可以将Java类以.dex文件的形式保存到磁盘上。
DEX文件中的类代码比Java类格式简单得多,以便在移动设备上节省存储空间和执行时间。
在运行安卓应用程序时,DEX文件会被加载到Dalvik虚拟机中,最终形成可执行代码。
1.2 安卓应用的反编译方法在理解安卓应用程序的反编译方法之前,需要先了解一些相关的基础知识。
(1)APK文件APK文件是Android Package的缩写,是安卓应用程序的一种压缩格式。
这种格式不仅包含了应用程序的代码、资源和清单文件,还包含了一些其他的文件。
APK文件可以被安装到设备上。
每个APK文件都有一个唯一的包名和应用程序ID,这些信息在清单文件中定义。
(2)Dex文件Dex文件是安卓应用程序的核心文件,它包含了Dalvik虚拟机需要的所有数据。
Dex文件是一种类似于Java class文件的二进制文件格式。
它的结构被划分为header、string table、type table、file table、class table等几个部分。
安卓逆向工程技术实践与应用
安卓逆向工程技术实践与应用随着智能手机的普及和应用程序的繁荣发展,安卓逆向工程技术的重要性与日俱增。
本文将探讨安卓逆向工程技术的实践与应用,旨在为读者提供一些关键的知识和技巧,帮助其更好地理解和使用该技术。
第一部分:安卓逆向工程技术概述与原理安卓逆向工程技术是指对安卓应用程序进行调试、破解、修改等操作的过程。
它可以帮助开发者了解应用程序的底层工作原理,发现潜在的安全漏洞,实现定制化和二次开发等功能。
在实践中,安卓逆向工程技术主要基于以下原理:反编译和逆向分析。
1. 反编译:通过将安卓应用程序的APK文件进行反编译,可以获得其中的源代码和资源文件。
这一过程可以借助一些开源的反编译工具,如dex2jar、apktool等。
通过反编译,我们可以深入了解应用程序的结构、功能以及底层实现,为后续的逆向分析提供必要的基础。
2. 逆向分析:逆向分析是指通过分析应用程序的反编译代码和相关文件,以及运行时调试信息,从而还原其原本的逻辑和算法过程。
逆向分析的方法和工具很多,包括静态分析、动态调试和运行时反编译等。
通过逆向分析,我们可以深入理解应用程序的工作机制,发现潜在的漏洞和隐患,并进行一些修改和优化。
第二部分:安卓逆向工程技术的应用场景安卓逆向工程技术具有广泛的应用场景,下面将介绍几个典型的实践案例。
1. 安全审计:通过对安卓应用程序的逆向分析,我们可以发现其中的安全漏洞和潜在的攻击面。
比如,在一个社交媒体应用中,我们可能会发现存在用户信息泄露的风险,或者应用程序的数据传输过程存在安全漏洞。
通过逆向工程技术,我们可以对应用程序进行安全审计,及时发现和解决潜在的安全问题。
2. 二次开发与定制化:通过对应用程序的反编译,我们可以获得其中的源代码和资源文件。
这为二次开发和定制化带来了便利。
比如,我们可以通过逆向工程技术,对游戏应用程序进行修改,实现一些额外的功能或者增加一些自定义的内容。
这对于开发者来说是一种非常有价值的技术手段。
Android安全与逆向分析
Android安全与逆向分析随着科技的不断发展,移动设备已经成为人们生活中不可或缺的一部分。
而Android作为目前最流行的移动操作系统之一,其安全性问题也备受关注。
为了保护用户的隐私和数据安全,以及防止恶意攻击者利用漏洞进行攻击,Android安全与逆向分析变得至关重要。
一、安卓的安全性挑战由于Android系统的开放性和大量的第三方应用程序,使得安卓系统面临着众多的安全挑战。
其中,恶意代码、权限滥用、信息泄露、应用反编译等问题是最令人担忧的。
首先,恶意代码是Android安全的一个主要问题。
恶意应用可能会偷取用户的个人信息、发送短信、拨打电话等恶意行为,严重影响用户的隐私和金融安全。
其次,权限滥用是另一个重要的安全问题。
某些应用程序可能会请求过多的权限,并将其滥用来收集用户的敏感信息,如通讯录、短信等。
此外,信息泄露也是一个令人担忧的问题。
一些应用程序可能会在未经用户许可的情况下,将用户的个人信息上传至互联网。
最后,应用的反编译也是Android安全面临的挑战之一。
通过逆向分析,攻击者可以获得应用程序的源代码和算法,从而发现其中的漏洞并进行攻击。
二、安卓安全措施为了保护用户的隐私和数据安全,Android系统提供了一系列的安全措施。
首先,Android系统通过权限控制机制来保护用户的隐私。
在安装应用程序时,系统会提示用户应用需要的权限,并由用户决定是否授权。
用户可以根据自己的需求和信任程度合理分配权限。
其次,Android系统提供了安全更新机制。
当发现安全漏洞时,系统会发布补丁程序以修复漏洞,并及时向用户推送更新。
此外,Android系统在代码层面也加入了一些安全机制,如代码混淆和加密,以增加攻击者对应用程序的逆向分析难度。
同样值得一提的是,Google Play商店对应用进行了审查和筛选,以减少恶意应用的存在。
用户可以通过下载应用商店提供的应用,避免下载不安全的应用。
三、逆向分析的重要性逆向分析是安卓安全领域的一个重要概念。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android应用逆向分析技术综述Dex文件结构Android 程序静态分析一、Dex文件结构1. 文件头DEX文件头主要包括校验和以及其他结构的偏移地址和长度信息。
字段名称偏移值长度描述magic 0x0 8 'Magic'值,即魔数字段,格式如”dex/n035/0”,其中的035表示结构的版本。
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 标识字节顺序的常量,根据这个常量可以判断文件是否交换了字节顺序,缺省情况下=0x78563412。
link_size 0x2C 4 连接段的大小,如果为0就表示是静态连接。
link_off 0x30 4 连接段的开始位置,从本文件头开始算起。
如果连接段的大小为0,这里也是0。
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 数据段的大小,必须以4字节对齐。
data_off 0x6C 4 数据段基地址2. 魔数字段魔数字段,主要就是Dex文件的标识符,它占用4个字节,在目前的源码里是“dex\n”,它的作用主要是用来标识dex文件的,比如有一个文件也以dex为后缀名,仅此并不会被认为是Davlik虚拟机运行的文件,还要判断这四个字节。
另外Davlik虚拟机也有优化的Dex,也是通过个字段来区分的,当它是优化的Dex文件时,它的值就变成”dey\n”了。
根据这四个字节,就可以识别不同类型的Dex文件了。
3. 检验码字段主要用来检查从这个字段开始到文件结尾,这段数据是否完整,有没有人修改过,或者传送过程中是否有出错等等。
通常用来检查数据是否完整的算法,有CRC32、有SHA128等,但这里采用并不是这两类,而采用一个比较特别的算法,叫做adler32,这是在开源zlib 里常用的算法,用来检查文件是否完整性。
该算法由MarkAdler发明,其可靠程度跟CRC32差不多,不过还是弱一点点,但它有一个很好的优点,就是使用软件来计算检验码时比较CRC32要快很多。
可见Android系统,就算法上就已经为移动设备进行优化了。
4.SHA-1签名字段dex文件头里,前面已经有了面有一个4字节的检验字段码了,为什么还会有SHA-1签名字段呢?不是重复了吗?可是仔细考虑一下,这样设计自有道理。
因为dex文件一般都不是很小,简单的应用程序都有几十K,这么多数据使用一个4字节的检验码,重复的机率还是有的,也就是说当文件里的数据修改了,还是很有可能检验不出来的。
这时检验码就失去了作用,需要使用更加强大的检验码,这就是SHA-1。
SHA-1校验码有20个字节,比前面的检验码多了16个字节,几乎不会不同的文件计算出来的检验是一样的。
设计两个检验码的目的,就是先使用第一个检验码进行快速检查,这样可以先把简单出错的dex文件丢掉了,接着再使用第二个复杂的检验码进行复杂计算,验证文件是否完整,这样确保执行的文件完整和安全。
SHA(Secure Hash Algorithm, 安全散列算法)是美国国家安全局设计,美国国家标准与技术研究院发布的一系列密码散列函数。
SHA-1看起来和MD5算法很像,也许是Ron Rivest在SHA-1的设计中起了一定的作用。
SHA-1的内部比MD5更强,其摘要比MD5的16字节长4个字节,这个算法成功经受了密码分析专家的攻击,也因而受到密码学界的广泛推崇。
这个算法在目前网络上的签名,BT软件里就有大量使用,比如在BT里要计算是否同一个种子时,就是利用文件的签名来判断的。
同一份8G的电影从几千BT用户那里下载,也不会出现错误的数据,导致电影不播放。
5.map_off字段这个字段主要保存map开始位置,就是从文件头开始到map数据的长度,通过这个索引就可以找到map数据。
map的数据结构如下:名称大小说明size 4字节map里项的个数list 变长每一项定义为12字节,项的个数由上面项大小决定。
map数据排列结构定义如下:/**Direct-mapped "map_list".*/typedef struct DexMapList {u4 size; /* #of entries inlist */DexMapItem list[1]; /* entries */}DexMapList;每一个map项的结构定义如下:/**Direct-mapped "map_item".*/typedef struct DexMapItem {u2 type; /* type code (seekDexType* above) */u2 unused;u4 size; /* count of items ofthe indicated type */u4 offset; /* file offset tothe start of data */}DexMapItem;DexMapItem结构定义每一项的数据意义:类型、类型个数、类型开始位置。
其中的类型定义如下:/*map item type codes */enum{kDexTypeHeaderItem = 0x0000,kDexTypeStringIdItem = 0x0001,kDexTypeTypeIdItem = 0x0002,kDexTypeProtoIdItem = 0x0003,kDexTypeFieldIdItem = 0x0004,kDexTypeMethodIdItem = 0x0005,kDexTypeClassDefItem = 0x0006,kDexTypeMapList = 0x1000,kDexTypeTypeList = 0x1001,kDexTypeAnnotationSetRefList = 0x1002,kDexTypeAnnotationSetItem = 0x1003,kDexTypeClassDataItem = 0x2000,kDexTypeCodeItem = 0x2001,kDexTypeStringDataItem = 0x2002,kDexTypeDebugInfoItem = 0x2003,kDexTypeAnnotationItem = 0x2004,kDexTypeEncodedArrayItem = 0x2005,kDexTypeAnnotationsDirectoryItem = 0x2006,};从上面的类型可知,它包括了在dex文件里可能出现的所有类型。
可以看出这里的类型与文件头里定义的类型有很多是一样的,这里的类型其实就是文件头里定义的类型。
其实这个map的数据,就是头里类型的重复,完全是为了检验作用而存在的。
当Android系统加载dex文件时,如果比较文件头类型个数与map里类型不一致时,就会停止使用这个dex 文件。
6.string_ids_size/off字段这两个字段主要用来标识字符串资源。
源程序编译后,程序里用到的字符串都保存在这个数据段里,以便解释执行这个dex文件使用。
其中包括调用库函数里的类名称描述,用于输出显示的字符串等。
string_ids_size标识了有多少个字符串,string_ids_off标识字符串数据区的开始位置。
字符串的存储结构如下:/** Direct-mapped "string_id_item".*/typedef struct DexStringId {u4 stringDataOff; /* file offset to string_data_item */} DexStringId;可以看出这个数据区保存的只是字符串表的地址索引。
如果要找到字符串的实际数据,还需要通过个地址索引找到文件的相应开始位置,然后才能得到字符串数据。
每一个字符串项的索引占用4个字节,因此这个数据区的大小就为4*string_ids_size。
实际数据区中的字符串采用UTF8格式保存。
例如,如果dex文件使用16进制显示出来内容如下:063c 696e 6974 3e00 其实际数据则是”<init>\0”另外这段数据中不仅包括字符串的字符串的内容和结束标志,在最开头的位置还标明了字符串的长度。
上例中第一个字节06就是表示这个字符串有6个字符。
关于字符串的长度有两点需要注意的地方:1、关于长度的编码格式dex文件里采用了变长方式表示字符串长度。
一个字符串的长度可能是一个字节(小于256)或者4个字节(1G大小以上)。
字符串的长度大多数都是小于256个字节,因此需要使用一种编码,既可以表示一个字节的长度,也可以表示4个字节的长度,并且1个字节的长度占绝大多数。
能满足这种表示的编码方式有很多,但dex文件里采用的是uleb128方式。
leb128编码是一种变长编码,每个字节采用7位来表达原来的数据,最高位用来表示是否有后继字节。
它的编码算法如下:/** Writes a 32-bit value in unsigned ULEB128 format.* Returns the updated pointer.*/DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data){while (true) {u1 out = data & 0x7f;if (out != data) {*ptr++ = out | 0x80;data >>= 7;} else {*ptr++ = out;break;}}return ptr;}它的解码算法如下:/** Reads an unsigned LEB128 value, updating the given pointer to point* just past the end of the read value. This function tolerates* non-zero high-order bits in the fifth encoded byte.*/DEX_INLINE int readUnsignedLeb128(const u1** pStream) {const u1* ptr = *pStream;int result = *(ptr++);if (result > 0x7f) {int cur = *(ptr++);result = (result & 0x7f) | ((cur & 0x7f) << 7);if (cur > 0x7f) {cur = *(ptr++);result |= (cur & 0x7f) << 14;if (cur > 0x7f) {cur = *(ptr++);result |= (cur & 0x7f) << 21;if (cur > 0x7f) {/** Note: We don't check to see if cur is out of* range here, meaning we tolerate garbage in the* high four-order bits.*/cur = *(ptr++);result |= cur << 28;}}}}*pStream = ptr;return result;}根据上面的算法分析上面例子字符串,取得第一个字节是06,最高位为0,因此没有后继字节,那么取出这个字节里7位有效数据,就是6,也就是说这个字符串是6个字节,但不包括结束字符“\0”。