17.安卓逆向-frida基础-调试实战1(有 spawn 模式实例)

embedded/2024/12/23 2:30:29/

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

内容参考于:图灵Python学院

本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要盲目相信。

工具下载:

链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3

提取码:6tw3

复制这段内容后打开百度网盘手机App,操作更方便哦

上一个内容:16.安卓逆向-frida基础-HOOK类方法2

然后接着继续Frida HOOK,现在的技术的叫Frida调试,Frida调试原理就是把所有方法全部HOOK然后逐个分析

首先连接adb shell,然后运行frida server(f14)

HOOK排序算法

有的app它会把参数进行一个封装(整合)丢到一个算法里去加密,加密算法如MD5、sha、mac等,然后在加密之前会把参数进行一个处理。

然后加密算法的特点:第一点明文不一样,加密的结果也不同(MD5、sha),第二点没有解密的钥匙加密完的结果不可逆,第三点加密完的结果长度一致

在app里面对参数加密时,会先对数据进行排序,加密的原因由于结果不可逆,服务端需要接收数据复现算法来对比加密结果,排序算法可以保证不会因为参数乱序而导致结果不同

然后开始,首先双击打开 jadx-gui-1.4.7.exe并且把apk文件拖到jadx-gui-1.4.7.exe里

然后Firda HOOK脚本代码

function showStacks(){console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()
));
}
function paixusuanfa(){
var Collections = Java.use('java.util.Collections');
// Hook sort() 方法
Collections.sort.overload("java.util.List").implementation = function(list) {console.log('Hooked Collections.sort()');
console.log('List: ' + list.toString());
// 可在此处对参数进行修改或记录
// 使用 Java.cast 进行类型转换 将list转换成ArrayList类型
var res = Java.cast(list,Java.use("java.util.ArrayList"))if(res.toString().includes("userPwd")){showStacks()}
console.log('List list-->',res)
// 调用原始的 sort() 方法
return this.sort(list);
}Collections.sort.overload("java.util.List","java.util.Comparator").implementation = function(a,b) {console.log("Hooked Collections.sort()22222");var res = Java.cast(a, Java.use("java.util.ArrayList"))if(res.toString().includes("userPwd")){showStacks()}console.log('Comparator list-->',res)return    this.sort(a,b);
}}Java.perform(function (){
paixusuanfa()})

效果图:然后根据打印的栈信息,去jadx-gui-1.4.7.exe里找

首先根据栈信息得到它调用了一个onClick方法,然后就从onClick方法入手

然后点击下图红框位置

搜索 LoginActivity类,通过栈可以看出onClick方法在LoginActivity类中,所以通过搜索 LoginActivity类名来找onClikck

如下图找的类

然后双击下图红框位置

进入类中

然后找onClick方法,如下图onClick方法,然后开始分析它

通过Firda hook脚本知道onClick里面调用了login方法,如下图源码也确实调用了,然后鼠标左键双击下图红框里的login进入login方法里

然后在login方法中调用了,下图红框的方法发送了登录请求,然后再进入requestNetwork方法里

然后下图蓝框可以看到它重写的响应处理

然后通过Frida hook看出入参是在红框里组装的

然后

然后,可以看出通过排序也是可以找到入参的

然后另一个栈,可以看出与上面的栈一样

hook string字符串

很多app在参数加密的时候会把字符串转成字节,一般stirng离着加密最近,也就是说stirng的内容是已经处理好的,所以在stirng的位置往上找,会找到一些蛛丝马迹

Frida hook脚本代码

function showStacks(){console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
function hookString(){var StringClass = Java.use('java.lang.String');// Hook String 类的构造函数StringClass.getBytes.overload().implementation = function () {console.log('Original Value');// 可在此处修改传入的字符串参数var res = this.getBytes();var newString = StringClass.$new(res)// 输出修改后的值console.log('Modified Value: ' + newString);return res;}}Java.perform(function (){
hookString()})

效果图:

打印堆栈的写法

