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

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

内容参考于:图灵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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值