- 今天小谷分享几种
基础的
防护
手段。— 当然,也说下如何破解
1. 白名单防护
- 这个
防护
目前应该是用的最少
的,原因是这个误伤比较大
思前想后,还是先要说下这种防护手段
- 原理:
白名单防护
手段的原理主要是防止动态库的插入
也就是把所有可能用到的
动态库收集起来
。如果检测到多余
的动态库,就可以做相应的防护技巧
- 第一步: 获取执行所需要的所有库
//获取image 个数
int count = _dyld_image_count();
//把自己的macho镜像去掉
for (int i = 1; i < count; i++) {
//打印所有image name,用,隔开
printf("%s,",_dyld_get_image_name(i));
}
复制代码
- 第二步: 把输出的
log
,copy
如果以后真的用到了,
绝对不能写在客户端
。(其实就算写在服务器
请求误伤还是很大
!)
- 第三步: 判断应用加载进入的时候,是否有
不包含的库
(这里如果存在,就视为注入的库)
int count = _dyld_image_count();
//把自己的macho镜像去掉
for (int i = 1; i < count; i++) {
// printf("%s,",_dyld_get_image_name(i));
if (!strstr(libStr, _dyld_get_image_name(i))) {
//如果不包含,视为注入库!
NSLog(@"注入库。采取防护措施~!");
}
}
复制代码
- 总结下
-
- 白名单防护
误伤太大
- 白名单防护
-
- 现在基本没有啥应用会这么做。
维护成本太高
- 现在基本没有啥应用会这么做。
-
- 如果系统升级,或者每个机型的系统库不一样。就要一直
改变兼容
- 如果系统升级,或者每个机型的系统库不一样。就要一直
-
- 就算写成服务器存储。也可能不是第一瞬间判断的
-
不推荐这种防护
!,但是通过白名单防护,可能会有很多延伸的思想
。兄弟们可以考虑下~
2. Ptrace
很早之前
支付宝
就是用的这个~
2.1. Ptrace防护
-
我们
逆向APP
的时候,有时候不仅仅是静态分析
,还可能会动态调试
-
我们的
动态调试
,无论是终端调试
,还是Xcode附加
。都是通过debugserver监测进程
做到的! -
Ptrace
就是通过限制进程
来阻止附加调试
的 -
先来个
Ptrace
的例子
//点击事件来一波
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"ptrace 防调试!");
ptrace(PT_DENY_ATTACH, 0, 0, 0);//这个就是Ptrace防护调试
NSLog(@"难道没有防护住?");
}
复制代码
- 我们点击一下
发现之后就不走了!
Ptrace特点:调试闪退,但是点击APP正常运行
2.2. Ptrace破解
有
防护
办法就有破解
办法
- 如果你确定是
Ptrace防护
了。那么我们可以hook这个符号
试试~
//定义函数指针!
int (*ptrace_p)(int _request, pid_t _pid, caddr_t _addr, int _data);
+(void)load
{
//交换
struct rebinding ptraceBd;
ptraceBd.name ="ptrace";
ptraceBd.replacement = my_ptrace;
ptraceBd.replaced = (void *)&ptrace_p;
struct rebinding bds[] = {ptraceBd};
rebind_symbols(bds, 1);
}
//自定义
int my_ptrace (int _request, pid_t _pid, caddr_t _addr, int _data){
if (_request != PT_DENY_ATTACH) {//如果不是拒绝附加,保持调用!
return ptrace_p(_request,_pid,_addr,_data);
}
return 0;
}
复制代码
利用
fishhook
的符号重绑定
就搞定了~
3. sysctl
3.1. sysctl防护
这个目前还是挺厉害的~
抖音
就是用的这个,不过他除了这个还做了别的防护
(改天我玩一下,然后写一篇博客,?)
- 写一下他的防护代码
#import <sys/sysctl.h>
bool isDebugServer(){
//控制码
int name[4];//放字节码-查询信息
name[0] = CTL_KERN;//内核查看
name[1] = KERN_PROC;//查询进程
name[2] = KERN_PROC_PID; //通过进程id查进程
name[3] = getpid();//拿到自己进程的id
//查询结果
struct kinfo_proc info;//进程查询信息结果
size_t info_size = sizeof(info);//结构体大小
int error = sysctl(name, sizeof(name)/sizeof(*name), &info, &info_size, 0, 0);
assert(error == 0);//0就是没有错误,设置个断言
//结果解析 p_flag的第12位为1就是有调试
//p_flag 与 P_TRACED =0 就是有调试
return ((info.kp_proc.p_flag & P_TRACED) !=0);
}
- (void)viewDidLoad {
[super viewDidLoad];
if (isDebugServer()) {
NSLog(@"在debugserver调试状态!");
//自行处理
}else{
NSLog(@"在正常运行状态!");
}
}
复制代码
- 当我
Xcode 运行
时
- 当我
断开xcode
,自己运行时
说明检测到了
3.2. sysctl破解
也是用的
fishhook
的符号重绑定
- 这里我就写重绑定之后的
实现
了
//自定义函数
int mySysctl(int *name, u_int namelen, void *info, size_t *infosize, void *newinfo, size_t newinfosize){
if (namelen == 4
&& name[0] == CTL_KERN
&& name[1] == KERN_PROC
&& name[2] == KERN_PROC_PID
&& info
&& (int)*infosize == sizeof(struct kinfo_proc))
{
int err = sysctl_p(name, namelen, info, infosize, newinfo, newinfosize);
//拿出info做判断
struct kinfo_proc * myInfo = (struct kinfo_proc *)info;
if((myInfo->kp_proc.p_flag & P_TRACED) != 0){
//使用异或取反
myInfo->kp_proc.p_flag ^= P_TRACED;
}
return 0;
}
return sysctl_p(name, namelen, info, infosize, newinfo, newinfosize);
}
复制代码
4. 总结
-
白名单防护
是一种思维手段
,这种防护误伤很大,慎用!!
-
Ptrace
和sysctl
现在用的还挺多的,你要想办法做到神不知鬼不觉~ -
大家可以用到工程试上一下~ ?。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END