带你开发一款给Apk中自己主动注入代码工具icodetools(开凿篇)

一、前言

从这篇開始咋们開始一个全新的静态方式逆向工具icodetools的实现过程。这个也是我自己第一次写的个人认为比較实用的小工具,特别是在静态方式逆向apk找关键点的时候。兴许会分为三篇来具体介绍这个工具实现:

第一篇:开凿篇,简介实现原理以及简单的初次方案实现简单的apk注入代码功能

第二篇:填坑篇。这一篇是在前一篇的基础上对工具的优化,能够应对市面上大部分的apk代码注入功能实现

第三篇:生产篇。这一篇是在前两篇的基础上利用这个工具来实际操刀怎样进行高速定位应用的关键方法功能

还记得那一年咋们 静态方式破解应用,为了更好的追踪代码位置。手动反编译成smali文件,然后加入smali日志代码,在回编译。查看日志信息来定位关键点。那种操作如今回忆是苦不堪言。操作非常复杂。

那么就尝试想想假设有一个工具能够在自己主动为每一个方法注入日志代码。这样就能够非常高速的定位到我们想要的方法,所以本文就来介绍一下这个工具的实现原理,我将其命名为icodetools

二、实现方案

首先咋们来看一下具体实现原理吧,这个工具终于的形态应该是这种,就是输入一个apk,然后在为apk中每一个类的每一个方法加入一段打印此方法的堆栈信息日志。然后在又一次签名打包成新的apk。所以这个过程中我们最关键的地方就是怎样把日志代码插入到已经编译好的apk中。我们可能想到的有两个方案:

第一个方案:首先利用apktool进行反编译成smali文件,然后解析smali文件找到每一个方法的位置,加入指定smali日志代码。那么这里有一个非常大的问题,就是怎样分析smali文件。怎样定位到每一个方法?这个过程工作量就比較大了。所以这个方法就废弃了。

第二个方案:利用dex2jar获取到apk中的dex转化之后的jar文件。然后在解析jar文件获取到每一个class文件,解析class文件进行方法的信息获取。

这里会发现这个方法非常靠谱。由于我们解析class文件比解析smali文件方便多了。并且在这个过程中会发现有一个更大的惊喜,就是dex2jar这个工具是开源的。事实上内部实现原理就是解析dex文件格式,然后借助asm工具将其变成class文件的,这里又出现了一个非常重要的工具asm,这个工具以下会具体介绍。

说明:

1》这里非常感谢dex2jar的作者Claud大神的开源精神。这个工具的地址:https://github.com/pxb1988/dex2jar,是纯java代码,所以大家一定要先解读这个工具源代码,内部实现原理自己研读,本文不会具体介绍的。

2》这里有的同学会想到,能不能直接解析dex文件格式,然后在找到每一个类的每一个方法加入日志信息,尽管我们在前面有具体介绍dex文件格式:Dex文件格式具体解释,可是假设想在每一个类每一个方法中加入日志代码这个工作量感觉比操作smali还要复杂,所以直接将其转化成class文件进行操作就非常方便了,由于我们有asm工具。

三、方案实现

上面已经探讨了方案了,在上面提到了非常多次一个非常重要的工具就是asm,那么这个工具究竟是干嘛的呢?这个工具非常实用。他的表现之处在JavaWeb开发中的Spring框架就实用到。能够动态的解析class文件,然后能够操作这个类,比方加入类成员,方法等等操作。所以以下不多解释了,直接用一个简单的案例来看看他的强大之处。我们实现给一个类加入一个成员字段,方法,给每一个方法调用前加入一行代码。

第一、asm库基本使用

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

这里借助ClassReader来读取一个类,使用ClassVisitor来进行类信息操作,ClassWriter将操作完之后的类写入文件里

第二、加入类成员字段

上面看到了一个基本的类ClassVistor。他主要就是用来操作一个类:

这里看到的是继承了ClassAdapter。然后在构造方法中能够加入类成员信息包括字段。方法等,这里我们加入一个字段mJW。类型是String的。看看怎样加入的:

借助ClassVisitor的visitField方法就能够进行字段的加入了。然后我们执行程序之后,使用JD-GUI工具查看保存本地的class文件信息:

看到了吧,这里成功的定义了一个字段mJW。

第三、为类的全部方法前加入代码

这里我们须要借助另外一个类了MethodVisitor了,他是用来操作方法信息的:

在ClassAdapter的visitMethod回调方法中能够获取方法信息,然后进行操作:

