一、前言

从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,Android中的破解其实大体上可以分为静态分析和动态分析,对于这两种方式又可以细分为Java层(smail和dex)和native层(so)。所以我们今天主要来讲解如何通过静态分析来破解我们的apk,这篇文章我们会通过破解Java层和native层的例子来讲解。

二、准备工作

在开始今天的文章之前,我们需要准备点东西,

第一、首先是基本知识:

1、了解Android中的Apk文件的结构。

2、了解Smail语法和dex文件格式

3、apk的签名机制

关于这三个知识点,这里就不做详细介绍了,不理解的同学可以自行网上学习,有很多资料讲解的。

第二、再者就是几个重要的工具

1、apktool:反编译的利器

2、dex2jar:将dex转化成jar

3、jd-gui:很好的查看jar文件的工具

4、IDA:收费的最全破解利器(分析dex和so都可以)

下载地址:http://pan.baidu.com/s/1hqBC7Es

额外:上面四个工具是最基本的,但是现在网上也有一些更好的工具:JEB,GDA等。但是这些工具就是丰富了上面四个工具,所以说我们只要上面的四个工具就足够了。IDA工具我专门给了一个下载地址,其他的工具在我们提供的案例中。

三、技术原理

准备工作完了,下面就来看一下今天的破解方式介绍:

Android中的破解的静态分析说重要,也不重要,为什么这么说呢?

因为我们到后面会介绍动态分析,那时候我们在破解一个Apk的时候,发现静态分析的方式几乎毫无用途,因为现在的程序加固的越来越高级,静态分析几乎失效,所以动态分析是必须的,但是要是说静态分析没有用,那么也错了,因为我们在有些场景下,只有静态分析能够开始破解之门,没有静态分析之后的结果,动态分析是无法开展的。这个下面会举例说明。所以说在破解的过程中,静态分析和动态分析一定会结合在一起的,只有这样我们才会勇往直前。下面就来看看我们如何通过静态分析来破解apk.

第一、静态分析的流程

1、使用apktool来反编译apk

在这个过程中,我们会发现有些apk很轻易的被反编译了,但是有些apk每次反编译都会报各种错误,这个也是正常的,因为加固了吗。现在网上有很多对apk加密的方式,直接让反编译就通不过,比如Androidmanifest文件,dex文件等,因为apktool他需要解析这些重要的资源,一旦这些文件加密了那么就会终止,所以这里我们暂且都认为apk都能反编译的,因为我们今天是主要介绍怎么通过静态分析来破解,关于这里的反编译失败的问题,我后面会在用一篇文章详细介绍,到时候会列举一些反编译错误的例子。

2、得到程序的smail源码和AndroidManifest.xml文件

我们知道一个Android的程序入口信息都会在AndroidManifest.xml中,比如Application和入口Activity,所以我们肯定会先来分析这个文件,找到我们想要的信息,当然这里还有一个常用的命令需要记住:

adb shell dumpsys activity top

能够获取到当前程序的Activity信息

然后我们会分析smail代码,进行代码逻辑的修改

3、直接解压apk文件得到classes.dex文件,然后用dex2jar工具得到jar,用jd-gui工具查看

这里我们主要很容易的查看代码,因为我们在第二步中得到了smail源码,就可以分析程序了,但是我们知道虽然smail语法不是很复杂,至少比汇编简单,但是怎么看着都是不方便的,还是看java代码比较方便,所以我们借助jd-gui工具查看代码逻辑,然后在smail代码中进行修改即可,上面说到的JEB工具,就加强了jd-gui工具的功能,它可以直接将smail源码翻译成java代码,这样我们就不需要先用jd-gui工具查看,再去smail源码中修改了,借助JEB即可。

4、如果程序中有涉及到native层的话,我们可以用IDA打开指定的so文件。我们还是需要先看java代码,找到指定的so文件,在用IDA来静态分析so文件。

第二、用到的技术

上面介绍了静态分析的流程,下面来看一下静态分析的几个技术,我们在静态分析破解Apk的时候,首先需要找到突破点,找到关键的类和方法,当然这里就需要经验了,不是有方法可循的。但是我们会借助一些技术来加快破解。

1、全局查找关键字符串和日志信息

这个技术完全靠眼,我们在运行程序之后,会看到程序中出现的字符串,比如文本框,按钮上的文本,toast显示的信息等,都可能是重要信息,然后我们可以在jd-gui工具中全局搜索这个字符串,这样就会很快的定位到我们想要找的逻辑地方:

