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

一、前言

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

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

 

二、知识概要分析

那么今天我们就用另外一种方式来破解apk:动态方式,关于动态方式其实很广义的,因为动态方式相对于静态方式来说,难度大一点,但是他比静态方式高效点,能够针对更过的破解范围。当然动态方式很多,所以这里就分为三篇文章来讲解这块:

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

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

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

从这三篇文章能够让我们破解一般的apk没有任何问题,不过不能代表能够破解所有的apk,因为没有绝对的安全,也是没有绝对的破解,两方都在进步,我们只能具体问题具体分析。好了,下面我们就来看第一篇文章,也是今天的重点:Eclipse动态调试smali源码

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

 

三、案例分析

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

我们就用阿里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的:

 

2、修改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

 

四、思路整理

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

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

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

4、设置远程调试工程,首先运行需要调试程序,然后在DDMS中找到对应的调试服务端的端口号,然后在Debug Configurations中设置远程调试项目,设置对应的调试端口和ip地址(一般都是本机pc,那就是localhost),然后红色小蜘蛛变成绿色的,表示我们的远程调试项目连接关联上了调试程序,这里需要注意的是,一定需要关联正确,不然是没有任何效果的,关联成功之后,就可以进行操作。

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

6、最后一般当我们知道了核心方法的逻辑,要想得到正确的密码,还是需要自己用语言去实现逻辑的,比如本文中的加密方法,我们需要手动的code一下加密的逆向方法,才能得到正确的密码。

 

五、遗留问题

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

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

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

3、有时候我们还会遇到回编译成功了,然后遇到运行不起来的错误,这个就需要使用静态方式先去分析程序启动的逻辑,看看是不是程序做了什么运行限制,比如我们在静态分析那篇文章中,提到了应用为了防止反编译在回编译运行,在程序的入口处作了签名校验,如果校验失败,直接kill掉自己的进程,退出程序了,所以这时候我们还是需要使用静态方式去分析apk。

4、如何做到不修改AndroidManifest.xml中的debug属性就可以进行调试:

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

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

 

六、总结

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