在visitCode回调方法中利用MethodVisitor開始加入代码:

这里看到能够利用visitFieldInsn方法方法System类的静态变量out,然后在使用visitLdcInsn从常量池中获取值,最后在利用visitMethodInsn方法来调用PrintStream类的成员方法println来信息打印,执行程序之后继续借助JD-GUI来查看class文件:

看到了,类中全部的方法前面都被加了一行打印代码。

注意:有的同学发现了,上面那个加入代码怎么得到呢?难道真的要记住那么多api去加入吗?事实上不用那么复杂。Eclipse有一个插件Bytecode,能够把Java代码自己主动生成相似于上面的代码。咋们之后手动拷贝一下就好了!工具后面会说。

第四、为类加入成员方法

以下在来看最后一个操作吧,就是给类中加入一个成员方法,有了上面的操作之后我们应该知道。假设要操作类就要借助ClassVisitor类。要是操作方法就须要借助MethodVisitor类,那么这里为类加入成员方法,借助ClassVistor类来进行操作了,可是在操作之前咋们得先搞好一个工具Bytecode,这个是Eclipse插件。安装非常easy:

安装完毕之后,能够打开视图栏:

然后选择Java中的bytecode视图就能够了:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

以下咋们首先在一个类中编写好我们想要加入的方法代码,然后点击Bytecode视图卡片就能够看到相应的asm代码:

看到了吧。这样操作是不是如此简单,我们能够把这段asm代码直接复制到AsmUtils中:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

然后在ClassVisitor的构造方法中直接调用这种方法就能够了:

再次执行程序之后,使用JD-GUI查看类信息:

成功的加入了printStackTrace方法了。就是如此简单。借助Eclipse的强大工具Bytecode就能够了,以后都不要在自己去调用asm库的api去手动编写了。这个工具太好了得记住它。

四、工具案例实践

上面就介绍完了怎样操作一个类和方法,给类加入字段,方法,在每一个方法之前加入一行代码。

以下就得进入本文的主题了,怎样给apk应用中每一个类中的每一个方法加入一行打印日志信息。

在開始的时候我们有了方法,就是借助工具dex2jar源代码。他内部也是解析dex格式。然后利用asm将其信息变成一个class文件的,那么我们仅仅要在这个过程中得到ClassVisitor和MethodVisitor这两个对象,就能够尽情的干非常多事了。所以第一步你一定要先看懂dex2jar的源代码。这里我不会对源代码进行具体分析了,用过dex2jar工具的都知道。找入口非常easy,直接看他的一个d2j-dex2jar.bat脚本信息:

Dex2jarCmd就是工具的入口类:

然后分析代码,会发现处理的核心类是Dex2jar类:

这里会看到能够拿到ClassVisitor类对象的。那么我就能够加入打印堆栈信息的方法了:

这里须要注意的是打印消息用了Android的Log.d方法。然后在每一个方法调用之前在调用这个打印方法:

这里过滤依旧过滤了构造方法和静态代码块方法。

事实上我们就须要这么做就能够了,以下咋们就用一个简单的Apk来做一下实验,咋们把apk中的classes.dex文件解压出来。为了简单直接跑这个dex2jar工具,能够在Dex2jarCmd開始处构造一个简单的命令:

输入的dex文件为指定文件夹的,输出的jar文件也是指定文件夹的:

然后咋们就能够执行程序了。执行结束之后我们得到了一个classes.jar文件,能够使用JD-GUI进行查看:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

到这里我们就成功的。把apk中的classes.dex中的每一个类每一个方法加入了我们自己的打印消息的代码了,已经成功一大半了,以下为了验证效果。咋们还得把classes.jar转成dex,在弄到apk中执行看效果。这个过程就简单了,利用系统的dx命令,把classes.jar在变成classes.dex文件:

然后在把这个classes.dex文件塞到apk中,只是这时候得又一次签名了。能够借助jarsigner工具:

jarsigner -verbose -keystore cyy_game.keystore -storepass cyy1888 -signedjar signed.apk unsigned.apk cyy_game.keystore -digestalg SHA1 -sigalg MD5withRSA

然后咋们就能够安装apk。然后開始执行效果:

看到效果了吧。表示成功的不要不要的。

有点小兴奋,通过栈信息加上我们出发一个事件之后就能够定位这个事件的方法了。

对于我们在使用hook的时候寻找hook点非常重要。

五、技术总结

到这里我们本文的知识点就算结束了,可是整个工具开发并没有结束。以下就来总结一下本文涉及到的知识点:

