首页
社区
课程
招聘
[原创]对某apk的一次插桩记录
发表于: 2023-3-31 22:26 36539

[原创]对某apk的一次插桩记录

2023-3-31 22:26
36539

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

依据本人的拙见,插桩就是在原有的代码中插入自己写的代码,用以打印某些想要知道的变量的值。当然了,插入的代码也可以在原有代码的基础上,为app增加各种各样的额外功能。

在过去学习fuzz的过程中,也有过插桩这一个概念,而过去使用的afl-fuzz是在二进制汇编代码中插桩,这一次是需要在apk中进行插桩,今日总体的插桩流程体验下来,本人明显感觉到在apk中插桩的灵活性明显跟好,而且可操作性更强.

现在我们给到的是一个base.apk

image-20230327184321422

如果我们想要对代码进行插桩,那么我们首先需要知道我们要在代码的什么地方去插桩

很幸运当我给到这一个apk的时候,nameless已经找到了需要插桩的代码位于com.nokelock.blelibrary.b.b

我们用jadx反编译看一下相关的java代码

image-20230327184914926

一看代码,这就是很典型的AES加密,而我们需要在日志中打印的变量也一目了然,分别是bArr,bArr2instance.doFinal(bArr)

假如我们想要对apk进行插桩,我们无法直接修改反编译出的java代码,而是需要修改比java代码更加底层的smali代码

简单来说,java和smali代码的关系可以简单类比为c语言和汇编语言之间的关系

那么如何查看smali代码呢?

如果在jadx中,我们可以直接对相关的java代码按一下tab键,然后就能得到更加原始的smali代码

image-20230327185747093

但是需要注意的是,虽然这种方式可以查看其smali代码,但是无法重新编译并打包apk,就是说你可以看,但是你改不了:]

这里我强烈推荐使用apk easy tool这个工具,问就是相当的好用:)

apk easy tool的下载地址:https://www.52pojie.cn/thread-1411747-1-1.html

下载完成之后打开apk easy tool,然后把我们需要反编译的apk拖到这个工具里面,直接先点一下反编译,然后在点一下打开反编译目录,就可以看到apk的smali代码了

image-20230327190347337

image-20230327190543349

之后根据我们需要插桩的代码的路径(com.nokelock.blelibrary.b.b)一级一级的点进去,就得到了可以直接编辑的smali代码

image-20230327190738365

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

初见这种smali代码可能会有手足无措的感觉,但是我自己感觉smali代码其实要比汇编更加的简单易懂

回到正题,对于首次插桩,我们可以在github上下载现成的插桩代码 Smali插桩自用代码库

用法很简单,首先将代码下载下来之后,将SewellDinGLog.smali直接复制到apk easy tool反编译完成后的那个smail文件夹中如图所示

image-20230327192145198

ok我们重新回到b.smali

我们可以插桩的代码位置有两处(为什么是这两处!?没有别的地方吗----亲身经历,要是插桩在别的地方会无法回编译报错:0)

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

代码很简单,就是直接使用Log来打印变量

随后我们便可以根据插桩的规则,插入相应的代码,位置类似下图

image-20230327193625493

随后我们再次打开apk easy tool,点一下回编译,在点一下打开回编译目录,就能找到最新编译成功的apk

image-20230327193848391

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

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

