iOS逆向1024-防护进阶

001--反调试sysctl(代码防护)

// sysctl:检测app进程是否被附加 (防护进程被调试) 《程序员的自我修养》

#import "ViewController.h"
#import 

@interface ViewController ()
@end

static dispatch_source_t timer;

@implementation ViewController

// 1秒钟检测一次
void debugCheck(){
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        if (isDebugger()) {
            NSLog(@"检测到了!!");
        }else{
            NSLog(@"正常!!");
        }
    });
    dispatch_resume(timer);
}


// 真机运行 没有DebuggerServer,所以不会检测到调试
// sysctl(int * 控制码, u_int 字节, void * 查询结果, size_t * 结构体, void * 结构体的大小, size_t)
// #define    P_TRACED    0x00000800    /* Debugged process being traced: 跟踪调试过程 */

//检测是否被调试
BOOL isDebugger(){
    //控制码
    int name[4];//里面放字节码.查询信息
    name[0] = CTL_KERN;     //内核查看
    name[1] = KERN_PROC;    //查询进程
    name[2] = KERN_PROC_PID;//传递的参数是进程的ID(PID)   //同:$ ps -A
    name[3] = getpid();     //PID的值告诉(进程id)
    
    struct kinfo_proc info; //接受进程查询结果信息的结构体
    size_t info_size = sizeof(info);//结构体的大小
    //int error = sysctl(name, 4, &info, &info_size, 0, 0);
    int error = sysctl(name, sizeof(name)/sizeof(*name), &info, &info_size, 0, 0);
    assert(error == 0);//0就是没有错误,其他就是错误码
    //1011 1000 1010 1010 1101 0101 1101 0101
    //&
    //0000 0000 0000 1000 0000 0000 0000 0000
    // == 0 ? 没有、有!!
    return ((info.kp_proc.p_flag & P_TRACED) != 0);  // P_TRACED: 跟踪调试过程
}

- (void)viewDidLoad {
    [super viewDidLoad];

    debugCheck();
    
}
@end


002--破解sysctl(攻击)

创建动态库:injectSysctl

iOS逆向1024-防护进阶_第1张图片
image.png

导入fishhook

iOS逆向1024-防护进阶_第2张图片
image.png
#import "injectCode.h"
#import "fishhook.h"
#import 
@implementation injectCode

//原始函数的地址
int (*sysctl_p)(int *, u_int, void *, size_t *, void *, size_t);

//自定义函数
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 err;
    }
    return sysctl_p(name, namelen, info, infosize, newinfo, newinfosize);
}

+(void)load
{
    //交换
    rebind_symbols((struct rebinding[1]){{"sysctl",mySysctl,(void *)&sysctl_p}}, 1);
}
@end


003--ptrace&sysctl提前执行 (再防护)

创建动态库:antiDebug

iOS逆向1024-防护进阶_第3张图片
image.png
iOS逆向1024-防护进阶_第4张图片
image.png

注意:antiDebugCode 防护在前

#import "antiDebugCode.h"
#import "fishhook.h"
#import "MyPtraceHeader.h"
#import 

static dispatch_source_t timer;
@implementation antiDebugCode

void debugCheck(){
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        if (isDebugger()) {
            NSLog(@"检测到了!!");
        }else{
            NSLog(@"正常!!");
        }
    });
    dispatch_resume(timer);
}


//检测是否被调试
BOOL isDebugger(){
    //控制码
    int name[4];//里面放字节码.查询信息
    name[0] = CTL_KERN;//内核查看
    name[1] = KERN_PROC;//查询进程
    name[2] = KERN_PROC_PID;//传递的参数是进程的ID(PID)
    name[3] = getpid();//PID的值告诉
    
    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就是没有错误,其他就是错误码
    
    //1011 1000 1010 1010 1101 0101 1101 0101
    //&
    //0000 0000 0000 1000 0000 0000 0000 0000
    // == 0 ? 没有  有!!
    return ((info.kp_proc.p_flag & P_TRACED) != 0);
}

void debugerCheck(){
    if (isDebugger()) {
        NSLog(@"进程被调试!!");
    }
    //开启反调试
    ptrace(PT_DENY_ATTACH, getpid(), 0, 0);
}

+(void)load
{
    debugerCheck();
}
@end


004--攻防博弈!找到你就赢

loadCommand: 改变原始代码
ptrace (process trace 进程跟踪)
ptrace 系统函数,是有符号的
查看 ptrace

iOS逆向1024-防护进阶_第5张图片
image.png

下个符号断点

iOS逆向1024-防护进阶_第6张图片
image.png
iOS逆向1024-防护进阶_第7张图片
image.png
iOS逆向1024-防护进阶_第8张图片
image.png

运行程序,立刻进入断点:目的 就是为了看函数调用栈

(lldb)bt        // 显示当前线程的调用堆栈(bt:back stack)
(lldb)image list      // 查看库
iOS逆向1024-防护进阶_第9张图片
image.png

看不到函数调用栈,解决方案:用 Debug 模式

iOS逆向1024-防护进阶_第10张图片
image.png

重新编译运行

iOS逆向1024-防护进阶_第11张图片
image.png
iOS逆向1024-防护进阶_第12张图片
image.png

用 Hopper Disassembler 分析MacO文件,找到上面对应的地址

image.png
iOS逆向1024-防护进阶_第13张图片
image.png

快捷键:alt + A
同上

iOS逆向1024-防护进阶_第14张图片
image.png

修改MacO文件:跳出 ptrace 方法的执行