转载于:https://www.cnblogs.com/chenxibobo/p/6075057.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
https://github.com/iBotPeaches/Apktool Introduction Basic First lets take a lesson into apk files. apks are nothing more than a zip file containing resources and compiled java. If you were to simply unzip an apk like so, you would be left with files such as classes.dex and resources.arsc. $ unzip testapp.apk Archive: testapp.apk inflating: AndroidManifest.xml inflating: classes.dex extracting: res/drawable-hdpi/ic_launcher.png inflating: res/xml/literals.xml inflating: res/xml/references.xml extracting: resources.arsc However, at this point you have simply inflated compiled sources. If you tried to view AndroidManifest.xml. You'd be left viewing this. P4F0\fnversionCodeversionNameandroid*http://schemas.android.com/apk/res/androidpackageplatformBuildVersionCodeplatformBuildVersionNamemanifestbrut.apktool.testapp1.021APKTOOL Obviously, editing or viewing a compiled file is next to impossible. That is where Apktool comes into play. $ apktool d testapp.apk I: Using Apktool 2.0.0 on testapp.apk I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: 1.apk I: Regular manifest package... I: Decoding file-resources... I: Decoding values */* XMLs... I: Baksmaling classes.dex... I: Copying assets and libs... $ Viewing AndroidManifest.xml again results in something much more human readable <?xml version="1.0" encoding="utf-8" standalone="no"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android" package="brut.apktool.testapp" platformBuildVersionCode="21" platformBuildVersionName="APKTOOL"/> In addition to XMLs, resources such as 9 patch images, layouts, strings and much more are correctly decoded to source form. Decoding The decode option on Apktool can be invoked either from d or decode like shown below. $ apktool d foo.jar // decodes foo.jar to foo.jar.out folder $ apktool decode foo.jar // decodes foo.jar to foo.jar.out folder $ apktool d bar.apk // decodes bar.apk to bar folder $ apktool decode bar.apk // decodes bar.apk to bar folder $ apktool d bar.apk -o baz // decodes bar.apk to baz folder Building The build option can be invoked either from b or build like shown below $ apktool b foo.jar.out // builds foo.jar.out folder into foo.jar.out/dist/foo.jar file $ apktool build foo.jar.out // builds foo.jar.out folder into foo.jar.out/dist/foo.jar file $ apktool b bar // builds bar folder into bar/dist/bar.apk file $ apktool b . // builds current directory into ./dist $ apktool b bar -o new_bar.apk // builds bar folder into new_bar.apk $ apktool b bar.apk // WRONG: brut.androlib.AndrolibException: brut.directory.PathNotExist: apktool.yml // Must use folder, not apk/jar file InfoIn order to run a rebuilt application. You must resign the application. Android documentation can help with this. Frameworks Frameworks can be installed either from if or install-framework, in addition two parameters -p, --frame-path <dir> - Store framework files into <dir> -t, --tag <tag> - Tag frameworks using <tag> Allow for a finer control over how the files are named and how they are stored. $ apktool if framework-res.apk I: Framework installed to: 1.apk // pkgId of framework-res.apk determines number (which is 0x01) $ apktool if com.htc.resources.apk I: Framework installed to: 2.apk // pkgId of com.htc.resources is 0x02 $ apktool if com.htc.resources.apk -t htc I: Framework installed to: 2-htc.apk // pkgId-tag.apk $ apktool if framework-res.apk -p foo/bar I: Framework installed to: foo/bar/1.apk $ apktool if framework-res.apk -t baz -p foo/bar I: Framework installed to: foo/bar/1-baz.apk Migration Instructions v2.1.1 -> v2.2.0 Run the following commands to migrate your framework directory Apktool will work fine without running these commands, this will just cleanup abandoned files unix - mkdir -p ~/.local/share; mv ~/apktool ~/.local/share windows - move %USERPROFILE%\apktool %USERPROFILE%\AppData\Local v2.0.1 -> v2.0.2 Update apktool to v2.0.2 Remove framework file $HOME/apktool/framework/1.apk due to internal API update (Android Marshmallow) v1.5.x -> v2.0.0 Java 1.7 is required Update apktool to v2.0.0 aapt is now included inside the apktool binary. It's not required to maintain your own aapt install under $PATH. (However, features like -a / --aapt are still used and can override the internal aapt) The addition of aapt replaces the need for separate aapt download packages. Helper Scripts may be found here Remove framework $HOME/apktool/framework/1.apk Eagle eyed users will notice resources are now decoded before sources now. This is because we need to know the API version via the manifest for decoding the sources Parameter Changes Smali/baksmali 2.0 are included. This is a big change from 1.4.2. Please read the smali updates here for more information -o / --output is now used for the output of apk/directory -t / --tag is required for tagging framework files -advance / --advanced will launch advance parameters and information on the usage output -m / --match-original is a new feature for apk analysis. This retains the apk is nearly original format, but will make rebuild more than likely not work due to ignoring the changes that newer aapt requires After [d]ecode, there will be new folders (original / unknown) in the decoded apk folder original = META-INF folder / AndroidManifest.xml, which are needed to retain the signature of apks to prevent needing to resign. Used with -c / --copy-original on [b]uild unknown = Files / folders that are not part of the standard AOSP build procedure. These files will be injected back into the rebuilt APK. apktool.yml collects more information than last version SdkInfo - Used to repopulate the sdk information in AndroidManifest.xml since newer aapt requires version information to be passed via parameter packageInfo - Used to help support Android 4.2 renamed manifest feature. Automatically detects differences between resource and manifest and performs automatic --rename-manifest-package on [b]uild versionInfo - Used to repopulate the version information in AndroidManifest.xml since newer aapt requires version information to be passed via parameter compressionType - Used to determine the compression that resources.arsc had on the original apk in order to replicate during [b]uild unknownFiles - Used to record name/location of non-standard files in an apk in order to place correctly on rebuilt apk sharedLibrary - Used to help support Android 5 shared library feature by automatically detecting shared libraries and using --shared-lib on [b]uild Examples of new usage in 2.0 vs 1.5.x Old (Apktool 1.5.x) New (Apktool 2.0.x) apktool if framework-res.apk tag apktool if framework-res.apk -t tag apktool d framework-res.apk output apktool d framework.res.apk -o output apktool b output new.apk apktool b output -o new.apk v1.4.x -> v1.5.1 Update apktool to v1.5.1 Update aapt manually or use package r05-ibot via downloading Mac, Windows or Linux Remove framework file $HOME/apktool/framework/1.apk Intermediate Framework Files As you probably know, Android apps utilize code and resources that are found on the Android OS itself. These are known as framework resources and Apktool relies on these to properly decode and build apks. Every Apktool release contains internally the most up to date AOSP framework at the time of the release. This allows you to decode and build most apks without a problem. However, manufacturers add their own framework files in addition to the regular AOSP ones. To use apktool against these manufacturer apks you must first install the manufacturer framework files. Example Lets say you want to decode HtcContacts.apk from an HTC device. If you try you will get an error message. $ apktool d HtcContacts.apk I: Loading resource table... I: Decoding resources... I: Loading resource table from file: 1.apk W: Could not decode attr value, using undecoded value instead: ns=android, name=drawable W: Could not decode attr value, using undecoded value instead: ns=android, name=icon Can't find framework resources for package of id: 2. You must install proper framework files, see project website for more info. We must get HTC framework resources before decoding this apk. We pull com.htc.resources.apk from our device and install it $ apktool if com.htc.resources.apk I: Framework installed to: 2.apk Now we will try this decode again. $ apktool d HtcContacts.apk I: Loading resource table... I: Decoding resources... I: Loading resource table from file: /home/brutall/apktool/framework/1.apk I: Loading resource table from file: /home/brutall/apktool/framework/2.apk I: Copying assets and libs... As you can see. Apktool leveraged both 1.apk and 2.apk framework files in order to properly decode this application. Finding Frameworks For the most part any apk in /system/framework on a device will be a framework file. On some devices they might reside in /data/system-framework and even cleverly hidden in /system/app or /system/priv-app. They are usually named with the naming of "resources", "res" or "framework". Example HTC has a framework called com.htc.resources.apk, LG has one called lge-res.apk After you find a framework file you could pull it via adb pull /path/to/file or use a file manager application. After you have the file locally, pay attention to how Apktool installs it. The number that the framework is named during install corresponds to the pkgId of the application. These values should range from 1 to 9. Any APK that installs itself as 127 is 0x7F which is an internal pkgId. Internal Frameworks Apktool comes with an internal framework like mentioned above. This file is copied to $HOME/apktool/framework/1.apk during use. Warning Apktool has no knowledge of what version of framework resides there. It will assume its up to date, so delete the file during Apktool upgrades Managing framework files Frameworks are stored in $HOME/apktool/framework for Windows and Unix systems. Mac OS X has a slightly different folder location of $HOME/Library/apktool/framework. If these directories are not available it will default to java.io.tmpdir which is usually /tmp. This is a volatile directory so it would make sense to take advantage of the parameter --frame-path to select an alternative folder for framework files. Note Apktool has no control over the frameworks once installed, but you are free to manage these files on your own. Tagging framework files Frameworks are stored in the naming convention of: <id>-<tag>.apk. They are identified by pkgId and optionally custom tag. Usually tagging frameworks isn't necessary, but if you work on apps from many different devices and they have incompatible frameworks, you will need some way to easily switch between them. You could tag frameworks by: $ apktool if com.htc.resources.apk -t hero I: Framework installed to: /home/brutall/apktool/framework/2-hero.apk $ apktool if com.htc.resources.apk -t desire I: Framework installed to: /home/brutall/apktool/framework/2-desire.apk Then: $ apktool d HtcContacts.apk -t hero I: Loading resource table... I: Decoding resources... I: Loading resource table from file: /home/brutall/apktool/framework/1.apk I: Loading resource table from file: /home/brutall/apktool/framework/2-hero.apk I: Copying assets and libs... $ apktool d HtcContacts.apk -t desire I: Loading resource table... I: Decoding resources... I: Loading resource table from file: /home/brutall/apktool/framework/1.apk I: Loading resource table from file: /home/brutall/apktool/framework/2-desire.apk I: Copying assets and libs... You don't have to select a tag when building apk - apktool automatically uses the same tag, as when decoding. Smali Debugging Warning SmaliDebugging has been marked as deprecated in 2.0.3, and removed in 2.1. Please check SmaliIdea for a debugger. Apktool makes possible to debug smali code step by step, watch variables, set breakpoints, etc. General information Generally we need several things to run Java debugging session: debugger server (usually Java VM) debugger client (usually IDE like IntelliJ, Eclipse or Netbeans) client must have sources of debugged application server must have binaries compiled with debugging symbols referencing these sources sources must be java files with at least package and class definitions, to properly connect them with debugging symbols In our particular situation we have: server: Monitor (Previously DDMS), part of Android SDK, standard for debugging Android applications - explained here client: any JPDA client - most of decent IDEs have support for this protocol. sources: smali code modified by apktool to satisfy above requirements (".java" extension, class declaration, etc.). Apktool modifies them when decoding apk in debug mode. binaries: when building apk in debug mode, apktool removes original symbols and adds new, which are referencing smali code (line numbers, registers/variables, etc.) Info To successfully run debug sessions, the apk must be both decoded and built in debug mode. Decoding with debug decodes the application differently to allow the debug rebuild option to inject lines allowing the debugger to identify variables and types.-d / --debug General instructions Above information is enough to debug smali code using apktool, but if you aren't familiar with DDMS and Java debugging, then you probably still don't know how to do it. Below are simple instructions for doing it using IntelliJ or Netbeans. Decode apk in debug mode: $ apktool d -d -o out app.apk Build new apk in debug mode: $ apktool b -d out Sign, install and run new apk. Follow sub-instructions below depending on IDE. IntelliJ (Android Studio) instructions In IntelliJ add new Java Module Project selecting the "out" directory as project location and the "smali" subdirectory as content root dir. Run Monitor (Android SDK /tools folder), find your application on a list and click it. Note port information in last column - it should be something like "86xx / 8700". In IntelliJ: Debug -> Edit Configurations. Since this is a new project, you will have to create a Debugger. Create a Remote Debugger, with the settings on "Attach" and setting the Port to 8700 (Or whatever Monitor said). The rest of fields should be ok, click "Ok". Start the debugging session. You will see some info in a log and debugging buttons will show up in top panel. Set breakpoint. You must select line with some instruction, you can't set breakpoint on lines starting with ".", ":" or "#". Trigger some action in application. If you run at breakpoint, then thread should stop and you will be able to debug step by step, watch variables, etc. Netbeans instructions In Netbeans add new Java Project with Existing Sources, select "out" directory as project root and "smali" subdirectory as sources dir. Run DDMS, find your application on a list and click it. Note port information in last column - it should be something like "86xx / 8700". In Netbeans: Debug -> Attach Debugger -> select JPDA and set Port to 8700 (or whatever you saw in previous step). Rest of fields should be ok, click "Ok". Debugging session should start: you will see some info in a log and debugging buttons will show up in top panel. Set breakpoint. You must select line with some instruction, you can't set breakpoint on lines starting with ".", ":" or "#". Trigger some action in application. If you run at breakpoint, then thread should stop and you will be able to debug step by step, watch variables, etc. Limitations/Issues Because IDE doesn't have full sources, it doesn't know about class members and such. Variables watching works because most of data could be read from memory (objects in Java know about their types), but if for example, you watch an object and it has some nulled member, then you won't see, what type this member is. 9Patch Images Docs exist for the mysterious 9patch images here and there. (Read these first). These docs though are meant for developers and lack information for those who work with already compiled 3rd party applications. There you can find information how to create them, but no information about how they actually work. I will try and explain it here. The official docs miss one point that 9patch images come in two forms: source & compiled. source - You know this one. You find it in the source of an application or freely available online. These are images with a black border around them. compiled - The mysterious form found in apk files. There are no borders and the 9patch data is written into a binary chunk called npTc. You can't see or modify it easily, but Android OS can as its quicker to read. There are problems related to the above two points. You can't move 9patch images between both types without a conversion. If you try and unpack 9patch images from an apk and use it in the source of another, you will get errors during build. Also vice versa, you cannot take source 9patch images directly into an apk. 9patch binary chunk isn't recognized by modern image processing tools. So modifying the compiled image will more than likely break the npTc chunk, thus breaking the image on the device. The only solution to this problem is to easily convert between these two types. The encoder (which takes source to compiled) is built into the aapt tool and is automatically used during build. This means we only need to build a decoder which has been in apktool since v1.3.0 and is automatically ran on all 9patch images during decode. So if you want to modify 9patch images, don't do it directly. Use apktool to decode the application (including the 9patch images) and then modify the images. At that point when you build the application back, the source 9patch images will be compiled. Other FAQ What about the -j switch shown from the original YouTube videos? Read Issue 199. In short - it doesn't exist. Is it possible to run apktool on a device? Sadly not. There are some incompatibilities with SnakeYAML, java.nio and aapt Where can I download sources of apktool? From our Github or Bitbucket project. Resulting apk file is much smaller than original! Is there something missing? There are a couple of reasons that might cause this. Apktool builds unsigned apks. This means an entire directory META-INF is missing. New aapt binary. Newer versions of apktool contain a newer aapt which optimizes images differently. These points might have contributed to a smaller than normal apk There is no META-INF dir in resulting apk. Is this ok? Yes. META-INF contains apk signatures. After modifying the apk it is no longer signed. You can use -c / --copy-original to retain these signatures. However, using -c uses the original AndroidManifest.xml file, so changes to it will be lost. What do you call "magic apks"? For some reason there are apks that are built using modified build tools. These apks don't work on a regular AOSP Android build, but usually are accompanied by a modified system that can read these modified apks. Apktool cannot handle these apks, therefore they are "magic". Could I integrate apktool into my own tool? Could I modify apktool sources? Do I have to credit you? Actually the Apache License, which apktool uses, answers all these questions. Yes you can redistribute and/or modify apktool without my permission. However, if you do it would be nice to add our contributors (brut.all, iBotPeaches and JesusFreke) into your credits but it's not required. Where does apktool store its framework files? unix - $HOME/.local/share/apktool mac - $HOME/Library/apktool windows - $HOME/AppData/Local/apktool Options Utility Options that can be executed at any time. -version, --version Outputs current version. (Ex: 1.5.2) -v, --verbose Verbose output. Must be first parameter -q, --quiet Quiet output. Must be first parameter -advance, --advanced Advance usage output Decode These are all the options when decoding an apk. --api <API> The numeric api-level of the smali files to generate (defaults to targetSdkVersion) -b, --no-debug-info Prevents baksmali from writing out debug info (.local, .param, .line, etc). Preferred to use if you are comparing smali from the same APK of different versions. The line numbers and debug will change among versions, which can make DIFF reports a pain. -f, --force Force delete destination directory. Use when trying to decode to a folder that already exists --keep-broken-res - Advanced If there is an error like "Invalid Config Flags Detected. Dropping Resources...". This means that APK has a different structure then Apktool can handle. This might be a newer Android version or a random APK that doesn't match standards. Running this will allow the decode, but then you have to manually fix the folders with -ERR in them. -m, --match-original - Used for analysis Matches files closest as possible to original, but prevents rebuild. -o, --output <DIR> The name of the folder that apk gets written to -p, --frame-path <DIR> The folder location where framework files should be stored/read from -r, --no-res This will prevent the decompile of resources. This keeps the resources.arsc intact without any decode. If only editing Java (smali) then this is the recommend for faster decompile & rebuild -s, --no-src This will prevent the disassemble of the dex files. This keeps the apk classes.dex file and simply moves it during build. If your only editing the resources. This is recommended for faster decompile & rebuild -t, --frame-tag <TAG> Uses framework files tagged via <TAG> Rebuild These are all the options when building an apk. -a, --aapt <FILE> Loads aapt from the specified file location, instead of relying on path. Falls back to $PATH loading, if no file found -c, --copy-original - Will still require signature resign post API18 Copies original AndroidManifest.xml and META-INF folder into built apk -d, --debug Adds debuggable="true" to AndroidManifest file. -f, --force-all Overwrites existing files during build, reassembling the resources.arsc file and classes.dex file -o, --output <FILE> The name and location of the apk that gets written -p, --frame-path <DIR> The location where framework files are loaded from

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值