1、学会了利用asm库来操作类,实现加入字段,方法等操作。

2、了解到了Eclipse的一个强大插件Bytecode,能够高速得到java代码相应的asm代码

3、了解了dex2jar的实现原理,内部也是借助于asm来进行操作的

事实上本文的这个自己主动注入代码工具绝大部分是借助了dex2jar这个工具的,我们仅仅是在适当的地方加入了我们想要的信息代码。在操作类的时候仅仅要有ClassVisitor对象就能够操作类,MethodVisitor对象就能够操作方法了。

而在dex2jar中正好有这两个对象,所以我们实际要操作的内容并不复杂。当我们使用通过改动之后的dex2jar得到了classes.jar之后,在用dx工具将其还原成classes.dex文件,在放到apk中进行重签名验证。

六、遗留的问题

假设到这里有的同学认为这个是挺简单的。那事实上就错了,由于開始的时候我已经说了后面另一个填坑篇文章,在那篇文章会具体说明在实际操作其它企业app会遇到哪些问题。我们须要继续优化这个工具,同一时候对这个工具最好能够做到一键化工作,所以我们须要解决这几个问题:

1、上面看到我们是为每一个类加入了一个打印栈信息的方法。那么就有一个非常大的问题,假设一个dex文件过大,包括的类非常多,那么就是添加了非常多方法,对于dx进行转化的时候会发现方法数超了。

2、在实际的apk操作过程中会发如今每一个方法中插入日志之后。当你启动app的时候那日志差点儿会被霸屏的。并且一个庞大的app内部调用的方法非常多,导致应用会出现无响应状态。所以咋们得弄个开关以及想在哪些方法中加入。

3、上面在看到在整个过程中,先把dex转成jar,然后再把jar转成dex。在放到apk中,在签名,整个过程我们都是手动操作的。显得非常的费劲,所以我们还得优化这个工作。做到真正意义上的一键化,输入一个apk,输入就是已经加入日志信息的apk就能够了。

所以后面一个填坑篇文章会有非常多工作要做的。当坑都填完了,咋们就得实际生产拿一些app进行实战操刀了。最后在来看一下我总结的一张原理图吧(能够点击查看高清大图):

严重说明:

===》本文介绍的是基础篇,能够看到我们是大致走通了整个流程。可是这个和终于的工具实现差的非常多,兴许还有非常多问题须要解决,所以重点事实上在下一篇中,那里会去解决在实际使用过程中遇到的各个问题。以及最重要的就是怎样把全部的步骤连贯起来,一键化开发完好。一定要记得看下一篇内容,那里才是主战场!

===》一定要自己去github上下载dex2jar的源代码,自己先调试走通程序。不然一切都是枉然,由于这个工具是纯Java编写的,代码不是非常多。所以难度不大。

七、总结

对于这个自己主动插入代码的工具我个人认为有需求採取这么干的,由于曾经遭受过那种手动注入代码的痛苦,可是从本文的工具能够看到。对于一些加固app是无能无力的。而工具的理念来源是美团的一个热修复框架Robust的。

关于源代码的话等后面都介绍完了。我把我写的部分公开。可是你还是得先去看看dex2jar的源代码。又開始了写这种文章。每次写完感觉自己身体被掏空了一样。多多点赞。打赏就在好只是了。

很多其它内容:点击这里

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

扫一扫加小编微信
加入时注明:“编码漂亮”否则不予通过!



watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" style="max-width: 100%; border: none; max-height: 100%;" />

时间: 2024-10-06 15:53:11

带你开发一款给Apk中自己主动注入代码工具icodetools(开凿篇)的相关文章

带你开发一款给Apk中自动注入代码工具icodetools(开凿篇)

一.前言 从这篇开始咋们开始一个全新的静态方式逆向工具icodetools的实现过程,这个也是我自己第一次写的个人觉得比较有用的小工具,特别是在静态方式逆向apk找关键点的时候,后续会分为三篇来详细介绍这个工具实现: 第一篇:开凿篇,简单介绍实现原理以及简单的初次方案实现简单的apk注入代码功能 第二篇:填坑篇,这一篇是在前一篇的基础上对工具的优化,可以应对市面上大部分的apk代码注入功能实现 第三篇:生产篇,这一篇是在前两篇的基础上利用这个工具来实际操刀如何进行快速定位应用的关键方法功能 还记

带你开发一款给Apk中自动注入代码工具icodetools(完善篇)

