[转]Android逆向之旅---动态方式破解apk前奏篇(Eclipse动态调试smail源码)

分类:
 
 

1、前言

今天咱们开始apk破解的另一种方式:动态代码调试破解,以前其实已经在一篇文章中说到如何破解apk了:android

Android中使用静态方式破解Apk  主要采用的是静态方式,步骤也很简单,首先使用apktool来反编译apk,获得smail源码,而后分析smail代码,采用代码注入技术来跟踪代码,而后找到关键方法进行修改,进而破解,同时还可使用一些开源的hook框架,好比:Xposed和Cydia Substrate,来进行关键方法的hook。因此这里咱们能够看到咱们破解的第一步是使用apktool来进行成功的反编译,而后是须要了解smali语法,不过关于smali语法其实很简单,网上有不少教程。算法

 

2、知识概要分析

那么今天咱们就用另一种方式来破解apk:动态方式,关于动态方式其实很广义的,由于动态方式相对于静态方式来讲,难度大一点,可是他比静态方式高效点,可以针对更过的破解范围。固然动态方式不少,因此这里就分为三篇文章来说解这块:ubuntu

一、动态方式破解apk前奏篇(Eclipse动态调试smail源码)api

二、动态方式破解apk升级篇(IDA动态调试so源码)数组

三、动态方式破解apk终极篇(应对加固的apk破解方法)安全

从这三篇文章可以让咱们破解通常的apk没有任何问题,不过不能表明可以破解全部的apk,由于没有绝对的安全,也是没有绝对的破解,两方都在进步,咱们只能具体问题具体分析。好了,下面咱们就来看第一篇文章,也是今天的重点:Eclipse动态调试smali源码服务器

首先须要解释一下,这里为何说是调试smali源码,不是Java源码,由于咱们弄过反编译的人知道,使用apktool反编译apk以后,会有一个smali文件夹,这里就存放了apk对应的smali源码,关于smali源码这里不解释了,网上有介绍。微信

 

3、案例分析

由于这一篇是一个教程篇,因此不能光说,那样会很枯燥的,因此这里用一个例子来介绍一下:

咱们就用阿里2014年安全挑战赛的第一题:AliCrack_one.apk


看到这张图了,阿里还挺会制造氛围的,那么其实很简单,咱们输入密码就能够破解了,下面咱们就来看看如何获取这个密码。

第一步:使用apktool来破解apk

java -jar apktool_2.0.0rc4.jar d -d AliCraceme_1.apk -o out


这里的命令不作解释了,可是有一个参数必须带上,那就是:-d

由于这个参数表明咱们反编译获得的smali是java文件,这里说的文件是后缀名是java,若是不带这个参数的话,后缀名是smali的,可是Eclipse中是不会识别smali的,而是识别java文件的,因此这里必定要记得加上这个参数。

反编译成功以后,咱们获得了一个out目录,以下:


源码都放在smali文件夹中,咱们进入查看一下文件:


看到了,这里全是Java文件的,其实只是后缀名为java了,内容仍是smali的:


 

二、修改AndroidManifest.xml中的debug属性和在入口代码中添加waitDebug

上面咱们反编译成功了,下面咱们为了后续的调试工做,因此仍是须要作两件事:

1》修改AndroidManifest.xml中的Android:debuggable="true"


关于这个属性,咱们前面介绍run-as命令的时候,也提到了,他标识这个应用是不是debug版本,这个将会影响到这个应用是否能够被调试,因此这里必须设置成true。

2》在入口处添加waitForDebugger代码进行调试等待。

这里说的入口处,就是程序启动的地方,就是咱们通常的入口Activity,查找这个Activity的话,方法太多了,好比咱们这里直接从上面获得的AndroidManifest.xml中找到,由于入口Activity的action和category是固定的。


固然还有其余方式,好比aapt查看apk的内容方式,或者是安装apk以后用adb dumpsys activity top命令查看都是能够的。

找到入口Activity以后,咱们直接在他的onCreate方法的第一行加上waitForDebugger代码便可,找到对应的MainActivity的smali源码:

而后添加一行代码:

invoke-static {}, Landroid/os/Debug;->waitForDebugger()V

这个是smali语法的,其实对应的Java代码就是:android.os.Debug.waitForDebugger();


这里把Java语言翻译成smali语法的,不难,网上有smali的语法解析,这里不想再解释了。

 

第三步:回编译apk而且进行签名安装

java -jar apktool_2.0.0rc4.jar b -d out -o debug.apk

仍是使用apktool进行回编译


