【Android 逆向】frida 检测绕过
1. aaa.apk 安装到手机,是一个叫玩吧的应用
./hooker
......
23248 浏 览 器 com.browser2345_oem
32541 玩吧 com.wodi.who
2447 电话和短信存储 com.android.providers.telephony
2447 电话服务 com.android.phone
3264 电量和性能 com.miui.powerkeeper
......
2. 启动hluda版frida server hluda-server-14.2.13-android-arm64 绕过一些对frida特征的检查
执行 frida -Uf com.wodi.who --no-pause,直接崩溃退出
Spawned `com.wodi.who`. Resuming main thread!
[MI 5X::com.wodi.who]-> Process terminated
[MI 5X::com.wodi.who]->
说明有对frida 附着到进程存在检测
3. 常用检测有 对 TracerPid 的检测,参考r0trace 的方案进行绕过
var ByPassTracerPid = function () {
var fgetsPtr = Module.findExportByName("libc.so", "fgets");
var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
var retval = fgets(buffer, size, fp);
var bufstr = Memory.readUtf8String(buffer);
if (bufstr.indexOf("TracerPid:") > -1) {
Memory.writeUtf8String(buffer, "TracerPid:\t0");
console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
}
return retval;
}, 'pointer', ['pointer', 'int', 'pointer']));
};
日志
Spawned `com.wodi.who`. Resuming main thread!
[MI 5X::com.wodi.who]-> tracerpid replaced: TracerPid: 0
Process terminated
[MI 5X::com.wodi.who]->
还是不行,看来还有别的地方检测
4.尝试hook pthread_create 来看一下哪里调用到了它
function hook_func() {
var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
Interceptor.attach(pthread_creat_addr,{
onEnter(args){
console.log("call pthread_create...")
let func_addr = args[2]
console.log("The thread function address is " + func_addr)
console.log('pthread_create called from:\n'
+ Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress)
.join('\n')
+ '\n');
}
})
}
执行日志:
call pthread_create...
The thread function address is 0xc0512129
The libmsaoaidsec.so base 0xc0501000
pthread_create called from:
0xc05123fd libmsaoaidsec.so!0x113fd
0xc0511ab7 libmsaoaidsec.so!0x10ab7
0xc0511bc1 libmsaoaidsec.so!0x10bc1
0xc050d5b9 libmsaoaidsec.so!_init+0x1ac
0xec63662b
......
tracerpid replaced: TracerPid: 0
Process terminated
可以看到 libmsaoaidsec.so 执行了0x113fd 后好像就出问题了,而且这个是在_init+0x1ac,很值得怀疑,看一下反汇编的代码
0xc0512129 - 0xc0501000 = 0x11129
可以看到这里看起来一个线程搞事情
int sub_113E0()
{
_DWORD *v0; // r4
pthread_t v2; // [sp+0h] [bp-10h] BYREF
int v3; // [sp+4h] [bp-Ch]
v0 = off_1FC04;
v3 = *(_DWORD *)off_1FC04;
pthread_create(&v2, 0, (void *(*)(void *))sub_11128, 0);
return *v0 - v3;
}
那么hook 掉这个 sub_11128 ,让他啥也不干,对应偏移地址 0x000113E0
Interceptor.replace(module.base.add(0x00011128+1), new NativeCallback(function() {
console.log("0x00011129 replace success!!!")
}, 'void', []))
执行日志
***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'xiaomi/tiffany/tiffany:8.1.0/OPM1.171019.019/V11.0.3.0.ODBCNXM:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 12322, tid: 12322, name: com.wodi.who >>> com.wodi.who <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x32b1
r0 0000c6dd r1 0000008c r2 8ea8c4cb r3 0000023d
r4 00000000 r5 0008d5f4 r6 00003225 r7 000001aa
r8 dd932900 r9 ffd70784 sl 00000000 fp ffd70878
ip ea1a962c sp ffd6e638 lr c052bc95 pc c052bc96 cpsr 200f0030
backtrace:
#00 pc 00001c96 /data/app/com.wodi.who-Gf4PUi4Emat5i9N3B4wFBA==/lib/arm/libmsaoaidsec.so (offset 0x12000)
#01 pc 00001c91 /data/app/com.wodi.who-Gf4PUi4Emat5i9N3B4wFBA==/lib/arm/libmsaoaidsec.so (offset 0x12000)
***
还是崩了,说明还有地方在检测,比如这个00001c96+0x12000处,
可以看到这里在检测linker的情况,查询了符号表和字符串表,估计实在检查一些函数是否被hook,那先hooker当前这个函数
Interceptor.replace(module.base.add(0x00013AB0+1), new NativeCallback(function() {
console.log("0x00013AB1 replace success!!!")
}, 'void', []))
注意: Thumb指令的地址 ,hook的时候要加1,然后就ok了,进程不再崩溃,执行frida命令ok
日志
Process
tracerpid replaced: TracerPid: 0
tracerpid replaced: TracerPid: 0
[MI 5X::com.wodi.who]-> Process
{
"arch": "arm",
"codeSigningPolicy": "optional",
"id": 12563,
"pageSize": 4096,
"platform": "linux",
"pointerSize": 4
}
[MI 5X::com.wodi.who]-> tracerpid replaced: TracerPid: 0
全部代码
var ByPassTracerPid = function () {
var fgetsPtr = Module.findExportByName("libc.so", "fgets");
var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
var retval = fgets(buffer, size, fp);
var bufstr = Memory.readUtf8String(buffer);
if (bufstr.indexOf("TracerPid:") > -1) {
Memory.writeUtf8String(buffer, "TracerPid:\t0");
console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
}
return retval;
}, 'pointer', ['pointer', 'int', 'pointer']));
};
//setImmediate(ByPassTracerPid);
function hook_dlopen(soName) {
Interceptor.attach(Module.findExportByName(null, "dlopen"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
if (path.indexOf(soName) >= 0) {
this.is_can_hook = true;
}
}
},
onLeave: function (retval) {
if (this.is_can_hook) {
console.log("hook start...");
hook_func()
}
}
}
);
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
if (path.indexOf(soName) >= 0) {
this.is_can_hook = true;
}
}
},
onLeave: function (retval) {
if (this.is_can_hook) {
console.log("hook start...");
hook_func()
}
}
}
);
}
function hook_func() {
var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
Interceptor.attach(pthread_creat_addr,{
onEnter(args){
console.log("call pthread_create...")
let func_addr = args[2]
console.log("The thread function address is " + func_addr)
let libmsaoaidsec = Process.findModuleByName("libmsaoaidsec.so")
if (libmsaoaidsec != null){
console.log("The libmsaoaidsec.so base " + libmsaoaidsec.base)
bypass_thread(libmsaoaidsec)
}
console.log('pthread_create called from:\n'
+ Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress)
.join('\n')
+ '\n');
}
})
}
function bypass_thread(module) {
// Interceptor.replace(module.base.add(0x0000FA98+1), new NativeCallback(function() {
// console.log("0x0000FA99 replace success!!!")
// }, 'void', []))
Interceptor.replace(module.base.add(0x00011128+1), new NativeCallback(function() {
console.log("0x00011129 replace success!!!")
}, 'void', []))
P
}
function main() {
ByPassTracerPid()
hook_dlopen("libc.so")
}
setImmediate(main)
【Android 逆向】frida 检测绕过的更多相关文章
- 修改Android手机内核,绕过反调试
本文博客链接:http://blog.csdn.net/qq1084283172/article/details/57086486 0x1.手机设备环境 Model number: Nexus 5 O ...
- android逆向学习小结--CrackMe_1
断断续续的总算的把android开发和逆向的这两本书看完了,虽然没有java,和android开发的基础,但总体感觉起来还是比较能接收的,毕竟都是触类旁通的.当然要深入的话还需要对这门语言的细节特性和 ...
- 【转】Android逆向入门流程
原文:https://www.jianshu.com/p/71fb7ccc05ff 0.写在前面 本文是笔者自学笔记,以破解某目标apk的方式进行学习,中间辅以原理性知识,方便面试需求. 参考文章的原 ...
- Android逆向系列文章— Android基础逆向(6)
本文作者:HAI_ 0×00 前言 不知所以然,请看 Android逆向-Android基础逆向(1) Android逆向-Android基础逆向(2) Android逆向-Android基础逆向(2 ...
- Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)
Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码) 来源 https://blog.csdn.net/jiangwei0910410003/article/details/51 ...
- 零开始Android逆向教程(一)——初探Android逆向
这段时间因为某些业务驱动,开始研究一些逆向相关的东西,浏览了下其所包含的大致内容,发现真是一个新大陆,跟之前耳听目染过的一些门面介绍完全不是一个层级的,真正的印证了下手难这一说法. 谨此以本文开始 ...
- 2021年正确的Android逆向开发学习之路
2021年正确的Android逆向开发学习之路 说明 文章首发于HURUWO的博客小站,本平台做同步备份发布.如有浏览或访问异常或者相关疑问可前往原博客下评论浏览. 原文链接 2021年正确的Andr ...
- [转]Android逆向之动态调试总结
一.在SO中关键函数上下断点 刚学逆向调试时.大多都满足于在SO中某关键函数上下断点.然后通过操作应用程序,去触发这个断点,然后进行调试 详细的步骤可以参见非虫大大的<Android软件安全与逆 ...
- Android内存泄漏检测利器:LeakCanary
Android内存泄漏检测利器:LeakCanary MAR 28TH, 2016 是什么? 一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具 为什么需要LeakCanary? ...
- 谷歌发布基于机器学习的Android APP安全检测系统:Google Play Protect
Google Play作为众所周知的在线应用市场,因为审查制度的松散,经常会有一些恶意软件伪装成其他应用混入其中.此前阿里聚安全小编就报道了2例关于恶意软件伪装在Google Play上的事件:< ...
随机推荐
- [转帖]阿里发布自研ARM服务器芯片倚天710,不对外出售
https://www.modb.pro/db/139440 10月19日,阿里巴巴旗下半导体公司平头哥发布自研云芯片倚天710,并宣称该芯片是业界性能最强的ARM服务器芯片,性能超过业界标杆20%, ...
- 巧用GenericObjectPool创建自定义对象池
作者:京东物流 高圆庆 1 前言 通常一个对象创建.销毁非常耗时的时候,我们不会频繁的创建和销毁它,而是考虑复用.复用对象的一种做法就是对象池,将创建好的对象放入池中维护起来,下次再用的时候直接拿池中 ...
- vue3中mixins的使用
vue3-mixins 在开发的过程中我们会遇见相同或者相似的逻辑代码. 可以通过vue的 mixin 功能抽离公共的业务逻辑, 然后通过impor再组件中引入.通过mixins注册进来. 这样我们就 ...
- echasrts定义折线图legend的样式-优化
option = { title: { text: '折线图堆叠' }, tooltip: { trigger: 'axis' }, //定义折线图legend的形状哈 legend: { itemW ...
- 正则表达式match方法和search方法
正则表达式, //match() 方法可在字符串内检索指定的值 找到返回相关数据,找不到返回null var part = /Box/ig; var str = "this is box,i ...
- go中的sync.RWMutex源码解读
读写锁 前言 什么是读写锁 看下实现 读锁 RLock RUnlock 写锁 Lock Unlock 问题要论 写操作是如何阻止写操作的 写操作是如何阻止读操作的 读操作是如何阻止写操作的 为什么写锁 ...
- 超级AI助手:全新提升!中文NLP训练框架,快速上手,海量训练数据
"超级AI助手:全新提升!中文NLP训练框架,快速上手,海量训练数据,ChatGLM-v2.中文Bloom.Dolly_v2_3b助您实现更智能的应用!" 1.简介 目标:基于py ...
- python实现GUI自动化(控制鼠标)|屏幕快照&图像识别基础
1.GUI自动化 ●GUI自动化就是写程序直接控制键盘和鼠标.这些程序可以控制其他应用,向它们发送虚拟的击键和鼠标点击,就像你自己坐在计算机前与应用交互-样.这种技术被称为"图形用户界面自动 ...
- 1.9 动态解密ShellCode反弹
动态解密执行技术可以对抗杀软的磁盘特征查杀.其原理是将程序代码段中的代码进行加密,然后将加密后的代码回写到原始位置.当程序运行时,将动态解密加密代码,并将解密后的代码回写到原始位置,从而实现内存加载. ...
- 1.7 完善自定位ShellCode
在之前的文章中,我们实现了一个正向的匿名管道ShellCode后门,为了保证文章的简洁易懂并没有增加针对调用函数的动态定位功能,此类方法在更换系统后则由于地址变化导致我们的后门无法正常使用,接下来将实 ...