一.前言 在前面已经介绍完了 自动给apk中注入日志代码工具icodetools原理了,在那里我们曾经说过其实离真正的可使用价值有点距离,本篇就对这个工具进行一些优化,让其真正意义上开始能工作量产.当时在前面一篇文章中说到遗留的三个主要问题: 第一个问题:对每个类中都添加一个静态打印方法堆栈信息的方法,这样会导致有些应用的dex过大,方法数超了问题 第二个问题:在从输入一个apk到给每个类中的每个方法添加日志代码然后在签名输出最终的apk,这个过程其实很多步,但是我们之前都是手动的去进行操作,非

Android 中带你开发一款自动爆破签名校验工具 kstools

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Android中带你开发一款自动爆破签名校验工具kstools - 生死看淡,不服就干! - 博客频道 - CSDN.NET 生死看淡,不服就干! http://www.wjdiankong.cn 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &n

Android中带你开发一款自动爆破签名校验工具kstools

一.技术回顾 为了安全起见,一些应用会利用自身的签名信息对应用做一层防护,为了防止应用被二次打包操作,在之前已经介绍了很多关于应用签名校验爆破的方法,一条基本原则不能忘:全局搜索"signature"字符串,这里可以在Jadx打开apk搜索,也可以在IDA中打开so搜索都可以.找到这信息之后可以手动的修改校验逻辑,但是这个法则有个问题,就是如果一个应用在代码中很多地方都做了签名校验,比如以前介绍的一篇爆破游戏文章:Android中爆破应用签名信息案例分析,那时候就会发现,应用在很多地方

Android插件化开发---运行未安装apk中的Service

如果你还不知道什么叫插件化开发,那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从整体角度分析了一下Android插件化开发的几个难点与动态加载没有被安装的apk中的Activity和资源的方法.其实一般的插件开发主要也就是加载个Activity,读取一些资源图片之类的.但是总有遇到特殊情况的时候,比如加载Service. 要动态加载Service,有两种思路:一是通过NDK的形式,将Service通过C++运行起来(这种方法我没有尝试,只听群里的朋友说实现

[译]async/await中使用阻塞式代码导致死锁

原文:[译]async/await中使用阻塞式代码导致死锁 这篇博文主要是讲解在async/await中使用阻塞式代码导致死锁的问题,以及如何避免出现这种死锁.内容主要是从作者Stephen Cleary的两篇博文中翻译过来. 原文1:Don'tBlock on Async Code 原文2:why the AspNetSynchronizationContext was removed 示例代码:async_await中使用阻塞式代码导致死锁.rar 一.async/await 异步代码运行流

[翔哥高手无敌之路]0-002.如何提取apk中的信息?

面对一款apk软件,我们如何去获取它的信息,如何获取它的版本号,包名,或者ID,用户权限,这些信息都隐藏在apk包中的AndroidManifest.xml文件中,解开它我们就能获取任何想要的信息.但是当解压apk之后却发现AndroidManifest.xml是一堆看不懂的数字,那该怎么才能获得信息呢?我们不妨做一个款工具来轻松达到目的. 所需条件 安装java环境 拥有AXMLPrinter2.jar文件 获取原理 将apk解压之后,打开cmd,输入java -jar 然后将AXMLPrin

Android内核开发:在源码树中添加新的app应用

本文是<Android内核开发>系列的第十二篇文章,上一篇文章介绍了如何从源码中删除出厂的app应用,本文则在此基础上,详细介绍一下如何在Android内核源码树中添加一个新的app应用. 网上也有介绍怎么在源码中添加新的app应用的博文,但大都数只介绍了不含有jni本地代码的app的添加方法,本文会更加全面地介绍三种不同类型的app应用如何添加到Android内核源码树中编译. 假设新的应用名字叫:HelloWorld,并且已经在Eclipse或者Android Studio中编译和调试通过

使用Cocos开发一款简单的3D VR抓钱游戏

使用Cocos开发一款简单的3D VR抓钱游戏 最近VR成为了一个新兴的热点,很多以前从事游戏开发的团队都在关注这个方向.如何在VR时代来临之际快速的掌握开发VR游戏的方法,这对于很多中小团队来说,是一个要考虑的问题. 目前市面上有很多3D引擎已经开始支持VR功能.特别是虚幻,Unity等引擎对于VR这个领域都非常重视,但是国内这几年有大量的手游团队在使用Cocos2d-x来开发游戏项目,现有人员的的经验对于游戏开发非常宝贵,更何况目前VR领域并未出现很好的CP盈利案例.短期内贸然转型,放弃现有