编译完成以后,将获得debug.apk文件,可是这个apk是没有签名的,因此是不能安装的,那么下面咱们须要在进行签名,这里咱们使用Android中的测试程序的签名文件和sign.jar工具进行签名:


关于签名的相关知识,能够看这篇文章:Android中的签名机制详解

java -jar .\sign\signapk.jar .\sign\testkey.x509.pem .\sign\testkey.pk8 debug.apk debug.sig.apk


签名以后,咱们就能够进行安装了。

 

第四步:在Eclipse中新建一个Java工程,导入smali源码

这里咱们新建一个Java工程,记住不是Android工程,由于咱们最后调试实际上是借助于Java的调试器,而后勾选掉Use default location选项,选择咱们的smali源码目录,也就是咱们上面反编译以后的out目录,点击完成


咱们导入源码以后的项目工程结构:


主要看MainActivity类:


 

第五步:找到关键点,而后打断点

这一步咱们看到,其实说的比较广义了,这个要具体问题具体分析了,好比这个例子中,咱们知道当咱们输入密码以后,确定要点击按钮,而后触发密码的校验过程,那么这里咱们知道找到这个button的定义的地方,而后进入他的点击事件中就能够了。这里分为三步走:

1》使用Eclipse自带的View分析工具找到Button的ResId


点击以后,须要等待一会,分析View以后的结果:


看到了,这里咱们可以看到整个当前的页面的所有布局,已经每一个控件的属性值,咱们须要找到button的resource-id

这里咱们看到定义是@+id/button这个值。

2》咱们获得这个resId以后,可否在smali工程中全局搜索这个值,就能够定位到这个button的定义的地方呢?

而后咱们看看搜到的结果:

这时候咱们实际上是在资源文件中搜到了这个id的定义,这个id值对应的是0x7F05003E。

固然除了这种方式,咱们还有一种方式能快速找到这个id对应的整型值,那就是在反编译以后的values/public.xml文件中:


这个文件颇有用的,他是真个apk中全部资源文件定义的映射内容,好比drawable/string/anim/attr/id 等这些资源文件定义的值,名字和整型值对应的地方:


这个文件很重要,是咱们在寻找突破口的重要关键,好比咱们有时候须要经过字符串内容来定位到关键点,这里就能够经过string的定义来找到对应的整型值便可。

当咱们找到了button对应的id值了以后,咱们就能够用这个id值在一次全局搜索一下,由于咱们知道,Android中编译以后的apk,在代码中用到的resId都是用一个整型值代替的,这个整型值就是在R文件中作了定义,将资源的id和一个值对应起来,而后代码里面通常使用R.id.button这样的值,在编译出apk的时候,这个值就会被替换成对应的整型值,因此在全局搜索0x7F05003E


搜索的结果以下:


看到了,这里就定位到了代码中用到的这个button,咱们进入代码看看:


在这里,看到了,使用了findViewById的方式定义Button,咱们在往下面简单分析一下smali语法,下面是给button添加一个按钮事件,这里用的是内部类MainActivity$1,咱们到这个类看看,他确定实现了OnClickListener接口,那么直接搜onClick方法:


在这里咱们就能够下个断点了,这里就是触发密码校验过程。

 

第六步:运行程序,设置远程调试工程

在第五步中,咱们找到了关键点,而后打上断点,下面咱们就来运行程序,而后在Eclipse中设置远程调试的工程

首先咱们运行程序,由于咱们加入了waitForDebug的代码,因此启动的时候会出现一个Wait debug的对话框。不过,我测试的时候,个人手机没有出现这个对话框,而是一个白屏,不过这个不影响,程序运行起来以后,咱们看看如何在Eclipse中设置远程调试工程,首先咱们找到须要调试的程序对应远程调试服务端对应的端口:


这里咱们看到有几个点:

1》在程序等待远程调试服务器的时候,前面会出现一个红色的小蜘蛛

2》在调试服务端这里咱们会看到两个端口号:8600/8700,这里须要解释一下,为何会有两个端口号呢?

首先在这里的端口号,表明的是,远程调试服务器端的端口,下面在简单来看一下,Java中的调试系统:


这里咱们看到,这里有三个角色:

111》JDB Client端(被调试的客户端),这里咱们能够认为咱们须要破解的程序就是客户端,若是一个程序能够被调试,当启动的时候,会有一个jdwp线程用来和远程调试服务端进行通讯


这里咱们看到,咱们须要破解的程序启动了JDWP线程,注意这个线程也只有当程序是debug模式下才有的,也就是AndroidManifest.xml中的debug属性值必须是true的时候,也就是一开始为何咱们要修改这个值的缘由。