当然我们还有一个重要点就是Android中的Log信息,因为在一个大的项目中,会有多人开发,所以每个模块每个人开发,每个人都会调试信息,所以就会添加一些log信息,但是不是所有的人都会记得在项目发布的时候关闭项目中的所有log信息,这个也是我们在项目开发的过程中不好的习惯。这时候我们就可以通过程序运行起来之后,会打印一些log信息,那么我们可以通过这些信息获取突破点,Android中的log可以根据一个应用来进行过滤的,或者我们可以通过log信息中的字符串在jd-gui中进行全局搜索也是可以的。

2、代码的注入技术

在第一种方式中我们通过全局搜索一些关键的字符串来找突破点,但是这招有时候不好使,所以这时候我们需要加一些代码了来观察信息了,这里有一个通用的方法就是加入我们自己的log代码,来追踪代码的执行逻辑,因为这里讲的是静态分析技术,所以就用代码注入技术来跟踪执行逻辑,后面介绍了动态分析技术之后,那就简单了,我们可以随意的打断点来进行调试。这里的添加代码,就是修改smail代码,添加我们的日志信息即可,在下面我们会用例子来进行讲解,这个也是我们最常用的一种技术。

3、使用系统的Hook技术,注入破解程序进程,获取关键方法的执行逻辑

关于Android中的进程注入和Hook技术,这里就不做详细介绍了,不了解这些技术的同学可以转战:

注入技术:http://blog.csdn.net/jiangwei0910410003/article/details/39292117

Hook技术:http://blog.csdn.net/jiangwei0910410003/article/details/41941393

这两篇文章介绍了这两项技术,但是我们在实际操作过程中不用这两篇文章中用到的方式,因为这两篇文章只是介绍原理,技术还不是很成熟,关于这两个技术,网上有两个框架很成熟,也很实用,就是人们熟知的:Cydia和Xposed,关于这两个框架的话,网上的资料太多了,而且用起来也很容易,这里就不做太多的详细介绍了。

我们在实际的破解的过程中,这种方式用的有点少,因为这种方式效率有点低,所以只有在特定的场景下会使用。

4、使用IDA来静态分析so文件

这里终于用到了IDA工具了,本人是感觉这个工具太强大了,他可以查看so中的代码逻辑,我们看到的的可能是汇编指令,所以这里就有一个问题了,破解so的时候,我们还必须掌握一项技能,就是能看懂汇编指令,不然用IDA来破解程序,会很费经的,关于汇编指令,大学的时候,我们接触过了,但是我们当时感觉这东西又难,而且用的地方也很少,所以就没太在意,其实不然呀,真正懂汇编的人才是好的程序员:

看到些汇编指令,头立马就大了,不过这个用多了,破解多了,还是可以的。我们可以看到左边栏中有我们的函数,我们可以找到指定函数的定义的地方进行查看即可。其实IDA最强大的地方是在于他动态调试so文件,下一篇文章会介绍怎么动态调试so文件。当然IDA可也是可以直接查看apk文件的:

可以查看apk文件中的所有文件,我们可以选择classes.dex文件:

但是这里我们可能会遇到一个问题,就是如果应用程序太大的话,这个打开的过程中会很慢的,有可能IDA停止工作,所以要慢慢等啦:

打开之后,我们可以看到我们的类和方法名,这里还可以支持搜索类名和方法名Ctrl+F,也可以查看字符串内容(Shirt+F12):

我们发现IDA也是一个分析Java代码的好手,所以说这个工具太强大了啦啦~~

四、案例分析

上面讲解了静态分析的破解技术,那么下面就开始使用一个例子来看看静态分析的技术。

第一、静态分析Java(smail)代码

首先我们拿到我们需要破解的Apk,使用apktool.jar工具来反编译:

java -jar apktool.jar d xxx.apk

这个apk很是容易就被反编译了,看来并没有进行任何的加固。那就好办了,我们这里来改一下他的AndroidManifest.xml中的信息,改成可调式模式,这个是我们后面进行动态调试的前提,一个正式的apk,在AndroidManifest.xml中这个值是false的。

我们看看他的AndroidManifest.xml文件:

我们把这个值改成true.在回编译,这时候我们就可以动态调试这个apk了,所以在这点上我们可以看到,静态分析是动态分析的前提,这个值不修改的话,我们是办法进行后续的动态调试的。

修改成功之后,我们进行回编译:

