越狱防护(25)

简介: Tweak原理DYLD_INSERT_LIBRARIES

Tweak原理DYLD_INSERT_LIBRARIES


  1. 查看dyld源码(版本519.2.2)


  1. 当DYLD_INSERT_LIBRARIES不为空, 则循环插入 -> 越狱的插件是通过DYLD_INSERT_LIBRARIES来进行注入的.


微信图片_20220510005822.png
image.png


  1. 该代码前面,有个processIsRestricted(进程限制), 如果该值存在, 则删除Insert_Libraries里面的数据


微信图片_20220510005834.png

image.png


       1.hasRestrictedSegment -> 为真就可以 -> 判断某个MachO是否是受限的


__RESTRICT防护


  1. 新建Xcode项目(antiTweak), 运行到手机


       1.在touchesbegan里面 写上exit(0);


  1. 新建tweak项目(antitweakdemo), hook -> touchesbegan -> NSLog(@"破解成功");


       1.make报错改touchesbegan的参数类型为id

       2.运行插件, 插件运行成功,成功hook


  1. 让__RESTRICT或__restrict起作用, 这样hasRestrictedSegment就会为真


       1.Xcode设置Build Settings -> other linker -> Other Linker Flags -> -Wl,-sectcreate,__RESTRICT,__restrict,/dev/null

       2.项目设置完后,编译打开编译包,用MachOView查看 -> 发现section字段里面有__RESTRICT,__restrict

       3.这种可以防止插件的插入(仅限低版本iOS10以下的系统),


             1.因为dyld的代码升级, 这种方法失效了

             2.并且这种只针对用DYLD_INSERT_LIBRARIES的插入的插件


修改二进制破解


针对以上的防护, 可以找到该字段, 修改二进制


  1. 将生成的MachO文件,用MachOView打开找到Load Commands -> 修改__RESTRICT对应的二进制(只用改一个就可以) ->  然后关掉重新打开 -> 发现Sections(__RESTRICT,__restrict)里面的值有变化了 -> 记得重签一下 -> 就破解成功了


放置__RESTRICT被修改,用自己的函数来验证


借助dyld源码里面扫码动态库的方法,来构建白名单


#import "ViewController.h"
#import <mach-o/loader.h>
#import <mach-o/dyld.h>
#if __LP64__
    #define macho_header              mach_header_64
    #define LC_SEGMENT_COMMAND        LC_SEGMENT_64
    #define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT
    #define LC_ENCRYPT_COMMAND        LC_ENCRYPTION_INFO
    #define macho_segment_command    segment_command_64
    #define macho_section            section_64
#else
    #define macho_header              mach_header
    #define LC_SEGMENT_COMMAND        LC_SEGMENT
    #define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT_64
    #define LC_ENCRYPT_COMMAND        LC_ENCRYPTION_INFO_64
    #define macho_segment_command    segment_command
    #define macho_section            section
#endif
@interface ViewController ()
@end
@implementation ViewController
+(void)load
{
    const struct macho_header * header = _dyld_get_image_header(0);
    if (hk_hasRestrictedSegment(header)) {
        NSLog(@"防止Tweak注入!");
    }else{
        NSLog(@"被修改了!");
//        exit(0);//相当于这是一个记号! -- 给服务器发请求!
    }
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //这里不能碰!
    exit(0);
}
//参考dyldy源码里面的扫码方法
static bool hk_hasRestrictedSegment(const struct macho_header* mh)
{
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(struct macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND:
            {
                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
//                printf("seg name: %s\n", seg->segname);
                //dyld::log("seg name: %s\n", seg->segname);
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict") == 0)
                            return true;
                    }
                }
            }
            break;
        }
        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
    }
    return false;
}
@end


如果想要修改hk_hasRestrictedSegment, 需要精准定位hk_hasRestrictedSegment的函数地址,用InlineHook,因为上架的时候是去符号的,并且检测到修改时, 不要用exit(0);来立即杀掉进程, 因为这个标记太明显, 可以考考, 延迟杀掉或者上报服务器或者断网(当检测到被修改时,让所有请求都超时)(做一个感知比较弱的操作来迷惑进攻者)


白名单检测(误杀比较大,建议黑名单)


