服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

对APK的一次插桩记录

日期: 来源:看雪学苑收集编辑:oacia

本文为看雪论坛优秀文章
看雪论坛作者ID:oacia

受好友nameless的委托,对一个名叫nokelock的apk进行插桩,希望在日志中打印出蓝牙加密包的密文,密钥与明文,由于本人是第一次对apk进行插桩,于是写了这一篇文章用以学习和记录。





什么是插桩?


依据本人的拙见,插桩就是在原来的代码中插入自己写的代码,用以打印某些想要知道的变量的值。
 
在过去学习fuzz的过程中,也有过插桩这一个概念,而过去使用的afl-fuzz是在二进制汇编代码中插桩,这一次是需要在apk中进行插桩,今日总体的插桩流程体验下来,本人明显感觉到在apk中插桩的灵活性明显跟好,而且可操作性更强。





对于apk的初步处理


需要插桩的代码位置&&需要打印的变量名称


现在我们给到的是一个base.apk
 
 
如果我们想要对代码进行插桩,那么我们首先需要知道我们要在代码的什么地方去插桩。
 
很幸运当我给到这一个apk的时候,nameless已经找到了需要插桩的代码位于com.nokelock.blelibrary.b.b中。
 
我们用jadx反编译看一下相关的java代码。
 
 
一看代码,这就是很典型的AES加密,而我们需要在日志中打印的变量也一目了然,分别是bArrbArr2instance.doFinal(bArr)。


得到apk的smali代码


假如我们想要对apk进行插桩,我们无法直接修改反编译出的java代码,而是需要修改比java代码更加底层的smali代码。
 
简单来说,java和smali代码的关系可以简单类比为c语言和汇编语言之间的关系。
 
那么如何查看smali代码呢?


简单查看smali代码


如果在jadx中,我们可以直接对相关的java代码按一下tab键,然后就能得到更加原始的smali代码。
 
 
但是需要注意的是,虽然这种方式可以查看其smali代码,但是无法重新编译并打包apk,就是说你可以看,但是你改不了。


修改smali代码并重新打包签名生成apk