我正疑惑呢难道密钥密文明文都是[B@开头的?后来才发现是SewellDinGLog.smali代码有问题

首先我需要打印的是一个byte类型是数组,而打印数组的java代码是长这个样子的

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

在这个过程中,我清楚的认识到我应该修改的是smali代码,但是如何修改?

我认为最为简便的方法就是先编写java代码,然后再编译成smali代码,可是要怎么实现呢?
我java的运行平台都是IDEA,但是我发现SewellDinGLog.java所需要的包android.util.Log根本就没有,在网上找了找也找不到这个包,之后通过google了很久,才知道我需要安装一个Android Studio

安装好了之后,就新建一个项目,然后把要运行的代码复制粘贴进去

image-20230327195721325

要注意这里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代码如下

随后在同级文件夹下就会生成SewellDinGLog.smali

image-20230327200425926

这里要注意的是由于我们的SewellDinGLog.smali是放在apk easy tool反编译后的smali文件夹的根文件夹下,所以我们需要对SewellDinGLog.smali内的代码进行修改

例如我这里

image-20230327202329460

那么需要将所有的Lcom/example/newlog/SewellDinGLog全部替换成LSewellDinGLog

变成这样

image-20230327202432870

随后和之前的步骤一模一样,把SewellDinGLog.smali复制到smali文件夹内,然后插桩,回编译就可以了

插桩后的apk我们再用jadx反编译看看

发现相较之前多了SewellDinGLog.Log函数用以打印变量的值

image-20230331194727784

最后我们也是成功打印出变量的值

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

,而是调用另一个类中的函数来打印呢?

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

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));
    }
 
}
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 ...");
    }

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2023-10-16 21:03 被oacia编辑 ,原因: 添加了文章中所使用到的apk
上传的附件:
收藏
免费 9
支持
分享
最新回复 (23)
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
apk easy tool,又是新的工具,思路不错的
2023-4-1 13:58
1
雪    币: 1333
活跃值: (1939)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这样的话用mt的注入日志打印会方便一点
2023-4-1 15:17
0
雪    币: 514
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
apk easy tool 发下呗。
2023-4-1 16:54
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
5
https://www.52pojie.cn/thread-1411747-1-1.html这里就可以下载了
2023-4-2 01:52
1
雪    币: 922
活跃值: (1803)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
能否分享base.apk捏
2023-4-13 21:09
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
插桩工具!apk easy tool
2023-4-14 22:06
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
8
NYSECbao 能否分享base.apk捏
可以的,链接在这个地方
链接: https://pan.baidu.com/s/1GHFYCd6FL6mnU3MgIsHphA?pwd=irmt 提取码: irmt 复制这段内容后打开百度网盘手机App,操作更方便哦
2023-4-23 16:12
0
雪    币: 94
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这个工具兼容性好像有问题。你下载一个谷歌浏览器,反编译后,一个代码不动,直接重新编译,就出错
2023-4-28 15:22
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
10
dico 这个工具兼容性好像有问题。你下载一个谷歌浏览器,反编译后,一个代码不动,直接重新编译,就出错
刚刚尝试一下,确实回编译是失败的,报错日志为error: Resource entry APKTOOL_DUPLICATE_attr_0x7f05002d already has bag item @null.,我在Apktool的github issue中找到了与你遇到相同情况的issue,https://github.com/iBotPeaches/Apktool/issues/3010,作者也对此进行了回复,你可以按照作者的回复重新选择apktool的版本后再反编译,希望这对你有帮助!
2023-4-28 19:21
0
雪    币: 94
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
oacia 刚刚尝试一下,确实回编译是失败的,报错日志为error: Resource entry APKTOOL_DUPLICATE_attr_0x7f05002d already has bag item @ ...
感谢您的热心回复和细心帮助!我去试试
2023-5-9 19:53
0
雪    币: 2519
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
写的不错,挺优秀
2023-5-10 09:01
0
雪    币: 94
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
oacia 刚刚尝试一下,确实回编译是失败的,报错日志为error: Resource entry APKTOOL_DUPLICATE_attr_0x7f05002d already has bag item @ ...
刚刚试了下,用最新的APKTOOL还是不行。编译还是出错
attrs.xml:52: error: duplicate symbol '@null'.
2023-5-10 22:04
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
14
dico 刚刚试了下,用最新的APKTOOL还是不行。编译还是出错 attrs.xml:52: error: duplicate symbol '@null'.
确实如此,我编译了最新版本的apktool-2.7.1-8d222d-SNAPSHOT-small.jar仍然有该报错存在,可以确定apktool的作者还并未对该问题进行修复,你可以等待作者发布最新版本的apktool后再次进行尝试,或者自行编译chrome,参考chromium官方文档https://chromium.googlesource.com/chromium/src.git/+/HEAD/docs/README.md
2023-5-11 12:10
1
雪    币: 94
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
其实很多都这样,例如WHATSAPP、抖音这些都是。现在APKTOOL对于新版本的很多著名APP都效果不好了。回编译都费劲
2023-5-24 15:31
0
雪    币: 763
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16

新手很疑惑,你插入的代码其中invoke-static {p0}这里是p0,是不是打印p0的值?而你插入代码的位置,并没有p0的值,上面只有v0,p1和v1。实在不明白,为什么要插入在这个位置?为什么是p0?

2023-6-14 16:33
0
雪    币: 199
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
apk easy tool 好像不是开源的? github搜了下没有
2023-6-14 18:57
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
18
ok_yuwang 新手很疑惑,你插入的代码其中invoke-static {p0}这里是p0,是不是打印p0的值?而你插入代码的位置,并没有p0的值,上面只有v0,p1和v1。实在不明白,为什么要插入在这个位置?为什么 ...
在smali的语法中,根据p命令法,在非static函数中,p0代指“this”,p1表示函数的第一个参数,p2表示第二个参数;而在static函数中p0表示函数的第一个参数,p1表示函数的第二个参数,你可以在上图的285行看到这个函数是static类型的,所以这里传入的p0,打印的其实是这个函数的第一个参数。而为什么要插入在这个位置,我还是以这张图片内的代码来举例,你可以看到从第286行到291行这几行smali代码,其作用是为293行的这个函数调用去准备参数,如果不在293行的后面一行插入代码,而是在之前插入代码,不就把本应该传给293行的这个函数的参数给“抢走了”吗,这样就会导致程序执行的过程中产生了报错。
2023-6-14 19:23
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
19
mb_rwmcnzwp apk easy tool 好像不是开源的? github搜了下没有
apk easy tool可以在这里进行下载https://www.52pojie.cn/thread-1411747-1-1.html,实际上这个工具的本质是对apktool等开源工具做了整合。
2023-6-14 19:30
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
oacia 可以的,链接在这个地方 链接: https://pan.baidu.com/s/1GHFYCd6FL6mnU3MgIsHphA?pwd=irmt 提取码: irmt 复制这段内容后打开百度网盘手机A ...
可以分享下 APK 吗
2023-10-16 17:34
0
雪    币: 3505
活跃值: (4748)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
21
0xuu 可以分享下 APK 吗
没想到没有把分享链接设置成永久的我把这个apk传到文章末尾的附件里面了
2023-10-16 21:05
1
雪    币: 163
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
很强
2023-10-17 02:28
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
oacia 没想到没有把分享链接设置成永久的[em_78]我把这个apk传到文章末尾的附件里面了[em_71]
多谢
2023-10-18 09:56
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
支持一下
2023-10-18 15:14
0
游客
登录 | 注册 方可回帖
返回
//