# 雪豹速清_2.9.0 逆向思路
# 雪豹速清_2.9.0 逆向思路
## 一、去除更新提示
当时刚下载的时候在期末考,没时间分析。今天刚打开软件就跳出个更新弹窗,正好来分析一下
首先用MT管理器的Activity记录功能获取到这个更新弹窗的类名为:
```java
com.afollestad.materialdialogs.MaterialDialog
```
弹窗之所以会跳出是因为调用了show()方法,再想想为什么会跳出更新弹窗
很大可能是在app`刚启动的时候,进行是否有新版本的判断`,如果有新版本就调用MaterialDialog的show()方法来跳出更新弹窗
所以HOOK MaterialDialog的show()方法,当show()方法被调用时打印当前堆栈看看show()方法的调用链:
```javascript
//打印堆栈
function showStacks() {
console.log(
Java.use("android.util.Log")
.getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
}
//HOOK MaterialDialog的show()方法
let MaterialDialog = Java.use("com.afollestad.materialdialogs.MaterialDialog");
MaterialDialog["show"].implementation = function () {
showStacks();//调用时打印堆栈
console.log(`MaterialDialog.show is called`);
this["show"]();
};
```
spwan方式运行HOOK脚本:
> spwan方式是会重启app,在app刚开始运行的时候就执行hook代码*(这样才能在show()被调用之前hook上)*
```shell
frida -U -f com.idaodan.clean.master -l D:\Code_Project\JS_project\demo1\雪豹速清_2.9.0.js --no-pause
```
打印出堆栈:
```
com.afollestad.materialdialogs.MaterialDialog.show(Native Method)
com.afollestad.materialdialogs.MaterialDialog$Builder.ۦۜۗ(Unknown Source:4)
o.oOO0oooO.ۦۦ(Unknown Source:260)
o.oOO0oooO.ۦۦ(Unknown Source:1)
o.O0O000oO.run(Unknown Source:109)
```
> 仔细看这个堆栈信息,发现有的方法名是一个奇怪的符号:ۦۦ
>
> 这个app做了混淆,所以有很多类似下图这种极其抽象的符号:
>
>
回到堆栈这里,打印出的堆栈里的这些方法是由下到上调用的:
```
o.oOO0oooO.ۦۦ(Unknown Source:1)
↓调用↓
o.oOO0oooO.ۦۦ(Unknown Source:260)
↓调用↓
com.afollestad.materialdialogs.MaterialDialog$Builder.ۦۜۗ(Unknown Source:4)
↓调用↓
com.afollestad.materialdialogs.MaterialDialog.show(Native Method)
```
com.afollestad.materialdialogs.MaterialDialog$Builder.ۦۜۗ 就不用看了,是MaterialDialog类下的,这个方法肯定是调用了show()方法
用Jadx看看那两个o.oOO0oooO.ۦۦ 方法的内容:
> 这里搜出来的方法名叫m\*\*\*\*\*是因为Jadx为了方便分析把方法名`ۦۦ` 重命名了(这种混淆符号确实让人眼睛难受)
搜到一堆重载方法,不知道是哪个,用objection hook o.oOO0oooO类下的所有方法:
```shell
objection -g com.idaodan.clean.master explore --startup-command "android hooking watch class_method o.oOO0oooO.ۦۦ"
```
这个命令的意思是用spwan方式hook o.oOO0oooO.ۦۦ 类下的所有方法:
报错了,说没找到这个方法,不知道是不是我操作的问题。没办法只能用attach方式hook试试:
> attach方式是在app已经启动的情况下hook
```shell
objection -g com.idaodan.clean.master explore
android hooking watch class_method o.oOO0oooO.ۦۦ
```
虽然报了一些错误,但还是hook上了:
这时候就有个问题,因为是以attach方式hook的,不是在app刚启动的时候hook而是在app正在运行的时候hook的。所以就没法通过app刚启动时弹出的更新弹窗来触发hook代码
可以通过点击“检查更新”按钮来弹出更新弹窗从而触发hook代码:
点击后在控制台上看到先触发`o.oOO0oooO.ۦۦ()`,然后触发`o.oOO0oooO.ۦۦ(android.app.Activity, o.oOO0oooo, boolean)`
梳理一下调用链:
```
o.oOO0oooO.ۦۦ()
↓调用↓
o.oOO0oooO.ۦۦ(android.app.Activity, o.oOO0oooo, boolean)
↓调用↓
com.afollestad.materialdialogs.MaterialDialog$Builder.ۦۜۗ()
↓调用↓
com.afollestad.materialdialogs.MaterialDialog.show()
```
o.oOO0oooO.ۦۦ(android.app.Activity, o.oOO0oooo, boolean)离MaterialDialog类最近,包含判断是否更新的相关代码的概率比较大,先看看:
顺便标记出调用com.afollestad.materialdialogs.MaterialDialog$Builder.ۦۜۗ()方法的地方:
> m3836是Jadx将 ۦۜۗ 重命名方便分析
来详细看看这个方法里的内容:
***来梳理一下总的思路:***
***一旦执行到`this.f30496 = m3881.m3836();`就会调用show()方法弹出更新弹窗,所以只要能想办法让这个方法`不执行到这句代码`,就相当于去除更新!!!***
我这里提供一种让方法执行不到 this.f30496 = m3881.m3836();的思路:
代码是从上到下执行的,上面这里有个if判断,只要`c8453oOO0oooo.f30509 <= m27683`为true,最终一定会执行里面的其中一个return,这样就会直接结束这个方法,从而不会执行到this.f30496 = m3881.m3836();
因为f30509和m27683都是int类型的数,要想让c8453oOO0oooo.f30509 <= m27683为true,将f30509的值改成0或者将m27683的值改成很大
我这里以后者为例
m27683的值是通过执行`C6905o0ooOO0OO.m27683(C6451o0oO0Oooo.f25301)`来获得的
所以可以hook或者直接修改smali代码,将C6905o0ooOO0OO.m27683的返回值强行改成一个非常大的数
> 注意这里的C6905o0ooOO0OO.m27683是经过Jadx重命名来方便看的
>
>
>
> hook或者修改smali时应该用原本的类名和方法名:
>
> `o.o0ooOO0OO.ۥۚ۠`
这里为了快速验证之前的思路是否正确,所以直接用HOOK来修改:
> \u06E5\u06DA\u06E0是方法名`ۥۚ۠` 的Unicode编码
```javascript
let C6905o0ooOO0OO = Java.use("o.o0ooOO0OO");
C6905o0ooOO0OO["\u06E5\u06DA\u06E0"].overload('android.content.Context').implementation = function (context) {
let result = this["\u06E5\u06DA\u06E0"](context);
console.log(`C6905o0ooOO0OO.m27683 result=${result}`);
return result;
};
```
spwan方式运行HOOK脚本:
当更新弹窗跳出来前确实调用了了C6905o0ooOO0OO.m27683方法,验证了前面的一系列分析。
接下来修改hook代码,将返回值强行改成一个很大的数(因为不知道c8453oOO0oooo.f30509的值是多少,所以直接把C6905o0ooOO0OO.m27683的返回值改成9999看看情况):
```javascript
let C6905o0ooOO0OO = Java.use("o.o0ooOO0OO");
C6905o0ooOO0OO["\u06E5\u06DA\u06E0"].overload('android.content.Context').implementation = function (context) {
let result = this["\u06E5\u06DA\u06E0"](context);
result = 9999;
console.log(`C6905o0ooOO0OO.m27683 result=${result}`);
return result;
};
```
***spwan方式运行HOOK脚本,这时候C6905o0ooOO0OO.m27683的返回值被强行改成9999,发现没有弹出更新弹窗,去除更新成功!***
这里演示的思路是将C6905o0ooOO0OO.m27683的返回值被强行改成一个固定的很大的数字,如果是将c8453oOO0oooo.f30509的值强行改成固定的0行,只要满足c8453oOO0oooo.f30509 <= m27683