cd C:\Users\jiangwei\Desktop\静态分析\apktool_2.0.0rc4
del debug.sig.apk
java -jar apktool.jar b -d 123 -o debug.apk
java -jar .\sign\signapk.jar .\sign\testkey.x509.pem .\sign\testkey.pk8 debug.apk debug.sig.apk
del debug.apk
adb uninstall com.shuqi.controller
adb install debug.sig.apk
adb shell am start -n com.shuqi.controller/.Loading
pause

这里是为了简单,写了一个批处理,首先进入到目录,然后使用命令进行回编译:

java -jar apktool.jar b -d sq -o debug.apk

sq是之前反编译的目录,debug.apk是回编译之后的文件

这时候,debug.apk是不能安装运行的,因为没有签名,Android中是不允许安装一个没有签名的apk

下面还要继续签名,我们用系统自带的签名文件即可签名:

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

注:其实我们在用IDE工具开发android项目的时候,工具就是用这个签名文件进行签名的,只是这个过程IDE帮我们做了。

后面就是直接安装这个apk,然后运行这个Apk。这个过程中我们只需要知道应用的包名和入口Activity名称即可,这个信息我们在AndroidManifest.xml中也是可以获取到的,当然我们用:adb shell dumpsys activity top 命令也可以得到:

回编译之后,我们运行程序,发现有问题,就是点击程序的icon,没反应,运行不起来,我们在查看log中的异常信息,发现也没有抛出任何异常,那么这时候,我们就判断,他内部肯定做了什么校验工作,这个一般回编译之后的程序运行不起来的话,那就是内部做校验了,一般做校验的话,有两种:

1、对dex做校验,防止修改dex的

2、对apk的签名做校验,防止重新打包

那我们就需要从新看看他的代码,来看看是不是做了校验:

我们在分析代码的时候,肯定先看看他有没有自己定义Application,如果有定义的话,就需要看他自己的Application类,这里我们看到他定了自己的Application:com.shuqi.application.ShuqiApplication

我们解压apk,得到dex,然后dex2jar进行转化,得到jar,再用jd-gui查看这个类:

这里我们看到他的代码做混淆了,但是一些系统回调方法肯定不能混淆的,比如onCreate方法,但是这里我们一般找的方法是:

1、首先看这个类有没有静态方法和静态代码块,因为这类的代码会在对象初始化之前运行,可能在这里加载so文件,或者是加密校验等操作

2、再看看这个类的构造方法

3、最后再看生命周期方法

我们这里看到他的核心代码在onCreate中,调用了很多类的方法,猜想这里的某个方法做工作了?

这时候我们就来注入我们的代码来跟踪是哪个方法出现问题了,这里有的同学有疑问,其实就这几个方法,直接一个一个看不就结了,哎,我们这篇文章就是要介绍静态分析技术,当然就需要做案例啦。

下面来看看我们怎么添加我们的日志信息,其实很简单,就是添加日志,需要修改smail文件,我们在去查看smail源码:

关于smail语法,本人认为不是很难,所以大家自己网上去搜一些资料学习一下即可,这里我们可以很清晰的看到调用了这些方法,那么我们就在每个方法加上我们的日志信息,这里加日志有两种方式,一种就是直接在这里调用系统的log方法,但是有两个问题:

1、需要导入包,在smail中修改

2、需要定义一个两个参数,一个是tag,msg,才能正常的打印log出来

明显这个方法有点麻烦,这里我们就自己定义一个MyLog类,然后反编译,得到MyLog的smail文件,添加到这个ShuqiApplication.smail的root目录下,然后在代码中直接调用即可,至于为何要放到root目录下,这样在代码中调用就不需要导入包了,比如SuqiApplication.smail中的一些静态方法调用:

编写日志类MyLog,这里就不粘贴代码了,我们新建一个项目之后,反编译得到MyLog.smail文件,放到目录中:

我们得到这个文件的时候,一定要注意,把MyLog.smail的包名信息删除,因为我们放到root目录下的,意味着这个MyLog类是没有任何包名的,这个需要注意,不然最后加的话,也是报错的。

我们在ShuqiApplication的onCreate方法中插入我们的日志方法:

invoke-static {}, LMyLog;->print()V

但是我们在加代码的时候,需要注意的是,要找对地方加,所谓找对地方,就是在上个方法调用完之后添加,比如:

invoke-virtual,invoke-static等,而且这些指令后面不能有:move-result-object,因为这个指令是获取方法的返回值,所以我们一般是这么加代码的:

1、在invoke-static/invoke-virtual指令他的返回类型是V之后可以加入

2、在invoke-static/invoke-virtual指令返回类型不是V,之后的move-result-object命令之后可以加入

