注入检测,越狱检测笔记

+ (void)load {
    _dyld_register_func_for_add_image(&image_added);
    _dyld_register_func_for_remove_image(&image_removed);
}

#pragma mark - Callbacks

static void image_added(const struct mach_header *mh, intptr_t slide) {
    _print_image(mh, true);
}

static void image_removed(const struct mach_header *mh, intptr_t slide) {
    _print_image(mh, false);
}

#pragma mark - Logger

static void _print_image(const struct mach_header *mh, bool added) {
    Dl_info image_info;
    int result = dladdr(mh, &image_info);
    
    if (result == 0) {
        printf("Could not print info for mach_header: %p\n\n", mh);
        return;
    }
    
    const char *image_name = image_info.dli_fname;
    
    const intptr_t image_base_address = (intptr_t)image_info.dli_fbase;
    const uint64_t image_text_size = _image_text_segment_size(mh);
    
    char image_uuid[37];
    const uuid_t *image_uuid_bytes = _image_retrieve_uuid(mh);
    uuid_unparse(*image_uuid_bytes, image_uuid);
    
    const char *log = added ? "Added" : "Removed";
    printf("%s: 0x%02lx (0x%02llx) %s <%s>\n\n", log, image_base_address, image_text_size, image_name, image_uuid);
    
    /*
    if (strstr(image_name, "MobileSubstrate.dylib")) {
        // 自由发挥
        exit();
    }
    */
}

#pragma mark - Private

static uint32_t _image_header_size(const struct mach_header *mh) {
    bool is_header_64_bit = (mh->magic == MH_MAGIC_64 || mh->magic == MH_CIGAM_64);
    return (is_header_64_bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
}

static void _image_visit_load_commands(const struct mach_header *mh, void (^visitor)(struct load_command *lc, bool *stop)) {
    assert(visitor != NULL);
    
    uintptr_t lc_cursor = (uintptr_t)mh + _image_header_size(mh);
    
    for (uint32_t idx = 0; idx < mh->ncmds; idx++) {
        struct load_command *lc = (struct load_command *)lc_cursor;
        
        bool stop = false;
        visitor(lc, &stop);
        
        if (stop) {
            return;
        }
        
        lc_cursor += lc->cmdsize;
    }
}

static uint64_t _image_text_segment_size(const struct mach_header *mh) {
    static const char *text_segment_name = "__TEXT";
    
    __block uint64_t text_size = 0;
    
    _image_visit_load_commands(mh, ^ (struct load_command *lc, bool *stop) {
        if (lc->cmdsize == 0) {
            return;
        }
        if (lc->cmd == LC_SEGMENT) {
            struct segment_command *seg_cmd = (struct segment_command *)lc;
            if (strcmp(seg_cmd->segname, text_segment_name) == 0) {
                text_size = seg_cmd->vmsize;
                *stop = true;
                return;
            }
        }
        if (lc->cmd == LC_SEGMENT_64) {
            struct segment_command_64 *seg_cmd = (struct segment_command_64 *)lc;
            if (strcmp(seg_cmd->segname, text_segment_name) == 0) {
                text_size = seg_cmd->vmsize;
                *stop = true;
                return;
            }
        }
    });
    
    return text_size;
}

static const uuid_t *_image_retrieve_uuid(const struct mach_header *mh) {
    __block const struct uuid_command *uuid_cmd = NULL;
    
    _image_visit_load_commands(mh, ^ (struct load_command *lc, bool *stop) {
        if (lc->cmdsize == 0) {
            return;
        }
        if (lc->cmd == LC_UUID) {
            uuid_cmd = (const struct uuid_command *)lc;
            *stop = true;
        }
    });
    
    if (uuid_cmd == NULL) {
        return NULL;
    }
    
    return &uuid_cmd->uuid;
}

越狱检测 

extern char ** environ;

+ (BOOL)mgjpf_isJailbroken{//越狱检测
    //以下检测的过程是越往下,越狱越高级
    
    //    /Applications/Cydia.app, /privte/var/stash
    NSString *cydiaPath = @"/Applications/Cydia.app";
    NSString *aptPath = @"/private/var/lib/apt/";
    if ([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) {
        return YES;
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) {
        return YES;
    }
    
    //可能存在hook了NSFileManager方法,此处用底层C stat去检测
    struct stat stat_info;
    if (0 == stat("/Library/MobileSubstrate/MobileSubstrate.dylib", &stat_info)) {
         return YES;
    }
    if (0 == stat("/Applications/Cydia.app", &stat_info)) {
         return YES;
    }
    if (0 == stat("/var/lib/cydia/", &stat_info)) {
         return YES;
    }
    if (0 == stat("/var/cache/apt", &stat_info)) {
         return YES;
    }   
 
    char ** envir = environ;
    int index = 0;
    
    while(*envir)
    {
        int n;
        char *s1 = *envir;
        char *s2 = "MobileSubstrate";
        while (*s1)
        {
            for (n = 0; *(s1 + n) == *(s2 + n); n ++)
            {
                if (!*(s2 + n + 1))
                    index++;
            }
            s1++;
        }
        envir++;
    }
    
    if (index >0) {
        return YES;
    }

    //如果攻击者给MobileSubstrate改名,但是原理都是通过DYLD_INSERT_LIBRARIES注入动态库
    //那么可以,检测当前程序运行的环境变量
    char *env = getenv("DYLD_INSERT_LIBRARIES");
    if (env != NULL) {
        return YES;
    }
    
    return NO;
}

想在main之前执行
__attribute__((constructor)) void initFuc0()
{
 printf("initFuc0 \n");
}

系统重启时间
+ (long)bootTime{
#define MIB_SIZE 2
    int mib[2];
    size_t size;
    struct timeval  boottime;
    
    mib[0] = CTL_KERN;
    mib[1] = KERN_BOOTTIME;
    size = sizeof(boottime);
    if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != -1)
    {
        return boottime.tv_sec;
    }
    return 0;
}

参考
https://www.jianshu.com/p/1de663f64c05
https://www.dllhook.com/post/154.html

你可能感兴趣的:(注入检测,越狱检测笔记)