APP逆向 day14 某货逆向
一.前言
今天和大家来讲一下识货app的搜索接口,今天这个没有逆向,但是和大家说一下绕过app的强制更新和绕过frida的反调试等
二.app版本选择
我们会讲讲老版本和新版本
识货-7.0.0-->老版本 识货-7.73.0-->新版本 我们选择这两个版本,老版本点开会强制更新
为什么我们要选择老版本呢?
因为在有的app中,老版本还能用,而且逆向难度低,所以我们今天就要和大家说一下老版本的绕过了。
我们下载好老版本之后,进去可以看到这个页面,提示我们要更新了,我们现在就是要绕过强制更新。
三.绕过强制更新
1 以后使用老版本app,会遇到两种更新情况 - 1 选择更新,取消按钮,取消掉继续使用,直接取消,继续抓包操作即可,此时app的接口,肯定都是能用的 - 2 强制更新,弹出更新框,直接覆盖app,必须更新,否则用不了app了,有可能它的某些接口用不了了,绕过更新后,看看接口还能不能用,如果不能用了,需要重新选择版本 2 强制更新 -1 车智赢:强制更新,断网,进入app,再联网即可绕过 -app一启动,向后端发送请求,获取最新版本号,跟本地版本比较,如果版本相差比较大,就会强制更新,一般情况下,代码会在首页上,这种情况,我们只需要切换到别的页面(断网),这个代码不执行,就绕过了 -2 识货:断网,绕过不了,只要连上网,又需要更新,通过hook,hook到弹窗,让窗不弹 -反编译,找到弹窗位置,通过hook,让代码不执行
3.1 反编译找到窗口位置
我们反编译之后,看到提示框,我们直接搜索最新版本
点进去
可以发现,是执行了 UpdateDialog进行提示更新,show方法弹出更新框,那我们就点进去,把这个方法给hook掉,记住hook得使用spawn(不记得了去我前面看)
3.2 hook绕过强制更新
然后我们就手机执行frida,进行端口转发,获取前台运行包名(因为spawn需要包名),再来执行hook,这里因为hook代码比较特殊,所以我就给出给大家hook代码
import frida
import sys
#spwan 自动运行
rdev = frida.get_remote_device()
pid = rdev.spawn(["com.hupu.shihuo"]) #这里添加的是包名
session = rdev.attach(pid)
scr = """
Java.perform(function () {
var UpdateDialog = Java.use("com.azhon.appupdate.dialog.UpdateDialog"); // Java.use("需要hook的地方的包名和大类名")=
UpdateDialog.show.implementation = function(str){
//构造方法的重载 比如new aaa这种
console.log("明文:",str);
console.log("不再弹出更新框了")
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
rdev.resume(pid)
sys.stdin.read()
这个hook上后,发现每次启动app都会闪退,那我们可以知道,这个是因为这款app精心了frida检测,那我们现在就来绕过frida检测
四.绕过frida反调试
写好了hook,运行时,发现,app一执行,里面就崩了,但是不执行hook,app顺利运行 识货这款app,做了frida的反调试,检测到只要frida脚本在运行,app就自动结束 -1 删某些so文件(今天学这种) -2 ptrace占坑 -3 frida加强版 识货这款app--》使用第一种可以绕过 识货这种公司,一般情况下,公司的安全人员写了一个so文件,检测是否在运行frida的hook,如果检测到,就把app强制终止 安全人员写的so,一般情况下跟app业务无关,只用来做hook的检测,这种情况下,我们可以尝试删除这个so文件尝试一下,如果删除了,app还能顺利运行,说明这个so跟业务是无关的,就可以删除 像识货,得物这种app就是这样的 于是,我们要找到 是那个so文件,做了检测,把so文件删除即可 如何定位是哪个so文件? 使用一个通用脚本---》所有app都可以用 原理是:通过hook安卓底层--》实现依次打印这款app运行时,加载了那些so文件---》通用 当加载到某个so,app闪退了,说明就是这个so文件做了frida检测--》删除这个so文件尝试 这种方式,并不适用于所有app--》以后只能尝试
这里给出hook所有so文件的代码
4.1 找到哪一个so文件检测
import frida
import sys
rdev = frida.get_remote_device()
pid = rdev.spawn(["com.hupu.shihuo"]) #放入包名
session = rdev.attach(pid)
scr = """
Java.perform(function () {
var dlopen = Module.findExportByName(null, "dlopen");
var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
Interceptor.attach(dlopen, {
onEnter: function (args) {
var path_ptr = args[0];
var path = ptr(path_ptr).readCString();
console.log("[dlopen:]", path);
},
onLeave: function (retval) {
}
});
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
var path_ptr = args[0];
var path = ptr(path_ptr).readCString();
console.log("[dlopen_ext:]", path);
},
onLeave: function (retval) {
}
});
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
rdev.resume(pid)
sys.stdin.read()
这个代码是通用的,只需要改变包名就好,执行到哪个文件中断了,就说明是哪个so文件作怪,删掉就好,但是如果发现删除完之后不能用,那就不能采用这个方法。
发现在这里停止,那么就说明是这个so文件作怪,我们就去把这个so文件删除就好
4.2 删除那个so文件
/data/app/~~Y0T7lai_U0oUCJog9GF-8A==/com.hupu.shihuo-O3JD2hiXKDpyGx8Ibl4sRA==/lib/arm64/libmsaoaidsec.so
我们刚刚得到的是这个so文件
那我们就要把他删除
1 进入到手机内部,删除这个so文件即可 adb shell su cd /data/app/~~Y0T7lai_U0oUCJog9GF-8A==/com.hupu.shihuo-O3JD2hiXKDpyGx8Ibl4sRA==/lib/arm64 rm -rf libmsaoaidsec.so
2 删除后,再进行绕过强制更新的hook即可
现在就能进去了
五.抓包分析
5.1 直接抓包
抓包发现,都是一些静态资源,然后获得的数据都是乱码,所以一定是做了代理检测,在安卓开发中OkHttp发送请求,设置 `Proxy.NO_PROXY`,基于系统代理都是抓不到包,我们就要绕过绕过,抓更底层的包,socket,需要借助app配合 。
这里给出app是SocksDroid,给出官网
GitHub - PeterCxy/SocksDroidhttps://github.com/PeterCxy/SocksDroid下载好安装到手机就好了
5.2 绕过app代理检测
1 手机端:安装 SocksDroid 2 charles上,配置代理socks包,如下图
3 再SocksDroid配置charles代理
4 在手机端--》去掉原来的代理
配置好了就能完全抓到数据了
抓完包大多数人肯定看到逆向值就想逆向,实际上是不需要逆向的
六.结果演示
七.各种Hook脚本
这里给大家介绍几个通用脚本,在我们搜索不到的时候可以试试
7.1 hook--Map
import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("识货")
scr = """
Java.perform(function () {
var TreeMap = Java.use('java.util.TreeMap');
var Map = Java.use("java.util.Map");
TreeMap.put.implementation = function (key,value) {
if(key=="data"){
console.log(key,value);
}
var res = this.put(key,value);
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
7.2 hook--StringBuilder
import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("识货")
scr = """
Java.perform(function () {
var StringBuilder = Java.use("java.lang.StringBuilder");
StringBuilder.toString.implementation = function () {
var res = this.toString();
console.log(res);
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()
7.3 hook--Base64
import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("识货")
scr = """
Java.perform(function () {
var Base64 = Java.use("android.util.Base64");
Base64.encodeToString.overload('[B', 'int').implementation = function (bArr,val) {
var res = this.encodeToString(bArr,val);
console.log("加密了-->",res);
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()
# 通过查看输出,那请求的数据搜索,发现hook到了
7.5 hook--拦截器
//hook_Interceptor.js 文件名
Java.perform(function () {
var Builder = Java.use('okhttp3.OkHttpClient$Builder');
Builder.addInterceptor.implementation = function (inter) {
console.log(JSON.stringify(inter) );
return this.addInterceptor(inter);
};
})
//最后执行frida -Uf com.hupu.shihuo -l hook_Interceptor.js -o all_interceptor3.txt
7.6 确定是哪个拦截器做的加密和解密
import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("识货")
scr = """
Java.perform(function () {
var a = Java.use("cn.shihuo.modulelib.startup.core.c.a");
a.intercept.implementation = function (chain) {
var req = chain.request();
var httpUrl = req.url().toString();
if( httpUrl.indexOf("https://sh-gateway.shihuo.cn/v4/services/sh-goodsapi/app_swoole_shoe/preload/single") != -1 ){
console.log('执行前',httpUrl);
}
var res = this.intercept(chain); // 执行自己这个拦截器
// var response = chain.proceed(req);
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()
以上常用hook都讲完了,里面代码都是根据识货给的,具体还需要自己修改
八.总结
今天主要是讲了绕过强制更新和绕过frida检测,和一些常用hook
补充
有不懂的地方可以主页咨询我,有求必应