加好了我们的日志代码之后,下面我们就回编译执行,在这个过程可能会遇到samil语法错误,这个就对应指定的文件修改就可以了,我们得到回编译的apk之后,可以在反编译一下,看看他的java代码:

我们看到了,我们添加的代码,在每个方法之后打印信息。

下面我们运行程序,同时开启我们的log的tag:adb logcat -s JW

看到我们打印的日志了,我们发现打印了三个log,这里需要注意的是,这里虽然打印了三个log,但是都是在不同的进程中,所以说一个进程中的log的话,只打印了一个,所以我们判断,问题出现在vr.h这个方法

我们查看这个方法源码:

果然,这个方法做了签名验证,不正确的话,直接退出程序。那么我们现在要想正常的运行程序的话,很简单了,直接注释这行代码:vr.h(this)

然后回编译,在运行,果然不报错了,这里就不在演示了:

好了,上面就通过注入代码,来跟踪问题,这个方法是很常用,也是很实在的。

第二、静态分析Native代码

下面继续来介绍一下,如何使用IDA来静态分析native代码,这里一定要熟悉汇编指令,不然看起来很费劲的。

我们在反编译之后,看到他的onCreate方法中有一个加载so的代码

看看这个代码:

获取密码的方法,是native的,我们就来看看那个getDbPassword方法,用IDA打开libpsProcess.so文件:

我们看看这个函数的实现,我们一般直接看BL/BLX等信息,跳转逻辑,还有就是返回值,我们在函数的最后部分,发现一个重点,就是:BL __android_log_print  这个是在native层调用log的函数,我们在往上看,发现:tag是System.out.c

我们运行程序看起log看看,但是我们此时也可以在java层添加日志的:我们全局搜索这个方法,在yi这个类中调用的

我们修改yi.smail代码:

回编译,在运行程序,开启log:

adb logcat -s JW

adb logcat -s System.out.c

发现,返回的密码java层和native层是一样的。说明我们静态分析native还是有效的。

好了,到这里我们今天的内容就介绍完了,当然还有很多静态分析apk的方法,这里只是介绍了本人用到的技术。

案例下载:http://download.csdn.net/detail/jiangwei0910410003/9308217

案例中有个说明文件,运行前请阅读~~

五、未解决的问题

1、如何搞定apktool工具反编译出错的问题

这个我在开始的时候也说了,这里出错的原因大部分是apk进行加固了,所以后面我会专门介绍一下如何解决这样的问题

2、如何搞定让一个Apk可以调试

我们在上面看到一个apk想要能调试的话,需要修改android:debug的值,但是有时候,我们会遇到修改失败,导致程序不能运行,后面会专门介绍有几种方式来让一个发布后的apk可以调试

六、技术总结

这篇文章我们介绍了如何使用静态方式去破解一个apk,我们在破解一个apk的时候,其实就是改点代码,然后能够运行起来,达到我们想要的功能,一般就是:

1、注释特定功能,比如广告展示等

2、得到方法的返回值,比如获取用户的密码

3、添加我们的代码,比如加入我们自己的监测代码和广告等

我们在静态分析代码的时候,需要遵循的大体路线:

1、首先能够反编译,得到AndroidManifest.xml文件,找到程序入口代码

2、找到我们想要的代码逻辑,一般会结合界面分析,比如我们想得让用户登录成功,我们肯定想要得到用户登录界面Activity,这时候我们可以用adb shell dumpsys activity top命令得到Activity名称,然后用Eclipse自带的程序当前视图分析工具:得到控件名称,或者是在代码中获取layout布局文件,一般是setContentView方法的调用地方,然后用布局文件结合代码得到用户登录的逻辑,进行修改

3、在关键的地方通过代码注入技术来跟踪代码执行逻辑

4、注意方法的返回值,条件判断等比较显眼的代码

5、对于有些apk中的源码,可能他有自己的加密算法,这时候我们需要获取到这个加密方法,如果加密方法比较复杂的话,我们就需要大批的测试数据来获取这个加密方法的逻辑,一般是输入和输出作为一个测试用例,比如阿里安全第一届比赛的第一题就可以用静态分析的方式破解,它内部就是一个加密算法,我们需要用测试数据来破解。

6、对于那些System.loadLibrary加载so文件的代码,我们只需要找到这个so文件,然后用IDA打开进行静态分析,因为有些apk中把加密算法放到了so中了,这时候我们也可以通过测试数据来获取加密算法。

7、通过上面的例子,我们可以总结一个方式,就是现在很多apk会做一些校验工作,一般在代码中包含:“signature”字符串信息,所以我们可以全局搜索一下,也许可以获取一些重要信息。

