美文网首页iOS 源码解析
iOS 反反调试之sysctl

iOS 反反调试之sysctl

作者: 萌小菜 | 来源:发表于2017-05-08 12:03 被阅读1530次

    前几天在调试某被注入过dylib的WX时,由于本人刚刚接触逆向,对该方面知识不够,碰到了点问题被困扰了两天,现已解决,特此分享给新手供参考。

    先说说遇到的问题现象:

    • 在正常状态下该ipa包能正常安装正常运行,且会一直停留在登录界面让输入授权码。
    • debugserver 能正常附加,lldb也能正常连接,但是在连接成功后再c后过大约5s后app崩溃。lldb输出:Process 11155 exited with status = 10 (0x0000000a)
      如下:
    (lldb) process connect connect://0000000:1234
    Process 11155 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
        frame #0: 0x00000001819c8fd8 libsystem_kernel.dylib`mach_msg_trap + 8
    libsystem_kernel.dylib`mach_msg_trap:
    ->  0x1819c8fd8 <+8>: ret    
    
    libsystem_kernel.dylib`mach_msg_overwrite_trap:
        0x1819c8fdc <+0>: mov    x16, #-0x20
        0x1819c8fe0 <+4>: svc    #0x80
        0x1819c8fe4 <+8>: ret    
    (lldb) c
    Process 11155 resuming
    Process 11155 exited with status = 10 (0x0000000a) 
    

    系统 log输出如下:

    May  7 19:55:27 iPhone WeChat[11484] <Error>: +[MicroMessengerAppDelegate application:didRegisterForRemoteNotificationsWithDeciceToken:]: unrecognized selector sent to class 0x103b37ce0
    May  7 19:55:28 iPhone mediaserverd[5349] <Notice>: '' com.cjwj.xin(pid = 11484) setting DiscoveryMode = DiscoveryMode_None, currentDiscoveryMode = DiscoveryMode_None
    May  7 19:55:28 iPhone SpringBoard[11461] <Warning>: UNNotificationSchedulerConnectionListener connection invalidated
    May  7 19:55:28 iPhone SpringBoard[11461] <Warning>: UNNotificationRegistrarConnectionListener connection invalidated
    May  7 19:55:28 iPhone SpringBoard[11461] <Warning>: HW kbd: Failed to set (null) as keyboard focus
    May  7 19:55:28 iPhone com.apple.xpc.launchd[1] (UIKitApplication:com.cjwj.xin[0x77fd][11484]) <Warning>: Service exited with abnormal code: 10
    May  7 19:55:28 iPhone com.apple.debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-340.3.124
        [11487] <Warning>: 1 +0.000000 sec [2cdf/3b03]: error: ::read ( 6, 0x16e35ea38, 1024 ) => -1 err = Bad file descriptor (0x00000009)
    May  7 19:55:28 iPhone SpringBoard[11461] <Warning>: Application 'UIKitApplication:com.cjwj.xin[0x77fd]' exited voluntarily.
    May  7 19:55:28 iPhone UserEventAgent[456] <Warning>: 14334655851519: id=com.cjwj.xin pid=11484, state=0
    May  7 19:55:37 iPhone kernel[0] <Notice>: AppleHDQGasGauge:stats num_clients=1,num_entries=617313,dl_skip=0,dl_cali=0,dl_over=0,dl_drain=27 ops=3615206,collated=0,bfailures=2,collate_error=0,ioerr=0,timeouts=97 retry16=210,chf16=29
    May  7 19:55:37 iPhone kernel[0] <Notice>: AppleHDQGasGauge:clientLog ld=593121808/d28 le=593122346/e30
    May  7 19:55:37 iPhone kernel[0] <Notice>: AppleHDQGasGauge:clientLog 495657400/T20 495657400/C20 495657667/S27 566137324/T26 566137324/d26 566137324/C26 566137857/S28 566137857/e28 566661472/T27
    May  7 19:55:37 iPhone kernel[0] <Notice>: AppleHDQGasGauge:clientLog 566661472/C27 566661717/S29 593121808/T28 593121808/d28 593121808/C28 593122346/S30 593122346/e30
    
    

    分析

    正常运行的时候没问题,一连接lldb就崩溃,这种情况一般都是加了反调试。但是作为逆向菜鸟的我来说之前只听说过ptrace反调试,但是加了ptrace断点后并没有发现,所以可以排除ptrace了。然后通过各种google 百度后发现了另一种反调试方法:sysctl。下断点,运行,断在了sysctl,再看下调用栈,的确是注入的dylib调用的:

    (lldb) process connect connect://20.20.20.20:1234
    Process 11611 stopped
    * thread #1, stop reason = signal SIGSTOP
        frame #0: 0x00000001819c8fd8 libsystem_kernel.dylib`mach_msg_trap + 8
    libsystem_kernel.dylib`mach_msg_trap:
    ->  0x1819c8fd8 <+8>: ret    
    
    libsystem_kernel.dylib`mach_msg_overwrite_trap:
        0x1819c8fdc <+0>: mov    x16, #-0x20
        0x1819c8fe0 <+4>: svc    #0x80
        0x1819c8fe4 <+8>: ret    
    (lldb) b sysctl
    Breakpoint 1: where = libsystem_c.dylib`sysctl, address = 0x00000001818f6a3c
    (lldb) c
    Process 11611 resuming
    Process 11611 stopped
    * thread #4, stop reason = breakpoint 1.1
        frame #0: 0x00000001818f6a3c libsystem_c.dylib`sysctl
    libsystem_c.dylib`sysctl:
    ->  0x1818f6a3c <+0>:  stp    x29, x30, [sp, #-0x10]!
        0x1818f6a40 <+4>:  mov    x29, sp
        0x1818f6a44 <+8>:  ldr    w8, [x0]
        0x1818f6a48 <+12>: cmp    w8, #0x8                  ; =0x8 
    (lldb) bt
    * thread #4, stop reason = breakpoint 1.1
      * frame #0: 0x00000001818f6a3c libsystem_c.dylib`sysctl
        frame #1: 0x0000000106387f1c libwsp.dylib`_bookIn + 146376
        frame #2: 0x0000000106394698 libwsp.dylib`_bookIn + 197444
        frame #3: 0x00000001818954bc libdispatch.dylib`_dispatch_call_block_and_release + 24
        frame #4: 0x000000018189547c libdispatch.dylib`_dispatch_client_callout + 16
        frame #5: 0x00000001818a14c0 libdispatch.dylib`_dispatch_queue_drain + 864
        frame #6: 0x0000000181898f80 libdispatch.dylib`_dispatch_queue_invoke + 464
        frame #7: 0x000000018189547c libdispatch.dylib`_dispatch_client_callout + 16
        frame #8: 0x00000001818a3914 libdispatch.dylib`_dispatch_root_queue_drain + 2140
        frame #9: 0x00000001818a30b0 libdispatch.dylib`_dispatch_worker_thread3 + 112
        frame #10: 0x0000000181aad470 libsystem_pthread.dylib`_pthread_wqthread + 1092
        frame #11: 0x0000000181aad020 libsystem_pthread.dylib`start_wqthread + 4
    (lldb) 
    
    

    接下来就是编写tweak干掉反调试,如下:

    #import <sys/sysctl.h>
    #import <sys/proc.h>
    #import <substrate.h>
    
     int (*old__sysctl)(int *name, u_int num, void* buffer, size_t *bufferSize, void *set0, size_t set1);
    
     int new_sysctl(int *name, u_int num, void* buffer, size_t *bufferSize, void *set0, size_t set1) {
        NSLog(@"========================new_sysctl");
        int result =  old__sysctl(name, num, buffer, bufferSize, set0, set1);
        size_t info_size = sizeof(struct kinfo_proc);
        if(info_size == *bufferSize){
            NSLog(@"info_size == buffer_size");
            int * flag = (int*)buffer+(0x20/sizeof(int));
            *flag = ~P_TRACED;
        }
        return result;
    }
    
    
    %ctor {
            MSHookFunction((void *)sysctl, (void *)&new_sysctl, (void **)&old__sysctl);
    }
    

    编译打包安装,再连接lldb,一切正常运行。完工!

    下面再补充下上面tweak中0x20的来源:

    sysctl反调试是利用sysctl函数查看内核进程状态标志,判断是否是被调试状态,当进程被调试的时候info.kp_proc.p_flag会变成P_TRACED,所以就可以通过sysctl查询进程相应的kinfo_proc信息就可以判断是否是在被调试状态,我们只需要在函数返回时修改p_flag = ~P_TRACED就可以让sysctl返回未在调试状态。

    0x20是内核进程状态标志(p_flag)相对于内核进程状态模型(struct kinfo_proc) 的偏移。可以通过下面方法获取:

    • 首先在Xcode中输入下面一行,然后打个断点


      1.png
    • 当断点住下后用lldb打印:


      2.png
    • $1 - $0 = 0x20

    如有错误欢迎评论指正。

    参考:

    http://bbs.iosre.com/t/sysctl-lldb-gdb/1953
    https://coredump.gr/articles/ios-anti-debugging-protections-part-2/

    相关文章

      网友评论

        本文标题:iOS 反反调试之sysctl

        本文链接:https://www.haomeiwen.com/subject/wzdmtxtx.html