安卓移动逆向入门教程第三课
- 格式:pdf
- 大小:458.69 KB
- 文档页数:11
1Android分析工具1.1分析工具经过试验,推荐的工具为:模拟器可以使用逍遥安卓;反编译,编译,smali代码注入,APK签名等等可以使用Android Killer;开发IDE可以使用Android Studio;一般的反编译和运行APK可以使用Android Killer + 逍遥安卓,注意连接逍遥安卓模拟器的方法是使用adb connect 127.0.0.1:21503,最好使用逍遥自带的adb工具。
1.APKtoola)直接编译和反编译APK文件;b)到smali语言级别;c)可以解析二进制的AndroidManifest.xml文件2.APKStudio图形界面的apktool;3.APK IDE小米出的apk反编译,打包集成工具,类似ApkStudio;集成了jd-gui,dex2jar等;4.android Killer集成了apktool,dex2jar, jd-gui等工具,同时支持搜索,类方法提取,代码插入等工具;同时支持动态连接android devices,自动编译,签名,安装,运行程序等操作。
易用性上,这几类工具的排名是:AndroidKiller> APK IDE >APKStudio>APKTool.5.JEB反编译工具,商业的,效果据说比开源的要好;6.Dex2jar可以直接把classes.dex转换成Jar包,内部是把Dalvik字节码转换成了Java字节码;7.enjarifygoogle自己出的工具,把dhttps:///google/enjarify/8.jad把某个.class文件转换成源码形式,本质是把Java字节码转换成java源码;9.jd-gui本质上和jad一样,但是是图形界面的,并且可以批量反编译整个Jar包文件;10.androguard包含了许多工具,可以对某个APK文件进行测绘,比如权限信息,函数调用图,指令级别的函数调用图,交互分析环境;11.IDEa)Eclipseb)AndroidStudioc)IDEA12.JDBa)JDK自带的调试JAVA程序的调试器,可以用来调试APK;13.IDA14.Mercury,现在改名叫Drozera)是一个渗透测试工具;15.Androguarda)一堆python脚本工具;b)有一个可以生成函数调用图;1.2分析平台系统1.2.1Santoku本质是一款Ubuntu Linux系统,上面集成了各种Android工具,包括开发,逆向,渗透测试,恶意代码分析等各个安全方向。
android 逆向中常用的arm汇编指令基础知识在Android 逆向工程中,了解ARM 汇编指令的基础知识对于理解和分析应用程序的底层行为至关重要。
以下是一些常用的ARM 汇编指令及其简要说明:数据移动指令:MOV:将源操作数的值复制到目标寄存器。
STR:将寄存器的值存储到内存中。
LDR:从内存中加载值到寄存器。
算术指令:ADD:加法。
SUB:减法。
MUL:乘法。
DIV:除法。
AND:位与。
ORR:位或。
XOR:位异或。
NOT:位非。
比较指令:CMP:比较两个值,并根据结果设置条件标志。
TST:测试寄存器的位,并根据结果设置条件标志。
条件分支指令:B:无条件分支。
BEQ:当相等时分支。
BNE:当不相等时分支。
BGT:当大于时分支。
BLT:当小于时分支。
BGE:当大于或等于时分支。
BLE:当小于或等于时分支。
堆栈操作指令:PUSH:将寄存器值压入堆栈。
POP:从堆栈中弹出值到寄存器。
加载/存储指令:LDM:从内存加载多个寄存器。
STM:将多个寄存器存储到内存。
交换指令:SWP:交换寄存器的值与内存中的值。
程序控制指令:BL:带返回的分支。
BX:跳转到寄存器指定的地址。
了解这些指令可以帮助你在逆向工程中识别和分析关键代码段,例如函数入口、出口、条件跳转等。
此外,对于某些特定的逆向工程技术,如hooking、代码注入等,对ARM 汇编的深入理解也是必不可少的。
请注意,ARM 架构有多个版本(如ARMv7、ARMv8 等),不同版本可能具有不同的指令集和特性。
因此,在具体的应用中,你可能需要参考特定版本的ARM 架构文档来获取更详细和准确的信息。
安卓逆向(⼀)--Smali基础安卓逆向(⼀)--Smali基础标签(空格分隔):安卓逆向APK的组成⽂件夹作⽤asset⽂件夹资源⽬录1:asset和res都是资源⽬录但有所区别,见下⾯说明lib⽂件夹so库存放位置,⼀般由NDK编译得到,常见于使⽤游戏引擎或JNI native调⽤的⼯程中META-INF⽂件夹存放⼯程⼀些属性⽂件,例如Manifest.MFres⽂件夹资源⽬录2:asset和res都是资源⽬录但有所区别,见下⾯说明AndroidManifest.xml Android⼯程的基础配置属性⽂件classes.dex Java代码编译得到的DalvikVM能直接执⾏的⽂件,下⾯有介绍resources.arsc对res⽬录下的资源的⼀个索引⽂件,保存了原⼯程中strings.xml等⽂件内容其他⽂件夹etc.asset资源⽬录和res资源⽬录的不同之处:res⽬录下的资源⽂件在编译时会⾃动⽣成索引⽂件(R.java),在Java代码中⽤R.xxx.yyy来引⽤;⽽asset⽬录下的资源⽂件不需要⽣成索引,在Java代码中需要⽤AssetManager来访问;⼀般来说,除了⾳频和视频资源(需要放在raw或asset下),使⽤Java开发的Android⼯程使⽤到的资源⽂件都会放在res下;使⽤C++游戏引擎(或使⽤Lua Unity3D等)的资源⽂件均需要放在asset下。
其中在Davlik字节码中,寄存器都是32位的,能够⽀持任何类型,64位类型(Long/Double)⽤2个寄存器表⽰;Dalvik字节码有两种类型:原始类型;引⽤类型(包括对象和数组)原始类型:B---byteC---charD---doubleF---floatI---intJ---longS---shortV---voidZ---boolean[XXX---arrayLxxx/yyy---object数组的表⽰⽅式是:在基本类型前加上前中括号“[”,例如int数组和float数组分别表⽰为:[I、[F;对象的表⽰则以L作为开头,格式是LpackageName/objectName;(注意必须有个分号跟在最后),例如String对象在smali中为:Ljava/lang/String;,其中java/lang对应ng包,String就是定义在该包中的⼀个对象。
安卓逆向3:逆向练习,通过修改smali⽂件,破解签名校验####shuqi.apkmumu模拟器###正常的shuqi.apk,是在模拟器可以正常运⾏的,###⾸先第⼀步使⽤apktool.sh d shuqi.apk反编译出来这个apk,###然后再次打包这个apk,使⽤命令,apktool.sh b shuqi会在产⽣⼀个dist⽂件夹,⾥⾯有⼀个shuqi.apk####进⼊这个dist⽂件夹,cd 进⼊,开始⽣成签名,使⽤命令:keytool -genkey -keystore my-release-key.keystore -alias my_alias -keyalg RSA -keysize 4096 -validity 10000输⼊密码123456签名就⽣成了###使⽤⽣成的签名⽂件,对apk进⾏签名,使⽤命令:jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore -signedjar shuqi_sign.apk shuqi.apkmy_alias会⽣成⼀个签名的apk####在模拟器再次安装这个apk发现安装失败了,分析第⼀步,因为你启动的时候就退出了,所以应该是在启动的某⼀个阶段,做了签名的校验,所以你要找到是在启动的哪⼀个阶段做的校验,因为app启动是会去读取,Androidmanifest.xml的,⼀个apk只有⼀个这个⽂件,⾥⾯有⼀个,application,这个加载完,app的⽣命周期就启动了,所以应该是还没有加载完这个application,就退出了,第⼆步,所以我们去找application,找到的地⽅,这个就是app启动的⼊⼝,⼤概率是会在这个启动的⼊⼝⽂件⾥,做⼀些事情,然后校验了签名的,我们要做的就是找到这个校验签名的地⽅,这个地⽅的⽂件是不会混淆的,因为混淆了app就找不到了,###这个就是对签名进⾏了校验,开发签名了之后是记录到代码⾥⾯的,每次app启动,会读取这个签名,如果不对就会有问题,我们下⼀步要找到这个签名的地⽅在哪⾥,###使⽤jadx打开shuqi.apk是启动的时候就退出了,可以猜测是启动的时候做了校验,找到启动application页⾯,找到书旗的application,可以通过右键的⽅式,找到这个函数的具体位置,我们猜测是做了校验,就要重点关注if,check,verify,这样的词,就是这个地⽅做了校验了,我们要做的就是把这⼀句注释掉,然后重新打包,###我们找到对应的路径,修改smali⽂件,把对应的四⾏删除,然后再去打包,###重新签名,打包,注意把之前⽣成的build和dist删除掉,⾸先重新打包使⽤命令,apktool.sh b shuqi会在产⽣⼀个dist⽂件夹,⾥⾯有⼀个shuqi.apk####进⼊这个dist⽂件夹,cd 进⼊,开始⽣成签名,使⽤命令:输⼊密码123456签名就⽣成了###使⽤⽣成的签名⽂件,对apk进⾏签名,使⽤命令:jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore -signedjar shuqi_sign.apk shuqi.apk my_alias会⽣成⼀个签名的apk###再次安装这个签名之后的apk,哈哈,就可以正常安装了,绕过了他的签名校验####为什么能够绕过这个签名,本质还是对安卓系统,对app加载流程有⼀个深刻的认识啊!#####。
此篇整理了最完整的--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内的代码,并对比源码分析。
⾮常详细的androidso库逆向调试教程⽬录前⾔应⽤环境准备创建默认的native application修改stringFromJNI⽅法,便于调试修改androidManifest⽂件修改CMakeLists.txt编译运⾏,获取sohook环境准备使⽤ida pro进⾏hookadb与⼿机的准备ida pro的⼯作准备使⽤ida pro进⾏调试进⾏调试结束前⾔好久没有写博客了,最近的精⼒全放在逆向上⾯。
⽬前也只是略懂⽪⽑。
android java层的逆向⽐较简单,主要就是脱壳、反编译源码,通过xposed进⾏hook。
接下来介绍⼀下,如何去调试hook native层的源码,也就是hook so⽂件。
应⽤环境准备⾸先,为了⽅便学习,⼀上来就hook第三⽅app难度极⼤,因此我们⾃⼰来创建⼀个native的项⽬,⾃⼰来hook⾃⼰的项⽬作为学习的练⼿点。
创建默认的native application打开as,选择File -> new project -> naive c++ 创建包含c++的原⽣⼯程。
默认的native⼯程,帮我们实现了stringFromJNI⽅法,那我们就来探索如何hook这个stringFromJNI,并修改他的值。
修改stringFromJNI⽅法,便于调试as默认实现的stringFromJNI只有在Activity onCreate的时候调⽤,为了便于调试,我们增加⼀个点击事件,每次点击重新调⽤,并且返回⼀个随机的值。
java代码增加如下⽅法:binding.sampleText.setOnClickListener {Log.e("MainActivity", "stringFromJNI")binding.sampleText.text = stringFromJNI()}修改native-lib.cpp代码:#include <jni.h>#include <string>using namespace std;int max1(int num1, int num2);#define random(x) rand()%(x)extern "C" JNIEXPORT jstring JNICALLJava_com_noober_naticeapplication_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {int result = max1(random(100), random(100));string hello = "Hello from C++";string hello2 = hello.append(to_string(result));return env->NewStringUTF(hello2.c_str());}int max1(int num1, int num2){// 局部变量声明int result;if (num1 > num2)result = num1;elseresult = num2;return result;}修改的代码很简单,相信不会 c++ 的同学也看得懂,就是随机输⼊两个数,取其中⼩的那⼀位拼接在“Hello from C++”后⾯,并返回。
安卓逆向工程技术实践与应用随着智能手机的普及和应用程序的繁荣发展,安卓逆向工程技术的重要性与日俱增。
本文将探讨安卓逆向工程技术的实践与应用,旨在为读者提供一些关键的知识和技巧,帮助其更好地理解和使用该技术。
第一部分:安卓逆向工程技术概述与原理安卓逆向工程技术是指对安卓应用程序进行调试、破解、修改等操作的过程。
它可以帮助开发者了解应用程序的底层工作原理,发现潜在的安全漏洞,实现定制化和二次开发等功能。
在实践中,安卓逆向工程技术主要基于以下原理:反编译和逆向分析。
1. 反编译:通过将安卓应用程序的APK文件进行反编译,可以获得其中的源代码和资源文件。
这一过程可以借助一些开源的反编译工具,如dex2jar、apktool等。
通过反编译,我们可以深入了解应用程序的结构、功能以及底层实现,为后续的逆向分析提供必要的基础。
2. 逆向分析:逆向分析是指通过分析应用程序的反编译代码和相关文件,以及运行时调试信息,从而还原其原本的逻辑和算法过程。
逆向分析的方法和工具很多,包括静态分析、动态调试和运行时反编译等。
通过逆向分析,我们可以深入理解应用程序的工作机制,发现潜在的漏洞和隐患,并进行一些修改和优化。
第二部分:安卓逆向工程技术的应用场景安卓逆向工程技术具有广泛的应用场景,下面将介绍几个典型的实践案例。
1. 安全审计:通过对安卓应用程序的逆向分析,我们可以发现其中的安全漏洞和潜在的攻击面。
比如,在一个社交媒体应用中,我们可能会发现存在用户信息泄露的风险,或者应用程序的数据传输过程存在安全漏洞。
通过逆向工程技术,我们可以对应用程序进行安全审计,及时发现和解决潜在的安全问题。
2. 二次开发与定制化:通过对应用程序的反编译,我们可以获得其中的源代码和资源文件。
这为二次开发和定制化带来了便利。
比如,我们可以通过逆向工程技术,对游戏应用程序进行修改,实现一些额外的功能或者增加一些自定义的内容。
这对于开发者来说是一种非常有价值的技术手段。
Android动态逆向分析工具——Andbug之基本操作一、Andbug的基本操作1、下载andbug修改版本:git clone https:///anbc/AndBug.git 作者原版本:git clone https:///swdunlop/AndBug2、对andbug的部分模块进行编译在Andbug文件夹中使用make命令进行编译3、对文件路径进行设置在Andbug文件夹中的andbug文件中,以下修改,修改sys.path.append(“”)中的路径,比如作者将Andbug下载到了“/home/anbc/test/test/Andbug/”路径中,将sys.path.append(“/home/anbc/test/test/Andbug/lib”)[4、启动虚拟机emulator -avd Android_35、查看当前的进行信息可以看到浏览器应用的进程id是920,包名是:com.android.browser6、启动andbug./andbug shell -p com.android.browserAndbug 有两种启动方式,一种是以进程id方式启动,一种是以包名方式启动通过进程id或者包名指定对某个apk进行调试。
如图:以包名方式启动,进入andbug的shell中7、列举apk中的类信息命令:classes作用:列举出指定apk中使用的所有的Class信息,包括apk中自己实现的Class以及所调用的系统class 信息另外classes命令后边可以跟Class名称的信息,通过添加名称信息,可以列举出符合条件的class的信息。
如:classes app如图,列举出所有类路径中包含了app字符串的类信息8、列举指定类的方法信息命令:methods android.app.NotificationManager功能:列举出android.app.NotificationManager类中的所有方法信息其中以 android.app.NotificationManager.from(Landroid/content/Context;)Landroid/ap p/NotificationManager; 为例。
安卓移动逆向入门教程(三)
-------深入Smali文件
Smali中的包信息
•.class public Lcom/aaaaa;
•.super Lcom/bbbbb;
•.source "ccccc.java"
•这是一个由ccccc.java编译得到的smali文件(第3行)•它是com.aaaaa这个package下的一个类(第1行)
•继承自com.bbbbb这个类(第2行)
Smali中的声明
一般来说在Smali文件中是这个样子的:
•# annotations
•.annotation system Ldalvik/annotation/MemberClasses;
value = {
Lcom/aaa$qqq;,
Lcom/aaa$www;
}
.end annotation
•这个声明是内部类的声明:aaa这个类它有两个成员内部类——qqq和www,内部类将在后面小节中会有提及。
关于寄存器的知识补充
•寄存器是什么意思呢?在smali里的所有操作都必须经过寄存器来
进行:本地寄存器用v开头数字结尾的符号来表示,如v0、v1、
v2、...参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2、...特别注意的是,p0不一定是函数中的第一个参数,在非
static函数中,p0代指“this”,p1表示函数的第一个参数,p2代
表函数中的第二个参数…而在static函数中p0才对应第一个参数
(因为Java的static方法中没有this方法。
寄存器简单实例分析:
•const/4 v0, 0x1
•iput-boolean v0, p0, Lcom/aaa;->IsRegistered:Z
•我们来分析一下上面的两句smali代码,首先它使用了v0本地寄存器,并把值0x1存到v0中,然后第二句用iput-boolean这个指令把v0中的值存放到com.aaa.IsRegistered这个成员变量中。
•即相当于:this.IsRegistered= true;(上面说过,在非static函数中p0代表的是“this”,在这里就是com.aaa实例)。
smali中的成员变量
•成员变量格式是:
•.field public/private [static] [final] varName:<类型>。
•对于不同的成员变量也有不同的指令。
•一般来说,获取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等。
•操作的指令有:iput、sput、iput-boolean、sput-boolean、iput-
object、sput-object等。
•没有“-object”后缀的表示操作的成员变量对象是基本数据类型,带“-object”表示操作的成员变量是对象类型,特别地,boolean
类型则使用带“-boolean”的指令操作。
•sget-object v0, Lcom/aaa;->ID:Ljava/lang/String;
•sget-object就是用来获取变量值并保存到紧接着的参数的寄存器中,本例中,它获取ID这个String类型的成员变量并放到v0这个寄存器中。
•注意:前面需要该变量所属的类的类型,后面需要加一个冒号和
该成员变量的类型,中间是“->”表示所属关系。
•iget-object v0, p0, Lcom/aaa;->view:Lcom/aaa/view;
•可以看到iget-object指令比sget-object多了一个参数,就是该变量所在类的实例,在这里就是p0即“this”。
•获取array的话我们用aget和aget-object,指令使用和上述一致
•put指令的使用和get指令是统一的如下:
•const/4 v3, 0x0
•sput-object v3, Lcom/aaa;->timer:Lcom/aaa/timer;
•相当于:this.timer= null;
•注意,这里因为是赋值object 所以是null,若是boolean的话,大家想应该相当于什么呢?
•.local v0, args:Landroid/os/Message;
•const/4 v1, 0x12
•iput v1, v0, Landroid/os/Message;->what:I
•相当于:args.what = 18;(args是Message的实例)
那第三课教程到这里就全部结束了,本节课理论知识也是较多,目的是为了让大家熟悉指令。
当然也需要课后自己多加练习,多多消化,不过,对于聪明的你来说是不是还是很简单?
所谓授人以鱼不如授人以渔,逆向之路也是一条艰苦的道路,只有不断的学习和努力才能一步步的提升自己,切忌一步登天。
那在下面一篇教程出来之前,大家不妨先去动手试试破解一下一些早期的Crackme,因为下节课我们要讲Smali函数调用以及常用结构smali分析。
谢谢观看。