六、总结

这篇文章总算是讲解完了,其实早就想用写破解的文章了,因为破解比加固有意思,至少破解成功了有成就感。这篇文章主要介绍了如何通过静态分析方式破解,介绍了一些工具的时候,破解流程和破解技巧。最常用的就是代码注入技术和全局搜索关键字符串等方式,但是我们可以看到,现在市面上的很多apk,光通过静态分析是无法满足我们的破解需求了,所以动态分析方式就来了,而且动态方式破解难度会很大,需要掌握的东西也很多,我后面会分几篇文章来一一介绍动态破解的技巧和常见的问题。但是静态方式破解也是很重要的。当然也是动态分析的前提,所以我们既然玩破解,那么这两种技术都必须很好的掌握。

PS: 关注微信,最新Android技术实时推送

Android逆向之旅---静态分析技术来破解Apk的更多相关文章

  1. android黑科技系列——静态分析技术来破解Apk

    一.前言 从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,And ...

  2. Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题

    一.故事背景 现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时.就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的.相比较短视频有 ...

  3. Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)

    Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码) 来源 https://blog.csdn.net/jiangwei0910410003/article/details/51 ...

  4. Android逆向之旅---SO(ELF)文件格式详解(转)

    第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...

  5. Android逆向之旅---反编译利器Apktool和Jadx源码分析以及错误纠正

    Android逆向之旅---反编译利器Apktool和Jadx源码分析以及错误纠正 http://blog.csdn.net/jiangwei0910410003/article/details/51 ...

  6. Android逆向之旅---基于对so中的section加密技术实现so加固

    一.前言 好长时间没有更新文章了,主要还是工作上的事,连续加班一个月,没有时间研究了,只有周末有时间,来看一下,不过我还是延续之前的文章,继续我们的逆向之旅,今天我们要来看一下如何通过对so加密,在介 ...

  7. Android逆向之旅---SO(ELF)文件格式详解

    第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...

  8. Android逆向之旅---带你爆破一款应用的签名验证问题

    一.前言 在之前的文章中说过Android中的安全和破解是相辅相成的,为了防止被破解.非常多应用做了一些防护策略.可是防护策略也是分等级.一般简单的策略就是混淆代码和签名校验.而对于签名校验非常多应用 ...

  9. Android 逆向实战篇(加密数据包破解)

    1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...

随机推荐

  1. Samba 1.0服务部署

    Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成. SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统.打印机及其他资源. ...

  2. c# thread4——lock,死锁,以及monitor关键字

    多线程的存在是提高系统效率,挖掘cpu性能的一种手段,那么控制它,能够协同多个线程不发生bug是关键. 首先我们来看一段不安全的多线程代码. public abstract class Calcula ...

  3. The bean 'dataSource', defined in BeanDefinition defined in class path resou

    SpringCloud对应SpringBoot不匹配 Greenwich 2.1.x Finchley 2.0.x Edgware 1.5.x Dalston 1.5.x SpringBoot Spr ...

  4. idea下载和设置自动翻译(有道)

    1:下载 点击file,点击settings,找到plugins,之后所搜translation并下载,他会自动从新启动idea 2:设置translation 3:这个应用ID和秘钥需要在有道智云去 ...

  5. python基础-4.1 open 打开文件练习:修改haproxy配置文件

    1.如何在线上环境优雅的修改配置文件? 配置文件名称ini global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 in ...

  6. vsphere虚拟化之Active Directory域的创建(一)

    1.搭建环境说明 本机是在Vmware Workstation 12 Pro虚拟软件下进行搭建的. 操作系统版本:Windows Server 2012 R2 简体中文企业版x64. 2.安装完win ...

  7. (4.12)mysql备份还原——mysql逻辑备份之mysqldump

    关键词:mysql逻辑备份介绍,mysqldump,mysqldump最佳实践 我的相关文章:https://www.cnblogs.com/gered/p/9721696.html 正文 1.mys ...

  8. Java-集合第一篇认识Java集合

    1.4种集合类型 List:有序可重复集合. Queue:队列集合. Set:无序不可重复集合. ------------------------------- Map:关系映射集合. 2.所有的集合 ...

  9. [CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)]飞行棋

    题目链接:https://www.cometoj.com/contest/59/problem/E?problem_id=2714 求期望并且一堆转移基本上就是期望dp了(叉腰 照常的设dp[i]表示 ...

  10. [BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap)

    [BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap) 题面 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数 ...