iOS逆向1024-防护进阶_第15张图片
image.png
iOS逆向1024-防护进阶_第16张图片
image.png

导出 新的MacO文件

iOS逆向1024-防护进阶_第17张图片
image.png

新的MacO 文件 导入MonkeyApp 创建的工程里,运行,可以调试了!


005--破解悬疑已久的反HOOK

这里涉及到以前的章节:1011- HOOK-代码的防护

终端命令:
压缩成ipa包
zip -ry ZMHook--基本防护.ipa Payload
zip -ry antiHook基本防护.ipa Payload
zip -ry antiHook基本防护2.ipa Payload
zip -ry antiHook基本防护exit.ipa Payload

1、先加载ZMHook 库 再加载 ZMHookManager,也就是hook代码在先,防护在后,所以防护失效
2、先加载ZMHookManager 库 再加载 ZMHook,现在防护,再hook 就交互交换不到方法了,已经被防护住了
3、对于检测到对方的hook,采取的方法式 退出程序 exit !!

#import "ZMHookManager.h"
#import "fishhook.h"
#import 

@implementation ZMHookManager

//专门HOOK
+(void)load
{
    NSLog(@"ZMHookManager--Load");
    //内部用到的交换代码!
    Method old = class_getInstanceMethod(objc_getClass("ViewController"), @selector(btnClick1:));
    Method new = class_getInstanceMethod(self, @selector(click1Hook:));
    method_exchangeImplementations(old, new);
    
    //基本防护
    struct rebinding bd;
    bd.name = "method_exchangeImplementations";
    bd.replacement = myExchang;
    bd.replaced = (void *)&exchangeP;
    
//    struct rebinding rebindings[] = {bd};
//    rebind_symbols(rebindings, 1);
    
    
//     method_getImplementation
//     method_setImplementation
    
    struct rebinding bd1;
    bd1.name = "method_getImplementation";
    bd1.replacement = myExchang;
    bd1.replaced = (void *)&getIMP;
    
    struct rebinding bd2;
    bd2.name = "method_setImplementation";
    bd2.replacement = myExchang;
    bd2.replaced = (void *)&setIMP;
    
    struct rebinding rebindings[] = {bd,bd1,bd2};
    rebind_symbols(rebindings, 3);
}

//保留原来的交换函数
IMP _Nonnull (*setIMP)(Method _Nonnull m, IMP _Nonnull imp);
IMP _Nonnull (*getIMP)(Method _Nonnull m);
void (*exchangeP)(Method _Nonnull m1, Method _Nonnull m2);

//新的函数
void myExchang(Method _Nonnull m1, Method _Nonnull m2){
    NSLog(@"检测到了HOOK!!!");
    //强制退出!
    exit(1);
}

-(void)click1Hook:(id)sendr{
    NSLog(@"原来APP的HOOK保留!!");
}
@end

5.1 定位反hook的 退出进程的 地方

iOS逆向1024-防护进阶_第18张图片
image.png
iOS逆向1024-防护进阶_第19张图片
image.png

5.2 hopper 查看 MacO 文件

iOS逆向1024-防护进阶_第20张图片
image.png

5.3 hopper 修改内存地址,让防护的代码,找不到要交换的方法,就可以去hook了

iOS逆向1024-防护进阶_第21张图片
image.png
%hook ViewController
- (void)btnClick1:(id)sender {
    NSLog(@"HOOK到了!!");
}
%end



总结:

001--反调试 sysctl.wmv (防护)

#import
// sysctl:检测app进程是否被附加 放在最前面执行

002--破解 sysctl.wmv (攻)

创建动态库:injectSysctl
导入fishhook
#import "injectCode.h"
#import "fishhook.h"
#import
// fishhook 交换 sysctl 方法

003--ptrace&sysctl提前执行.wmv (防护)

创建动态库:antiDebug
注意:antiDebugCode 防护在前(MonkeyApp 也进攻不了)

  • 反调试 (上节课有讲解)
    ptrace (process trace 进程跟踪)
    此函数提供了一个进程监听控制另外一个进程.并且可以检测被控制进程的内存和寄存器里面的数据!
    它可以用来实现断点调试和系统调用跟踪.debugserver就是用的它
    iOS 中没有提供相关的头.
    书籍:<程序员的自我修养>
    */

原理:防护的代码执行的太早!
导致:我Hook的代码执行在其后!

004--攻防博弈!找到你就赢.wmv

MacO loadCommand 段:改变原始代码
ptrace (process trace 进程跟踪)
ptrace 系统函数,是有符号的
下个ptrace符号断点

运行程序,立刻进入断点:目的 就是为了看函数调用栈
(lldb)bt // 显示当前线程的调用堆栈(bt:back stack)
(lldb)image list // 查看库

修改MacO文件:跳出 ptrace 方法的执行
导出 新的MacO文件
新的MacO 文件 导入MonkeyApp 创建的工程里,运行,可以调试了

005--破解悬疑已久的反HOOK.wmv

这里涉及到以前的章节:1011- HOOK-代码的防护
1、先加载ZMHook 库 再加载 ZMHookManager,也就是hook代码在先,防护在后,所以防护失效
2、先加载ZMHookManager 库 再加载 ZMHook,现在防护,再hook 就交互交换不到方法了,已经被防护住了
3、对于检测到对方的hook,采取的方法式 退出程序 exit !!

反hook方案:
5.1 定位反hook的 退出进程的 地方
5.2 hopper 查看 MacO 文件
5.3 hopper 修改内存地址,让防护的代码,找不到要交换的方法,就可以去hook了

你可能感兴趣的:(iOS逆向1024-防护进阶)