222》JDWP协议(用于传输调试信息的,好比调试的行号,当前的局部变量的信息等),这个就能够说明,为何咱们在一开始的时候,反编译成java文件,由于为了Eclipse导入可以识别的Java文件,而后为何可以调试呢?由于smali文件中有代码的行号和局部变量等信息,因此能够进行调试的。

333》JDB Server端(远程调试的服务端,通常是有JVM端),就是开启一个JVM程序来监听调试端,这里就能够认为是本地的PC机,固然这里必须有端口用来监听,那么上面的8600端口就是这个做用,并且这里端口是从8600开始,后续的程序端口后都是依次加1的,好比其余调试程序:


那么有了8600端口,为何还有一个8700端口呢?他是干什么的?

其实他的做用就是远程调试端备用的基本端口,也就是说好比这里的破解程序,咱们用8600端口能够链接调试,8700也是能够的,可是其余程序,好比demo.systemapi他的8607端口能够链接调试,8700也是能够的:


因此呀,能够把8700端口想象成你们均可以用于链接调试的一个端口,不过,在实际过程当中,仍是建议使用程序独有的端口号8600,咱们能够查看8600和8700端口在远程调试端(本地pc机)的占用状况:


看到了,这里的8600端口和8700端口号都是对应的javaw程序,其实javaw程序就是启动一个JVM来进行监听的。

好了,到这里咱们就弄清楚了,Java中的调试系统以及远程调试的端口号。

注意:

其实咱们可使用adb jdwp命令查看,当前设备中能够被调试的程序的进程号信息:


 

下面继续,咱们知道了远程调试服务端的端口:8600,以及ip地址,这里就是本地ip:localhost/127.0.0.1

咱们能够在Eclipse中新建一个远程调试项目,将咱们的smali源码工程和设备中须要调试的程序关联起来:

右击被调试的项目=》选择Debug Configurations:


而后开始设置调试项目


选择Romote Java Application,在Project中选择被调试的smali项目,在Connection Type中选择SocketAttach方式,其实还有一种方式是Listener的,关于这两种方式其实很好理解:

Listner方式:是调试客户端启动就准备好一个端口,当调试服务端准备好了,就链接这个端口进行调试

Attach方式:是调试服务端开始就启动一个端口,等待调试端来链接这个端口


咱们通常都是选择Attach方式来进行操做的。

好了,咱们设置完远程调试的工程以后,开始运行,擦发现,设备上的程序仍是白屏,这是为何呢?看看DDMS中调试程序的状态:


擦,关联到了这个进程,缘由也很简单,咱们是上面使用的是8700端口号,这时候咱们选中了这个进程,因此就把smali调试工程关联到了这个进程,因此破解的进程没反应了,咱们立马改一下,用8600端口:


好了,这下成功了,咱们看到红色的小蜘蛛变成绿色的了,说明调试端已经链接上远程调试服务端了。

注意:

咱们在设置远程调试项目的时候,必定要注意端口号的设置,否则没有将调试项目源码和调试程序关联起来,是没有任何效果的

 

第七步:开始运行调试程序,进入调试

下面咱们就开始操做了,在程序的文本框中输入:gggg内容,点击开始:


好了,到这里咱们看到期待已久的调试界面出来了,到了咱们开始的时候加的断点处,这时候咱们就能够开始调试了,使用F6单步调试,F5单步跳入,F7单步跳出进行操做:


看到了,这里使用v3变量保存了咱们输入的内容


这里有一个关键的地方,就是调用MainActivity的getTableFromPic方法,获取一个String字符串,从变量的值来看,貌似不是规则的字符串内容,这里先不用管了,继续往下走:


这里又遇到一个重要的方法:getPwdFromPic,从字面意义上看,应该是获取正确的密码,用于后面的密码字符串比对。


查看一下密码的内容,貌似也是一个不规则的字符串,可是咱们能够看到和上面获取的table字符串内容格式很像,接着往下走:


这里还有一个信息就是,调用了系统的Log打印,log的tag就是v6保存的值:lil


这时候,咱们看到v3是保存的咱们输入的密码内容,这里使用utf-8获取他的字节数组,而后传递给access$0方法,咱们使用F5进入这个方法:


在这个方法中,还有一个bytesToAliSmsCode方法,使用F5进入:


那么这个方法其实看上去仍是很简单的,就是把传递进来的字节数组,循环遍历,取出字节值,而后转化成int类型,而后在调用上面获取到的table字符串的chatAt来获取指定的字符,使用StringBuilder进行拼接,而后返回便可。

