一、frida介绍
简单来说,Frida是一个动态代码插桩框架。这意味着它能够在程序运行的时候,不改变原有程序代码的情况下,让你往里面添加自己的代码片段。这听起来可能有点像魔法,但实际上,它是通过一种叫做“HOOK”的技术实现的。Hook就像是在软件内部安装了一个小间谍,能够监听或修改特定部分的行为。
Frida特别灵活,因为它可以用Python来编写控制脚本,用JavaScript来编写注入到目标应用程序中的实际hook代码。这意味着,即使你不完全懂应用程序是怎么写的,只要懂得Python和一点点JavaScript,就能开始探索和修改它的行为。
举个例子,假设你想知道一个游戏是如何计算得分的,你可以用Frida来“挂钩”(hook)游戏中的计分函数,每当这个函数被调用时,Frida就会告诉你,并显示或修改传入的参数,比如让得分翻倍。
Frida不仅限于游戏,它还能用于安全研究、软件调试、性能监控等多种场景,支持Android、iOS、Windows等多个平台,是开发者和安全研究人员的强大助手。
二、frida检测
检测Frida注入通常涉及检查系统中与Frida相关的各种迹象,以下是几种常见的检测方法:
检查进程和线程:
早期的检测方法会检查是否有名为frida-server的进程运行,但这种方法在现代Android系统中已经不太有效,因为Frida可以更隐蔽地运行。
分析Maps文件:
Frida在注入过程中会在目标进程中加载其代理库(如frida-agent.so)。检查 /proc/[pid]/maps 文件可以发现这些额外加载的库,从而检测到Frida的存在。
扫描网络连接:
Frida使用D-Bus协议进行通信,可以通过遍历/proc/net/tcp或/proc/net/tcp6文件来查找与Frida服务器通信的端口,或者尝试向所有开放端口发送D-Bus认证消息,响应REJECT的端口可能表明存在Frida通信。
符号表分析:
对于Native代码,可以通过遍历目标进程的符号表来寻找Frida注入的线索,因为Frida注入可能会留下特定的函数签名或修改原有的函数地址。
检查临时文件和目录:
Frida在运行时可能会创建特定的目录(如/data/local/tmp/re.frida.server)或临时文件,检查这些位置可以发现Frida的活动痕迹。
Hook检测:
应用程序自身可以通过在关键函数前后设置陷阱(例如,在函数入口处设置断点或校验堆栈帧),来检测是否被Frida或其他工具进行了Hook操作。如果函数的执行流程或返回值不符合预期,可能是被Hook的迹象。
性能监控和异常检测:
异常的内存访问模式、CPU使用率突增或应用程序行为的其他异常变化,虽然不是直接证据,但也可能是Frida活动的间接指示。
代码完整性验证:
应用程序可以在启动时验证自身的代码完整性,对比当前运行代码与原始代码或校验和,以判断是否被篡改或注入了额外的代码。
三、Frida绕过
测试app我们选择bilibili,启动Frida server。
然后开始附加到我们的进程,脚本就开始奔溃了。
写一个脚本看看是哪个so在检测。
把so拖进ida看看pthread_create在哪,结果没有找到,那就是混淆了。
继续完善我们的脚本,找到pthread_create函数。
这下我们知道在加载libmsaoaidsec.so之后紧接这调用了2次pthread_create后Frida就奔溃了。那我们完全可以基于内存做一个替换。
function create_fake_pthread_create() {
const fake_pthread_create = Memory.alloc(4096)
Memory.protect(fake_pthread_create, 4096, "rwx")
Memory.patchCode(fake_pthread_create, 4096, code => {
const cw = new Arm64Writer(code, { pc: ptr(fake_pthread_create) })
cw.putRet()
})
return fake_pthread_create
}
然后我们再运行一下frida。
完全没有问题了,可以愉快的玩耍了。