Apktool源码分析

JulAllison 7年前
   <p><img src="https://simg.open-open.com/show/a3309733d239b89b611fa67f5f23608b.jpg"></p>    <p>一、编译</p>    <p>1.源码下载: <a href="/misc/goto?guid=4958984450184054830" rel="nofollow,noindex">https://github.com/iBotPeaches/Apktool</a></p>    <p>2.编译可以直接使用Apktool目录下的gradlew.bat命令,这里使用了Android Studio来编译源码,为后续调试做准备。</p>    <p>3.导入源码,步骤:File–>open–>源码路径,或者在导航页面直接选择import project</p>    <p>4.点击右边的Gradle(注意这里按钮可能贴边上,仔细找一下),点开找到一个类似刷新的按钮,点击一下即可</p>    <p>5.编译:Apktool的主要类在brut.apktool:apktool-cli模块里,运行”fatjar”任务生成项目的jar文件。</p>    <p>6.小结</p>    <p>总体遇到的问题比较少,编译过程会有一些警告,但是并没有大碍;第一次编译Gradle的时候特别慢,于是翻山越岭你懂的,到了第5步编译时要记得断开V*N,不然会报错。</p>    <p>完整步骤及其他问题请移步参考 : <a href="/misc/goto?guid=4959677493448014799" rel="nofollow,noindex">ANDROID反编译工具APKTOOL源码调试过程</a></p>    <p>二、总体代码解析</p>    <p>程序的主要类入口点在 apktool-cli–>java–>brut.apktool–>Main</p>    <p>如下是主要的四个用法:d 反编译 、b 回编译、if 安装框架、处理arsc文件</p>    <p><img src="https://simg.open-open.com/show/bb6cfb992b610e9330de347e7182c1fd.jpg"></p>    <p>Main类里其他部分可到我的github看完整版注释</p>    <p>三、反编译代码解析</p>    <p>跟进路径(Ctrl+B)一:</p>    <p>(1)、cmdDecode–>decoder.decode()–>decodeResourcesFull()–>fileDecoder.decode()–>ResRawStreamDecoder.decoder()</p>    <p>cmdDecode一开始解析选项,比如我们经常敲的命令 apktool d -d 1.apk,这里的-d就是d用法的选项,详细移步Github注释完整版</p>    <p><img src="https://simg.open-open.com/show/5971a59a29427ceafd2a452915d07362.jpg"></p>    <p>继续往下看,找到关键的代码 :</p>    <p><img src="https://simg.open-open.com/show/779fe3ce50b02a68e6cce9857e8ed01e.jpg"></p>    <p>跟进去,进入ApkDecoder类,decode()方法,第一个逻辑判断是否有arsc文件,否则判断是否有manifest文件,接着判断处理dex文件,最后处理原始的文件以及未知的文件,这里的未知文件为不属于apktool自定义的一些后缀,可自行添加。</p>    <p><img src="https://simg.open-open.com/show/cc97a41db1b2f6705450f0c53e598979.jpg"></p>    <p>重点的函数应该是最后一个decodeResourcesFull,其他的函数完整版注释也都有写,有兴趣可自行下载查看,这里我们跟进这个函数。</p>    <p><img src="https://simg.open-open.com/show/70aba010e362deaa698e74f4a8f9ede7.jpg"></p>    <p>这个主要的处理res、xml以及value文件以及public.xml文件,后两个函数相对简单,这里选择跟进fileDecoder.decode()</p>    <pre>  进入ResFileDecoder类,第一个decode函数主要是确定传给第二个decode函数的decoder参数,再调用相应的解码函数。  <img alt="apktool-6" src="https://simg.open-open.com/show/8f2f8cb780778bc4477472c8177c2124.jpg">  如果怕跟丢,可以直接在apktool-lib-->java-->res-->decoder里找到相对应的解码decoder。  主要有三类解码器,raw、xml、9patch  这里9patch的解析需要熟悉其使用,就不跟进去 可参考: <a href="/misc/goto?guid=4959677493531813229" id="cb_post_title_url">关于安卓9patch图片的探究 </a>  xml解码等出来后再跟  这里跟进去raw解码,其实相对简单,简单的copy,主要类为ResRawStreamDecoder  <img alt="apktool-7" src="https://simg.open-open.com/show/44fee29de57fcde5a0b25aceb49539da.jpg">    跟进路径二:  (2)、cmdDecode-->decoder.decode()-->decodeManifestFull()-->XmlPullStreamDecoder.decode()  <img alt="apktool-8" src="https://simg.open-open.com/show/332ab081a2ae94f32b97176e1778b14f.jpg"></pre>    <p>这里是判断是否有manifest.xml文件,跟进去最后还是到xml文件解码的关键代码处。这里如有按ctrl+b的话,需要按很多步骤,在完整版注释中我都标注好了”xml解码关键点”,按标注跟进去即可,也可以直接找到XmlPullStreamDecoder的decode函数。</p>    <p><img src="https://simg.open-open.com/show/0c74db4e74297f4efcad4b11340a056f.jpg"></p>    <p>可以看到这里抛出的异常是我们经常遇到的,所以,这一整个类是我们需要重点分析的地方,以及下断点调试的关键地方。这里我把原来的异常抛出更改得更加详细一点,可知是由哪个异常类抛出的异常,更加利于我们进行下断点调试。</p>    <p>这里有J2EE编程经验可能分析会相对简单,否则建议学习一下,XmlPullWrapperFactory、XmlPullParserWrapper、XmlPullParser等Java类的使用。</p>    <pre>  跟进路径三:</pre>    <pre>  (3)、cmdDecode-->decoder.decode()-->decodeSourcesSmali()-->SmaliDecoder.decode()-->baksmali.disassembleDexFile()</pre>    <pre>  判断是否有dex,下面是判断是否有多个dex,处理方式大同小异  <img alt="apktool-10" src="https://simg.open-open.com/show/2d15adf93b826b8adc2aa2485487c41f.jpg"></pre>    <p>看到这里最终还是调用了baksmali进行dex2smali的编译,关于baksmali的源码分析将会在近期发出,也请持续关注。</p>    <p><img src="https://simg.open-open.com/show/3fa95ee306e3cff1ce5eee7dc6594d6c.jpg"></p>    <p>跟进路径四:</p>    <p>以下是apkdecoder的最后几个处理函数,分析,相对简单,这里就不写了。完整版的注释分析也算相对详细了。</p>    <p><img src="https://simg.open-open.com/show/041b9b4808d8dff0ee4422fed0a80113.jpg"></p>    <p>四、回编译代码解析</p>    <pre>  cmdBuild-->Androlib(apkOptions).build()-->buildApk()</pre>    <pre>  cmdBuild函数跟上面的反编译函数差不多,先是处理选项,然后调用真正的处理函数Androlib(apkOptions).build()。  <img alt="apktool-13" src="https://simg.open-open.com/show/53fa85534671e1ae9269ae1b4ed6a2a3.jpg"></pre>    <p>主要的处理函数集如下,大部分跟进去都只是复制目录中的文件</p>    <p><img src="https://simg.open-open.com/show/92e011d4dbc773dbb512b97bcd15c50f.jpg"></p>    <p>跟进Buildapk函数,可以看到主要的处理方式是使用了aapt的工具,具体使用方法: <a href="/misc/goto?guid=4959677493614034720" rel="nofollow,noindex">android aapt用法</a></p>    <p><img src="https://simg.open-open.com/show/f884108681d6a4cd390bfe4165b386ac.jpg"></p>    <p>五、处理arsc代码解析</p>    <p>安装框架的代码这里就不写,代码注释我也有写,可自行移步。</p>    <p>这里简要写一下处理arsc文件,</p>    <p>跟进路径:cmdPublicizeResources()–>Androlib().publicizeResources()–>ARSCDecoder.decode()</p>    <p><img src="https://simg.open-open.com/show/8d7f8ace4c695083728129f6f957f5fe.jpg"></p>    <p>可以看到这里也出现了经常遇到的反编译抛出的异常,所以主要的有两个地方,一个是读取头部出错,一个是新建ARSData数据结构出错,这两步都可能是反编译手段所在的地方。需要详细的理解arsc的文件格式,具体可参考: <a href="/misc/goto?guid=4959677493689626961" rel="nofollow,noindex">手把手教你解析Resources.arsc</a></p>    <p>六、总结</p>    <p>看完sqlmap的源码,再来apktool的源码,感觉天壤之别,apktool相对来说还是很好读的,而且写的思路也很明确,每个数据结构比较易懂,命名相对好一点,反正salmap的一个自定义的dict类要弄懂就折腾了好久,还有各种奇葩的命名。</p>    <p>看完apktool的源码,最大的好处就是以后出现反编译的问题可以自己动手进行调试,同时也可以研究反调试的手段及方法。</p>    <p> </p>    <p> </p>    <p>来自:http://www.tasfa.cn/index.php/2016/08/30/apktool-source-code-analysis/</p>    <p> </p>