按F7跳出,查看,咱们返回来加密的内容是:日日日日,也就是说gggg=>日日日日


最后再往下走,能够看到是进行代码比对的工做了。

 

那么上面咱们就分析完了全部的代码逻辑,还不算复杂,咱们来梳理一下流程:

A>调用MainActivity中的getTableFromPic方法,获取一个table字符串

咱们能够进入看看这个方法的实现:


这里能够大致了解了,他是读取asset目录下的一个logo.png图片,而后获取图片的字节码,在进行操做,获得一个字符串,那么咱们从上面的分析能够知道,其实这里的table字符串相似于一个密钥库。

B>经过MainActivity中的getPwdFromPic方法,获取正确的密码内容

C>获取咱们输入内容的utf-8的字节码,而后调用access$0方法,获取加密以后的内容

D>access$0方法中在调用bytesToAliSmsCode方法,获取加密以后的内容

这个方法是最核心的,咱们经过分析知道,他的逻辑是,经过传递进来的字节数组,循环遍历数组,拿到字节转化成int类型,而后在调用密钥库字符串table的charAt获得字符,使用StringBuilder进行拼接。

经过上面的分析以后,咱们知道获取加密以后的输入内容和正确的密码内容作比较,那么咱们如今有的资源是:

密钥库字符串和正确的加密以后的密码,以及加密的逻辑

那么咱们的破解思路其实很简单了,至关于,咱们知道了密钥库字符串,也知道了,加密以后的字符组成的字符串,那么能够经过遍历加密以后的字符串,循环遍历,获取字符,而后再去密钥库找到指定的index,而后在转成byte,保存到字节数组,而后用utf-8获取一个字符串,那么这个字符串就是咱们要的密码。

下面咱们就用代码来实现这个功能:


代码逻辑,很简单吧,其实这个函数至关于上面加密函数的bytesToAliSmsCode的反向实现,运行结果:


OK,获得了正确的密码,下面来验证一下:


哈哈,不要太激动,成功啦啦~~。破解成功。

 

补充:

刚刚咱们在断点调试的时候,看到了代码中用了Log来打印日志,tag是lil,那么咱们能够打印这个log看看结果:


看到了,这里table是密钥库,pw是正确的加密以后的密码,enPassword是咱们输入以后加密的密码。

因此从这里能够看到,这个例子,其实咱们在破解apk的时候,有时候日志也是一个很是重要的信息。

 

破解须要的资料,我已经上传了,下载地址:http://download.csdn.net/detail/jiangwei0910410003/9526113

 

4、思路整理

一、咱们经过apktool工具进行apk的反编译,获得smali源码和AndroidManifest.xml,而后修改AndroidManifest.xml中的debug属性为true,同时在入口处加上waitForDebug代码,进行debug等待,通常入口都是先找到入口Activity,而后在onCreate方法中的第一行这里须要注意的是,apktool工具必定要加上-d参数,这样反编译获得的文件是java文件,这样才可以被Eclipse识别,进行调试

二、修改完成AndroidManifest.xml和添加waitForDebug以后,咱们须要在使用apktool进行回编译,回编译以后获得的是一个没有签名的apk,咱们还须要使用signapk.jar来进行签名,签名文件直接使用测试程序的签名文件就能够,最后在进行安装。

三、而后咱们将反编译以后的smali源码导入到Eclipse工程中,找到关键点,进行下断点,这里的关键点,通常是咱们先大体了解程序运行的结构,而后找到咱们须要破解的地方,使用View分析工具,或者是使用jd-gui工具直接查看apk源码(使用dex2jar将dex文件转化成jar文件,而后用jd-gui进行查看),找到代码的大致位置。而后下断点,这里咱们能够借助Eclipse的DDMS自带的View分析工具找到对应控件的resid,而后在全局搜索这个控件的resid,或者直接在values/public.xml中查找,最终定位到这个控件位置,在查看他的点击事件便可。

四、设置远程调试工程,首先运行须要调试程序,而后在DDMS中找到对应的调试服务端的端口号,而后在Debug Configurations中设置远程调试项目,设置对应的调试端口和ip地址(通常都是本机pc,那就是localhost),而后红色小蜘蛛变成绿色的,表示咱们的远程调试项目链接关联上了调试程序,这里须要注意的是,必定须要关联正确,否则是没有任何效果的,关联成功以后,就能够进行操做。