#import <mach-o/dyld.h>
#import <mach-o/loader.h>
const char * libStrs = ".app/whitelistDemo/Developer/usr/lib/libBacktraceRecording.dylib/Developer/usr/lib/libMainThreadChecker.dylib/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib/System/Library/Frameworks/Foundation.framework/Foundation/usr/lib/libobjc.A.dylib/usr/lib/libSystem.B.dylib/System/Library/Frameworks/UIKit.framework/UIKit/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation/usr/lib/libcompression.dylib";
@interface ViewController ()
@end
@implementation ViewController
+(void)load
{
    int count = _dyld_image_count();//你进程依赖库的数量!
    for (int i = 1; i < count; i++) {
        const char * imageName = _dyld_get_image_name(i);
//        printf("%s",imageName);
        if (!strstr(libStrs, imageName)) {//如果这个库不在白名单中!
//            printf("该动态库有危险!%s\n",imageName);//exit(0)
        }
    }
}


  1. 第一次用不越狱的手机来运行, 来拿到所有的库
  2. printf("%s",imageName); -> 打印要所有加载过的库的名字
  3. 打印出来的字符串,最开始的包含有沙盒路径,需要去掉,因为沙盒路径在不断的变化.


        1.所以上面的检测方法, 是从for循环下标等于1开始的


  1. 这里测试的时候可以用越狱手机来运行测试, 可以监测到越狱的库,并打印出来对应的有危险的库名称
  2. 如果要做一个完整的白名单,需要跑不同的手机,拿到所有手机的常用库,所以比较难, 这里推荐构建一个黑名单来检测


        1.这个名单, 建议放在服务器中,来适应不同的变化

        2.检测到之后的逻辑,就是不建议立即杀掉, 需要做弱感知的操作来迷惑(包括延迟杀掉进程/上报服务器/断网/或者请求回来之后不做处理等弱感知操作)


ptrace防护


LLDB之所以可以附加进程 -> 就是因为debugserver发送指令来跟踪我们的进程 -> ptrace()

所以在这里有这么个想法, 不允许进程附加来阻止LLDB附加,来防止别人来调试我们的APP.


  1. antiDebug
  2. 引入MyPtraceHeader.h -> 有头文件就可以调用, 因为ptrace是系统的函数
  3. 看下面的详细调用以及解释
  4. 如果加上以下函数, 用Xcode运行APP就会闪退, 不用Xcode运行就能正常打开
  5. 所以要加上环境判断,如果是大环境线上的,就放开该函数来防止别人调试


//告诉系统,当前进程.拒绝被debugserver附加!
    //arg1:ptrace要做到事情
    //arg2:需要操作的进程
    //arg4/arg3:取决于第一个参数!
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
    //如果附加就闪退!!


ptrace防护的特点


  1. 附加不了进程
  2. Xcode重签闪退
  3. 正常使用正常


破解ptrace


  1. antiAntiDebug
  2. 下符号断点ptrace,可以断到该函数,如果是ptrace防护,可以断到
  3. bt -> 查看堆栈
  4. 正常用sbt() -> 恢复符号表来找到hook的位置

       1.因为ptrace是一个系统函数 -> 需要间接符号表

       2.用fishhook符号重绑定来破解

       3.测试的时候记得修改支持的最低系统,高系统有可能运行出错


#import "InjectCode.h"
#import "fishhook.h"
#import "MyPtraceHeader.h"
@implementation InjectCode
//定义函数指针!
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;
}




目录
相关文章
|
8月前
|
安全 网络安全
技巧!通过360卫士白名单绕过查杀
技巧!通过360卫士白名单绕过查杀
206 0
|
运维 安全 Linux
linux服务器安全防护加固防黑客攻击方案
对于咱们 Linux系统来说,其实它的运维是运维,它的安全方面加固是方方面面的,这涉及到的东西有点多,安全加固牵扯到的安全因素和运维不是一回事。然后咱们今天主要挑其中的几点来为大家来讲一下,也是一些比较基础的。今天周一,因为我们这一周都是讲安全相关的,我来起个头就讲一些比较基础的。其实咱们对于Linux系统加固,对于系统架构,咱们首先要从以下几个方面来进行考虑。首先是用户安全,其次是文件安全以及登录安全这三个首先要从这三个方面来进行考虑,然后再考虑咱们的业务,包括一些咱们的服务在考虑他们的性能。
133 1
linux服务器安全防护加固防黑客攻击方案
|
安全 网络安全 数据安全/隐私保护
|
安全 数据安全/隐私保护 iOS开发