安卓动态调试七种武器之离别钩 – Hooking(上)

0x00 序

随着移动安全越来越火,各种调试工具也都层出不穷,但因为环境和需求的不同,并没有工具是万能的。另外工具是死的,人是活的,如果能搞懂工具的原理再结合上自身的经验,你也可以创造出属于自己的调试武器。因此,笔者将会在这一系列文章中分享一些自己经常用或原创的调试工具以及手段,希望能对国内移动安全的研究起到一些催化剂的作用。

目录如下:

文章中所有提到的代码和工具都可以在我的github下载到,地址是:https://github.com/zhengmin1989/TheSevenWeapons

0x01 离别钩

Hooking翻译成中文就是钩子的意思,所以正好配合这一章的名字《离别钩》。

“我知道钩是种武器,在十八般兵器中名列第七,离别钩呢?” “离别钩也是种武器,也是钩。”
“既然是钩,为什么要叫做离别?”
“因为这柄钩,无论钩住什么都会造成离别。如果它钩住你的手,你的手就要和腕离别;如果它钩住你的脚,你的脚就要和腿离别。”
“如果它钩住我的咽喉,我就和这个世界离别了?”
“是的,”
“因为我不愿被人强迫与我所爱的人离别。”
“我明白你的意思了。”
“你真的明白?”
“你用离别钩,只不过为了要相聚。”
“是的。”

一提到hooking,让我又回想起了2011年的时候。当时android才出来没多久,各大安全公司都在忙着研发自己的手机助手。当时手机上最泛滥的病毒就是短信扣费类的病毒,但仅仅是靠云端的病毒库扫描是远远不够的。而这时候”LBE安全大师”横空出世,提供了主动防御的技术,可以在病毒发送短信之前拦截下来,并让用户选择是否发送。 其实这个主动防御技术就是hooking。虽然在PC上hooking的技术已经很成熟了,但是在android上的资料却非常稀少,只有少数人掌握着android上hooking的技术,因此这些人也变成了各大公司争相抢夺的对象。

但是没有什么东西是能够永久保密的,这些技术早晚会被大家研究出来并对外公开的。因此,到了2015年,android上的hook资料已经遍地都是了,各种开源的hook框架也层出不穷,使用这些hook工具就可以轻松的hook native,jni和java层的函数。但这同样也带来了一些问题,新手想研究hook的时候因为资料和工具太多往往不知道如何下手,并且就算使用了工具成功的hook,也根本不知道原理是什么。因此笔者准备从hook的原理开始,配合开源工具循序渐进的介绍native,jni和java层的hook,方便大家对hook进行系统的学习。

0x02 Playing with Ptrace on Android

其实无论是hook还是调试都离不开ptrace这个system call,利用ptrace,我们可以跟踪目标进程,并且在目标进程暂停的时候对目标进程的内存进行读写。在linux上有一篇经典的文章叫《Playing with Ptrace》,简单介绍了如何玩转ptrace。在这里我们照猫画虎,来试一下playing with Ptrace on Android。

PS:这里的一部分内容借鉴了harry大牛在百度Hi写的一篇文章,可惜后来百度Hi关了,就失传了。不过不用担心,我这篇比他写的还详细。:)

首先来看我们要ptrace的目标程序,用来一直循环输出一句话”Hello,LiBieGou!”:

图片描述

想要编译它非常简单,首先建立一个Android.mk文件,然后填入如下内容,让ndk将文件编译为elf可执行文件:

图片描述

接下来我们写出hook1.c程序来hook target程序的system call,main函数如下:

图片描述

首先要知道hook的目标的pid,这个用ps命令就能获取到。然后我们使用ptrace(PTRACE_ATTACH, pid, NULL, NULL)这个函数对目标进程进行加载。加载成功后我们可以使用ptrace(PTRACE_SYSCALL, pid, NULL, NULL)这个函数来对目标程序下断点,每当目标程序调用system call前的时候,就会暂停下载。然后我们就可以读取寄存器的值来获取system call的各项信息。然后我们再一次使用ptrace(PTRACE_SYSCALL, pid, NULL, NULL)这个函数就可以让system call在调用完后再一次暂停下来,并获取system call的返回值。