五、操做的过程当中,会进入到关键的断点处,经过F6单步,F5单步进入,F7单步跳出,来进行调试,找到关键方法,而后经过分析smali语法,了解逻辑,若是逻辑复杂的,能够经过查看具体的环境变量的值来观察,这里也是最重要的,也是最复杂的,同时这里也是没有规章可寻的,这个和每一个人的逻辑思惟以及破解能力有关系,分析关键的加密方法是须要功底的,固然这里还须要注意一个信息,就是Log日志,有时候也是很重要的一个信息。

六、最后通常当咱们知道了核心方法的逻辑,要想获得正确的密码,仍是须要本身用语言去实现逻辑的,好比本文中的加密方法,咱们须要手动的code一下加密的逆向方法,才能获得正确的密码。

 

5、遗留问题

一、使用apktool工具进行反编译有时候并非那么顺利,好比像这样的报错:


这个通常都是apktool中解析出现了错误,其实这个都是如今apk为了抵抗apktool,作的apk加固策略,这个后面会写一篇文章如何应对这些加固策略,如何进行apk修复,其实原理就是分析apktool源码,找到指定的报错位置,进行apktool代码修复便可。

二、本文中说到了Java的调试系统,可是为了篇幅限制,没有详细的讲解了整个内容,后面会写一篇文章具体介绍Java中的调试系统以及Android的调试系统。

三、有时候咱们还会遇到回编译成功了,而后遇到运行不起来的错误,这个就须要使用静态方式先去分析程序启动的逻辑,看看是否是程序作了什么运行限制,好比咱们在静态分析那篇文章中,提到了应用为了防止反编译在回编译运行,在程序的入口处做了签名校验,若是校验失败,直接kill掉本身的进程,退出程序了,因此这时候咱们仍是须要使用静态方式去分析apk。

四、如何作到不修改AndroidManifest.xml中的debug属性就能够进行调试:

1》 修改boot.img,从而打开系统调试,这样就能够省去给app添加android:debuggable="true",再重打包的步骤了。
2.》直接修改系统属性,使用setpropex工具在已经root的设备上修改只读的系统属性。使用此工具来修改ro.secure和ro.debuggable的值。

这个也会在后面详细介绍这两种方法

 

6、总结

这篇文章咱们就介绍了如何使用Eclipse去动态调试反编译以后的smali源码,这种方式比静态方式高效不少的,好比本文中的这个例子,其实咱们也可使用静态方式进行破解的,可是确定效率没有动态方式高效,因此之后咱们又学会了一个技能,就是动态的调试smali源码来跟踪程序的核心点,可是如今市场上的大部分应用没有这么简单就破解了,好比核心的加密算法放到了native层去作,那么这时候就须要咱们去动态调试so文件跟踪,这个是咱们下一篇文章的内容,也有的时候,apk进行加固了,直接在apktool进行反编译就失败了,这时候咱们就须要先进行apk修复,而后才能后续的操做,这个是咱们下下篇的文章,如何应对apk的加固策略。经过这篇文章咱们能够看到动态方式破解比静态方式高效的多,可是有时候咱们还须要使用静态方式先作一些准备工做,因此在破解apk的时候,动静结合,才能作到完美的破解。

 

 

更多内容:点击这里

 

关注微信公众号,最新Android技术实时推送

 


 

 

 

 
9
0
 
 
 

 

 
猜你在找
【直播】机器学习&深度学习系统实战(唐宇迪)
【直播】Kaggle 神器:XGBoost 从基础到实战(冒教授)
【直播回放】深度学习基础与TensorFlow实践(王琛)
【直播】计算机视觉原理及实战(屈教授)
【直播】机器学习之凸优化(马博士)
【直播】机器学习之矩阵(黄博士)
【直播】机器学习之几率与统计推断(冒教授)
【直播】机器学习之数学基础
【直播】TensorFlow实战进阶(智亮)
【直播】深度学习30天系统实训(唐宇迪)

 

 

查看评论
4楼 code_xzh 2016-05-23 17:30发表 [回复]
楼主来一篇用studio的,毕竟eclipse如今都淘汰了
Re: yuwumo4341 2016-06-02 18:26发表 [回复]
回复code_xzh:仍是eclipse间接实用
3楼 starrywz 2016-05-21 18:17发表 [回复]
在Eclipse中设置远程调试的工程----请问具体是怎么操做的
2楼 qq402335257 2016-05-21 09:33发表 [回复]
膜拜
1楼 Dream_boy_94 2016-05-20 17:39发表 [回复]
厉害
 
该文章已被禁止评论!
* 以上用户言论只表明其我的观点,不表明CSDN网站的观点或立场
 
 
TOP
相关文章
相关标签/搜索