监控线程的 Mach 异常

xnu 采用了微内核的架构,

因此 Mach Message 与各模块都有着千丝万缕的联系,

异常也不例外。

如果想详细的学习 Mach Exception 是如何工作的,

其与 Unix Signal 的关系,

大家可以去阅读:

《Mac OS X Internals: A Systems Approach》

《Mac OS X and iOS Internals: To The Apple's Core》


这里给出一个监控某个线程 Mach Exception 的代码,

主要用于在发生异常时分析其他线程的状态,

并且可以用来构建基于异常的反调试机制。


#import 
#import 
#import 
#import 
#import 
#import 
#import 

mach_port_t gExceptionPort = 0;

static void *ExceptionHandler(void *ignored)
{
    mach_msg_return_t rc;
    printf("--------->Exc handler listening\n");
    
    typedef struct {
        mach_msg_header_t Head;
        mach_msg_body_t msgh_body;
        mach_msg_port_descriptor_t thread;
        mach_msg_port_descriptor_t task;
        NDR_record_t NDR;
        exception_type_t exception;
        mach_msg_type_number_t codeCnt;
        integer_t code[2];
        int flavor;
        mach_msg_type_number_t old_stateCnt;
        natural_t old_state[144];
    } Request;
    
    Request exc;
    for(;;) {
        rc = mach_msg(&exc.Head,
                      MACH_RCV_MSG | MACH_RCV_LARGE,
                      0,
                      sizeof(Request),
                      gExceptionPort,
                      MACH_MSG_TIMEOUT_NONE,
                      MACH_PORT_NULL);
        
        if(rc != MACH_MSG_SUCCESS) {
            return 0;
        };
        
        printf("--------->Got Message\n");
        exit(1);
    }
}

static void CatchMACHExceptions()
{
    kern_return_t rc = 0;
    exception_mask_t excMask = EXC_MASK_BAD_ACCESS; // !!!这里只是监控了异常读写,实际使用时需要根据需要进行修改!!!
    
    rc = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &gExceptionPort);
    if (rc != KERN_SUCCESS) {
        fprintf(stderr, "------->Fail to allocate exception port\n");
        exit(-1);
    }
    
    rc = mach_port_insert_right(mach_task_self(), gExceptionPort, gExceptionPort, MACH_MSG_TYPE_MAKE_SEND);
    if (rc != KERN_SUCCESS) {
        fprintf(stderr, "-------->Fail to insert right");
        exit(-2);
    }
    
    rc = thread_set_exception_ports(mach_thread_self(), excMask, gExceptionPort, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
    if (rc != KERN_SUCCESS) {
        fprintf(stderr, "-------->Fail to  set exception\n");
        exit(-3);
    }
    
    pthread_t thread;
    pthread_create(&thread, NULL, ExceptionHandler, NULL);
}


你可能感兴趣的:(监控线程的 Mach 异常)