这里我强烈推荐使用apk easy tool(https://www.52pojie.cn/thread-1411747-1-1.html)这个工具,相当的好用。
 
下载完成之后打开apk easy tool,然后把我们需要反编译的apk拖到这个工具里面,直接先点一下反编译,然后在点一下打开反编译目录,就可以看到apk的smali代码了。
 
 
 
之后根据我们需要插桩的代码的路径(com.nokelock.blelibrary.b.b)一级一级的点进去,就得到了可以直接编辑的smali代码。
 




如何插桩?


当我们打开b.smali文件后,通过对相同方法名和形参类型的寻找,我们可以快速定位到如下代码段;

.method public static a([B[B)[B
.locals 2

:try_start_0
new-instance v0, Ljavax/crypto/spec/SecretKeySpec;

const-string v1, "AES"

invoke-direct {v0, p1, v1}, Ljavax/crypto/spec/SecretKeySpec;-><init>([BLjava/lang/String;)V

const-string p1, "AES/ECB/NoPadding"

invoke-static {p1}, Ljavax/crypto/Cipher;->getInstance(Ljava/lang/String;)Ljavax/crypto/Cipher;

move-result-object p1

const/4 v1, 0x1

invoke-virtual {p1, v1, v0}, Ljavax/crypto/Cipher;->init(ILjava/security/Key;)V

invoke-virtual {p1, p0}, Ljavax/crypto/Cipher;->doFinal([B)[B

move-result-object p0
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

return-object p0

:catch_0
const/4 p0, 0x0

return-object p0
.end method



.method public static b([B[B)[B
.locals 2

:try_start_0
new-instance v0, Ljavax/crypto/spec/SecretKeySpec;

const-string v1, "AES"

invoke-direct {v0, p1, v1}, Ljavax/crypto/spec/SecretKeySpec;-><init>([BLjava/lang/String;)V

const-string p1, "AES/ECB/NoPadding"

invoke-static {p1}, Ljavax/crypto/Cipher;->getInstance(Ljava/lang/String;)Ljavax/crypto/Cipher;

move-result-object p1

const/4 v1, 0x2

invoke-virtual {p1, v1, v0}, Ljavax/crypto/Cipher;->init(ILjava/security/Key;)V

invoke-virtual {p1, p0}, Ljavax/crypto/Cipher;->doFinal([B)[B

move-result-object p0
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

return-object p0

:catch_0
const/4 p0, 0x0

return-object p0
.end method

初见这种smali代码可能会有手足无措的感觉,但是我自己感觉smali代码其实要比汇编更加的简单易懂。
 
回到正题,对于首次插桩,我们可以在github上下载现成的插桩代码Smali插桩自用代码库(https://github.com/SewellDinG/smaliArmory)。
 
用法很简单,首先将代码下载下来之后,将SewellDinGLog.smali直接复制到apk easy tool反编译完成后的那个smail文件夹中如图所示:
 


在哪里插桩?


ok我们重新回到b.smali中。
 
我们可以插桩的代码位置有两处(为什么是这两处,没有别的地方吗----亲身经历,要是插桩在别的地方会无法回编译报错):
在invoke-static/invoke-virtual/invoke-direct指令返回类型是V之后可以加入。
在invoke-static/invoke-virtual/invoke-direct指令返回类型不是V,那么在move-result-object命令之后可以加入。


插桩代码


invoke-static {}, LSewellDinGLog;->Log()V# 无参数,用来判断函数是否执行
invoke-static {v1}, LSewellDinGLog;->Log(Ljava/lang/Object;)V# 打印字符串
invoke-static {v1}, LSewellDinGLog;->Log([Ljava/lang/Object;)V# 打印数组

这里的插桩代码我们可以结合SewellDinGLog.java来看。

import java.util.Arrays;
import android.util.Log;

public class SewellDinGLog {

public static void Log(String tag, String msg) {//两个参数
Log.d(tag, msg);
}

public static void Log() {//无参数
Log("SewellDinG", "DeBug ...");
}

public static void Log(Object someObj) {//一个参数,打印字符串
Log("SewellDinG", someObj.toString());
}

public static void Log(Object[] someObj) {//一个参数,打印数组
Log("SewellDinG", Arrays.toString(someObj));
}

}

代码很简单,就是直接使用Log来打印变量。
 
随后我们便可以根据插桩的规则,插入相应的代码,位置类似下图:
 
 
随后我们再次打开apk easy tool,点一下回编译,在点一下打开回编译目录,就能找到最新编译成功的apk。
 


查看日志


之后使用adb命令运行该apk,然后使用命令就可以查看打印的日志。

adb logcat -s SewellDinG





意料之外的错误


但是当我将插桩后的代码发给nameless后,确实有日志打印出来,但是却是长这个样子的:

F:\platform-tools>adb logcat -s SewellDinG
--------- beginning of main
03-27 12:38:56.882 14325 14325 D SewellDinG: [B@3ad0a72
03-27 12:38:56.882 14325 14325 D SewellDinG: [B@85ec3
03-27 12:38:56.882 14325 14325 D SewellDinG: [B@e41f340
03-27 12:39:05.392 14325 14325 D SewellDinG: [B@4ee0ab4
03-27 12:39:05.392 14325 14325 D SewellDinG: [B@bd596dd
03-27 12:39:05.392 14325 14325 D SewellDinG: [B@9d6c252

我正疑惑呢难道密钥密文明文都是[B@开头的?后来才发现是SewellDinGLog.smali代码有问题。
 
首先我需要打印的是一个byte类型是数组,而打印数组的java代码是长这个样子的。

public static void Log(Object[] someObj) {//一个参数,打印数组
Log("SewellDinG", Arrays.toString(someObj));
}

这里就有问题了呀,直接使用toString方法,对于字节数组来说返回是字节数组的地址而非字节数组的值!





处理bug,重新编写代码SewellDinGLog.smali


在这个过程中,我清楚的认识到我应该修改的是smali代码,但是如何修改?
 
我认为最为简便的方法就是先编写java代码,然后再编译成smali代码,可是要怎么实现呢?

我java的运行平台都是IDEA,但是我发现SewellDinGLog.java所需要的包android.util.Log根本就没有,在网上找了找也找不到这个包,之后通过google了很久,才知道我需要安装一个Android Studio(https://developer.android.com/studio)。
 
安装好了之后,就新建一个项目,然后把要运行的代码复制粘贴进去。
 
 
要注意这里Language一定要选Java,不要选Kotlin,不然得像我一样下了很久的安装包最后发现代码根本运行不了。
 
第一次使用Android studio,得需要等大约几十分钟安装运行所需要的包。
 
随后点击File-->Settings-->Plugins,然后在插件市场搜索java2smali,安装完之后重启Android studio,然后在Build-->Compile to smali就可以直接生成smali代码了。
 
为了能够成功Log打印字节数组,我们需要对原先的SewellDinGLog.java代码进行相应的修改,然后使用Build-->Compile to smali生成smail代码。
 
修改后的java代码如下:

package com.example.newlog;

import android.util.Log;

public class SewellDinGLog {
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static void Log(String tag, String msg) {
Log.d(tag, msg);
}

public static void Log() {
Log("SewellDinG", "DeBug ...");
}

public static void Log(byte[] someObj) {
String result = bytesToHex(someObj);
Log("SewellDinG", result);
}

}

随后在同级文件夹下就会生成SewellDinGLog.smali。
 
 
这里要注意的是由于我们的SewellDinGLog.smali是放在apk easy tool反编译后的smali文件夹的根文件夹下,所以我们需要对SewellDinGLog.smali内的代码进行修改。
 
例如我这里:
 
 
那么需要将所有的Lcom/example/newlog/SewellDinGLog全部替换成LSewellDinGLog。
 
变成这样:
 
 
随后和之前的步骤一模一样,把SewellDinGLog.smali复制到smali文件夹内,然后插桩,回编译就可以了。
 
插桩后的apk我们再用jadx反编译看看。
 
发现相较之前多了SewellDinGLog.Log函数用以打印变量的值。
 
 
最后我们也是成功打印出变量的值。

F:\platform-tools>adb logcat -s SewellDinG
--------- beginning of main
03-27 17:18:08.895 31117 31117 D SewellDinG: 05010630303030303082E3C89616017D
03-27 17:18:08.895 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:08.895 31117 31117 D SewellDinG: 6629B62C88A7E50525E92C328AF258E6
03-27 17:18:10.114 31117 31117 D SewellDinG: 732F5CB22C06B0C2D0D17AD31D165805
03-27 17:18:10.114 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:10.114 31117 31117 D SewellDinG: 05020100E3C896010202000000000000
03-27 17:18:11.770 31117 31117 D SewellDinG: 530B1FCA1467A408A321E71F3D152127
03-27 17:18:11.771 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B





一个自问自答


Q: 为什么不直接使用android.util.Log中的Log函数来打印,即在需要插桩的位置插入这串代码:

invoke-static {p0, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

而是调用另一个类中的函数来打印呢?
 
A:我认为重写一个Log打印方法,灵活性将会更高,我们可以将复杂的代码先用java编写,然后再编译成smali,这样比直接用smali写代码要更简单方便,只需要插桩的位置添加一个函数方法的调用就可以了。




看雪ID:oacia

https://bbs.kanxue.com/user-home-963320.htm

*本文由看雪论坛 oacia 原创,转载请注明来自看雪社区


# 往期推荐

1、在 Windows下搭建LLVM 使用环境

2、深入学习smali语法

3、安卓加固脱壳分享

4、Flutter 逆向初探

5、一个简单实践理解栈空间转移

6、记一次某盾手游加固的脱壳与修复




球分享

球点赞

球在看

相关阅读

  • 注意,本周上班时间有变!

  • 愉快的假期已经过去今天是五一节后上班第一天值得注意的是本周工作时间有调整本周六——也就是5月6日要上班!要上班!要上班!大家调好闹钟,千万别迟到五一之后下一个节假日是端午
  • YY | 2023年4月第四周转债周报

  • 市场回顾: 上周上证指数收涨0.67%,创业板指收跌0.7%,中证转债指数收涨0.82%。值得关注的重点舆情:4月28日中共中央政治局会议、4月全国百城二手住宅价格水平。一级跟踪:上周一级
  • 2023考点|32 大豆坚果营养价值

  • 老邬备考,分高价少自2018年首期备考群以来老邬已累计培训学员数千人其中,1名注册营养师全国状元3名注册营养技师全国状元详情请戳↓↓↓2018注册营养师考试成绩公布,状元在咱家
  • 西湖景区小店宰客?误会,误会!

  • 五一假期,杭州西湖游人如织。5月1日,在翠光亭附近经营一家小店被游客投诉了。而也是这一个投诉,引发了大量网友关注,甚至有网友表示,西湖景区存在“宰客”情况。那真相到底如何?潮
  • 沙海之中,有一群铁路“高人”!

  • 4台车梯、40余名同时作业,中国铁路呼和浩特局集团有限公司包头供电段响沙湾供电车间副主任杜赫和同事们肩负的是551.24条公里接触网设备的运营检修任务。视频:央视影音编辑:谢
  • 第一次看到离婚声明还有第三个人出场的

  • 五月的第一个瓜,是洪欣和张丹峰给的。瓜虽然是糊了一些,好歹也拉拉扯扯了5年。凌晨2点43,洪欣发文,说自己和张丹峰不再是夫妻。没一会,删掉了,过了20多分钟,洪欣再次发布。没一会,还

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四
  • 美国对华2000亿关税清单,到底影响有多大?

  • 1 今天A股大跌,上证最大跌幅超过2%。直接导火索是美国证实计划对华2000亿美元产品加征25%关税。 听起来,2000亿美元数目巨大,我们来算笔账。 2000亿美元,按现在人民币汇率

最新文章

  • Frida-server运行报错问题的解决

  • 本文为看雪论坛优秀文章看雪论坛作者ID:madsu刚刚开始学Android逆向,发现Frida是个好东西,于是赶紧下载研究一番。下载源码编译,切换到最新版16.0.11, 编译之前注意先更新nodejs
  • 对APK的一次插桩记录

  • 本文为看雪论坛优秀文章看雪论坛作者ID:oacia受好友nameless的委托,对一个名叫nokelock的apk进行插桩,希望在日志中打印出蓝牙加密包的密文,密钥与明文,由于本人是第一次对apk进
  • 赋能企业安全!系统0day安全-二进制漏洞攻防

  • 二进制漏洞是可执行文件(PE、ELF文件等)因编码时考虑不周,造成软件执行了非预期的功能。由于二进制漏洞大都涉及到系统层面,所以危害程度比较高。因此,二进制漏洞的挖掘和分析就
  • 五一,他们获奖章!

  • 劳动创造幸福,实干成就伟业。2023年五一国际劳动节前夕,中华全国总工会决定,授予207个集体和1035名个人全国五一劳动奖状、奖章,授予1044个集体获全国工人先锋号。据校友总会不
  • “我从高职毕业,当了清华老师”

  • 陕西姑娘邢小颖高职毕业后,以专业排名第一的成绩,在清华大学担任实践教学指导老师。今年29岁的她,已在清华任教9年。此前,她的讲课视频在网上播放量过亿。火出圈的她,引来更多关