获取system call编号的函数如下:

图片描述

ARM架构上,所有的系统调用都是通过SWI来实现的。并且在ARM 架构中有两个SWI指令,分别针对EABI和OABI:

[EABI] 机器码:
1110 1111 0000 0000 -- SWI 0
具体的调用号存放在寄存器r7中.

[OABI] 机器码:
1101 1111 vvvv vvvv -- SWI immed_8
调用号进行转换以后得到指令中的立即数。立即数=调用号 | 0x900000

既然需要兼容两种方式的调用,我们在代码上就要分开处理。首先要获取SWI指令判断是EABI还是OABI,如果是EABI,可从r7中获取调用号。如果是OABI,则从SWI指令中获取立即数,反向计算出调用号。

我们接着看hook system call前的函数,和hook system call后的函数:

图片描述

在获取了system call的number以后,我们可以进一步获取个个参数的值,比如说write这个system call。在arm上,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递。若形参个数大于4,大于4的部分必须通过堆栈进行传递。而执行完函数后,函数的返回值会保存在R0这个寄存器里。

下面我们就来实际运行一下看看效果。我们先把target和hook1 push到 /data/local/tmp目录下,再chmod 777一下。接着运行target。

图片描述

我们随后再开一个shell,然后ps获取target的pid,然后使用hook1程序对target进行hook操作:

图片描述

我们可以看到第一个SysCallNo是162,也就是sleep函数。第二个SysCallNo是4,也就是write函数,因为printf本质就是调用write这个系统调用来完成的。关于system call number对应的具体system call可以参考我在github上的reference文件夹中的systemcalllist.txt文件,里面有对应的列表。我们的hook1程序还对write的参数做了解析,比如1表示stdout,0xadf020表示字符串的地址,19代表字符串的长度。而返回值19表示write成功写入的长度,也就是字符串的长度。

整个过程用图表达如下:

图片描述

0x03 利用Ptrace动态修改内存

仅仅是用ptrace来获取system call的参数和返回值还不能体现出ptrace的强大,下面我们就来演示用ptrace读写内存。我们在hook1.c的基础上继续进行修改,在write被调用之前对要输出string进行翻转操作。

我们在hookSysCallBefore()函数中加入modifyString(pid, regs.ARM_r1, regs.ARM_r2)这个函数:

图片描述

因为write的第二个参数是字符串的地址,第三个参数是字符串的长度,所以我们把R1和R2的值传给modifyString()这个函数:

图片描述

modifyString()首先获取在内存中的字符串,然后进行翻转操作,最后再把翻转后的字符串写入原来的地址。这些操作用到了getdata()和putdata()函数:

图片描述

getdata()和putdata()分别使用PTRACE_PEEKDATA和PTRACE_POKEDATA对内存进行读写操作。因为ptrace的内存操作一次只能控制4个字节,所以如果修改比较长的内容需要进行多次操作。

我们现在运行一下target,并且在运行中用hook2程序进行hook:

图片描述

哈哈,是不是看到字符串都被翻转了。如果我们退出hook2程序,字符串又会回到原来的样子。

0x04 利用Ptrace动态执行sleep()函数

上一节中我们介绍了如何使用ptrace来修改内存,现在继续介绍如何用ptrace来执行libc .so中的sleep()函数。主要逻辑都在inject()这个函数中:

图片描述

首先我们用ptrace(PTRACE_GETREGS, pid, NULL, &old_regs)来保存一下寄存器的值,然后获取sleep()函数在目标进程中的地址,接着利用ptrace执行sleep()函数,最后在执行完sleep()函数后再用ptrace(PTRACE_SETREGS, pid, NULL, &old_regs)恢复寄存器原来值。

下面是获取sleep()函数在目标进程中地址的代码:

图片描述

因为libc.so在内存中的地址是随机的,所以我们需要先获取目标进程的libc.so的加载地址,再获取自己进程的libc.so的加载地址和sleep()在内存中的地址。然后我们就能计算出sleep()函数在目标进程中的地址了。要注意的是获取目标进程和自己进程的libc.so的加载地址是通过解析/proc/[pid]/maps得到的。