function showStacks(){console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
function hookString(){var StringClass = Java.use('java.lang.String');// Hook String 类的构造函数StringClass.getBytes.overload().implementation = function () {console.log('Original Value');// 可在此处修改传入的字符串参数var res = this.getBytes();var newString = StringClass.$new(res)// 输出修改后的值console.log('Modified Value: ' + newString);if (newString.toString().includes('username')){// 字符串中包含 username 就打印堆栈showStacks()}return res;}}Java.perform(function (){
hookString()})

分析栈

通过上方的栈看源码,下图红框位置是md5加密

image-20241002140212571

然后进入md5方法,可以看到下图红框位置它调用了getBytes方法,在加密之前获取了字符串的字节(或者说是字符),基本上所有md5的都会这样写,md5要的参数就是字节,对于安全方面来说下图中的md5的写法需要改一下,自己实现字节转换,不要用它提供好的方法,避免被人用上方的Frida hook脚本拦截

Stirng还有一个静态的getByte方法,如下图红框

function showStacks(){console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
function hookString(){var StringClass = Java.use('java.lang.String');// Hook String 类的构造函数StringClass.getBytes.overload().implementation = function () {console.log('Original Value');// 可在此处修改传入的字符串参数var res = this.getBytes();var newString = StringClass.$new(res)// 输出修改后的值console.log('Modified Value: ' + newString);if (newString.toString().includes('username')){// 字符串中包含 username 就打印堆栈showStacks()}return res;}// Hook String 类的静态方法StringClass.getBytes.overload('java.lang.String').implementation = function(obj) {console.log('Hooked String.valueOf()');// 可在此处修改传入的对象参数showStacks()var res = this.getBytes(obj);var newString = StringClass.$new(res,obj)// 输出修改后的结果console.log('getBytes: ' + newString)return res}}Java.perform(function (){
hookString()})

效果图:可以看到它也是可以hook到请求入参的

hook StringBuilder字符串

StringBuilder也是一种数据存放的容器

Frida HOOK脚本代码

function showStacks(){console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()
));
}
function d(){
// 获取 StringBuilder 类并定义需要 Hook 的方法名
var stringBuilderClass = Java.use("java.lang.StringBuilder");
stringBuilderClass.toString.implementation = function (){var res = this.toString.apply(this,arguments)if (res == ""){showStacks()console.log('tostring is called ',res)}console.log('tostring is called ',res)return res
}}Java.perform(function (){
d()})

效果图:注意下图红框接口返回的是加密的数据(密文)现在它是明文,这样通过打印栈信息可以找到它解密的代码

然后还可以看到请求入参的明文和响应的密文,可以发现StringBuilder也可以覆盖很多东西,所以直接把所有方法所有类全HOOK掉就一定可以找到漏洞

HOOK点击按钮进行定位

Andriod sdk里有一个工具叫做 uiautomatorviewer.bat,如下图红框

双击上图红框里文件运行之后,会出现下图中的内容,然后点击下图红框里的按钮,会出错

下图出错的原因是,安装了多个Android SDK当前目录未配置环境变量,意思就是找错目录了

需要用环境变量里的那个目录,如下图是Path的环境变量的内容,需要在这里面打开 uiautomatorviewer.bat才行

然后下图的错是因为,uiautomatorviewer.bat不维护了正常版本的会有问题,网上有大神修改了,需要下载修改的uiautomatorviewer.bat才行,已经放到百度网盘了

如下图:下载下图红框里的东西

上图红框里的东西下载完,然后把里面的tool进行复制,然后把原本Android SDK里的tool删了(一定要删了或者改个名)然后把复制的tool粘贴过去,如下图

然后再次双击 uiautomatorviewer.bat 运行

然后再点下图红框按钮连接手机就可以了,它可以看组件的id,如何使用继续往下看

然后鼠标点击,下图红框位置后,就可以在下图蓝框位置看到它的id(下图也就是输入框组件的id)

主要是看它按钮的id,如下图按钮的id是btn_login,找到了它的id就可以对它进行hook

Frida Hook脚本代码:它是通过hook绑定事件的setOnClickListener方法来实现,它只能通过Frida重启app的方式来拦截

function showStacks(){console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
function d(){
var btn_login_id = Java.use("com.dodonew.online.R$id").btn_login.value;console.log('id:',btn_login_id)var View = Java.use('android.view.View');View.setOnClickListener.implementation = function(listener) {console.log(this.getId(),"22222222222")if (this.getId() === btn_login_id){showStacks()console.log("view.id-->" + this.getId())}// 调用原始的setOnClickListener方法return this.setOnClickListener(listener);};}Java.perform(function (){
d()})

下图通过红框里绑定了点击事件,处理点击事件的函数是通过实现下图蓝框里的接口来的,也就是setOnClickListener方法绑定的是当前类(this就是当前类)

然后在下图中可以看出 OnClickListener 接口只有一个onClick方法,所以源码中 LoginActivity类就一定会实现onClick方法并且在点击空间的时候会执行onClick方法

也就是会执行下图红框的代码,这就是通过id来hook看源码的思路

强制重启hook的Frida命令:frida -Uf com.dodonew.online -l ./xxx/js,也就是使用 spawn 模式,执行之后app会关闭重启,重启时会处于卡死状态,需要输入 %resume 让app运行起来

执行的指令

效果图:


img


http://www.ppmy.cn/embedded/121583.html

相关文章

uniapp 知识点

自定义导航 在page.json navigationstyle":"custom"navigateTo传参 页面传参只能onLoad(option)里面拿 px和upx的关系 在750设计图中,1px1upx 路由 navigateBack返回上一页 重定向 其实就是把当前页面干掉了 公共组件和页面共同点 computed,watc…

batch和momentum

🚀 机器学习系列前期回顾 1、初识机器学习 2、线性模型到神经网络 3、local minima的问题如何解决 🚀在初识机器学习中,了解了机器学习是如何工作的并引入了线性模型,在线性模型到神经网络这节,将线性模型进一步改进为…

INTO:Web3世界的“价值引力场”

在Web3的宇宙中,一股强大的引力正在重塑整个数字世界的格局。这股引力,来自一个名为INTO的“超级连接器”。作为Web3社交领域的先锋,INTO正在用一种前所未有的方式重构整个产业链的价值体系。它不再满足于单一领域的创新,而是大胆…

集师专属心理咨询 心理培训 心理知识服务小程序搭建 专属知识付费小程序搭建

集师专属心理咨询 心理培训 心理知识服务小程序搭建 专属知识付费小程序搭建 1. 心理咨询知识服务小程序功能图解 2. 心理咨询知识服务小程序解决方案及运营服务模式图解 3. 心理咨询行业为什么要搭建自己的专属知识付费小程序平台图解 4. 心理咨询培训知识小程序人人可变现图…

Rust和Go谁会更胜一筹

在国内,我认为Go语言会成为未来的主流,因为国内程序员号称码农,比较适合搬砖,而Rust对心智要求太高了,不适合搬砖。 就个人经验来看,Go语言简单,下限低,没有什么心智成本&#xff0c…

代码随想录 99. 岛屿数量

99. 岛屿数量 #include<bits/stdc.h> using namespace std;void dfs(vector<vector<int>>& mp, vector<vector<int>>& visit, int y, int x){if (visit[y][x] 1 || mp[y][x] 0) return;visit[y][x] 1;if (y > 0) dfs(mp, visit, …

OpenCV库 详细常见操作

在PyCharm中使用OpenCV时&#xff0c;可以访问OpenCV库提供的丰富函数来进行图像处理和计算机视觉任务。以下是一些常用的OpenCV库函数及其简要说明&#xff1a; 一、图像读取与显示 cv2.imread()&#xff1a;读取图像文件。cv2.imshow()&#xff1a;在一个窗口中显示图像。c…

Java中使用接口实现回调函数的详解与示例

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…