接下来是执行sleep()函数的代码:

图片描述

首先是将参数赋值给R0-R3,如果参数大于四个的话,再使用putdata()将参数存放在栈上。然后我们将PC的值设置为函数地址。接着再根据是否是thumb指令设置ARM_cpsr寄存器的值。随后我们使用ptrace_setregs()将目标进程寄存器的值进行修改。最后使用waitpid()等待函数被执行。

编译完后,我们使用hook3对target程序进行hook:

图片描述

正常的情况是target程序每秒输出一句话,但是用hook3程序hook后,就会暂停10秒钟的时间,因为我们利用ptrace运行了sleep(10)在目标程序中。

0x05 利用Ptrace动态加载so并执行自定义函数

仅仅是执行现有的libc函数是不能满足我们的需求的,接下来我们继续介绍如何动态的加载自定义so文件并且运行so文件中的函数。逻辑大概如下:

保存当前寄存器的状态 -> 获取目标程序的mmap, dlopen, dlsym, dlclose 地址 -> 调用mmap分配一段内存空间用来保存参数信息 –> 调用dlopen加载so文件 -> 调用dlsym找到目标函数地址 -> 使用ptrace_call执行目标函数 -> 调用 dlclose 卸载so文件 -> 恢复寄存器的状态。

实现整个逻辑的函数 injectSo()的代码如下:

图片描述
图片描述

mmap()可以用来将一个文件或者其它对象映射进内存,如果我们把flag设置为MAP_ANONYMOUS并且把参数fd设置为0的话就相当于直接映射一段内容为空的内存。mmap()的函数声明和参数如下:

图片描述

  • start:映射区的开始地址,设置为0时表示由系统决定映射区的起始地址。 length:映射区的长度。

  • prot:期望的内存保护标志,不能与文件的打开模式冲突。我们这里设置为RWX。

  • flags:指定映射对象的类型,映射选项和映射页是否可以共享。我们这里设置为:MAP_ANONYMOUS(匿名映射,映射区不与任何文件关联),MAP_PRIVATE(建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件)。

  • fd:有效的文件描述词。匿名映射设置为0。

  • off_toffset:被映射对象内容的起点。设置为0。

在我们使用ptrace_call(pid, mmap_addr, parameters, 6, &regs)调用完mmap()函数之后,要记得使用ptrace(PTRACE_GETREGS, pid, NULL, &regs); 用来获取保存返回值的regs.ARM_r0,这个返回值也就是映射的内存的起始地址。

mmap()映射的内存主要用来保存我们传给其他函数的参数。比如接下来我们需要用dlopen()去加载”/data/local/tmp/libinject.so”这个文件,所以我们需要先用putdata()将”/data/local/tmp/libinject.so”这个字符串放置在mmap()所映射的内存中,然后就可以将这个映射的地址作为参数传递给dlopen()了。接下来的dlsym(),so中的目标函数,dlclose()都是相同调用的方式,这里就不一一赘述了。

我们再来看一下被加载的so文件,里面的内容为:

图片描述

这里我们不光使用printf()还使用了android debug的函数LOGD()用来输出调试结果。所以在编译时我们需要加上LOCAL_LDLIBS := -llog。

编译完后,我们使用hook4对target程序进行hook:

图片描述

可以看到无论是stdout还是logcat都成功的输出了我们的调试信息。这意味着我们可以通过注入让目标进程加载so文件并执行任意代码了。

0x06 小节

现在我们已经可以做到hook system call以及动态的加载自定义so文件并且运行so文件中的函数了,但离执行以及hook java层的函数还有一定距离。因为篇幅原因,我们的hook之旅就先进行到这里,敬请期待一下篇《离别钩 - Hooking》

文章中所有提到的代码和工具都可以在我的github下载到,地址是:https://github.com/zhengmin1989/TheSevenWeapons

0x07 参考资料

作者:蒸米@阿里聚安全,更多技术文章,请访问阿里聚安全博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值