iOS代碼防護,反調(diào)試,反注入,防打包,日志處理

第一:反調(diào)試,修改main.m

#import <dlfcn.h>
#import <sys/types.h>

//定義一個函數(shù)指針用來接收動態(tài)加載出來的函數(shù)ptrace
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);

#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif

// 阻止調(diào)試器attach
void disable_gdb() {
    //第一個參數(shù)path為0時, 它會自動查找 $LD_LIBRARY_PATH,$DYLD_LIBRARY_PATH, $DYLD_FALLBACK_LIBRARY_PATH 和 當前工作目錄中的動態(tài)鏈接庫.
    void * handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
    //動態(tài)加載ptrace函數(shù),ptrace函數(shù)的參數(shù)個數(shù)和類型,及返回類型跟ptrace_ptr_t函數(shù)指針定義的是一樣的
    ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
    //執(zhí)行ptrace_ptr相當于執(zhí)行ptrace函數(shù)
    ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
    //關閉動態(tài)庫,并且卸載
    dlclose(handle);
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
        #ifndef DEBUG
                disable_gdb();
        #endif
        signal(SIGPIPE, SIG_IGN);
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

第二:反注入,定時查看(不能在開始只檢查一次)。原理為lib庫白名單檢查

//代碼防注入
bool HKCheckWhitelist(){
    int count = _dyld_image_count();
    NSArray * arr = @[@"libstdc++.tbd",...,@"libViewDebuggerSupport.dylib"];
    for (int i = 0; i < count; i++) {
        //遍歷拿到庫名稱!
        const char * imageName = _dyld_get_image_name(i);
        
        //系統(tǒng)的lib Debug庫 除外
        if (strstr(imageName, "/System/Library/Frameworks/") || strstr(imageName, "/Developer/")  ) {
            continue;
        }

        if (strstr(imageName, "libAppProxy") || strstr(imageName, "PacketTunnel")) {
            continue;
        }
        
        NSString *str= [NSString stringWithCString:imageName encoding:[NSString defaultCStringEncoding]];
        str = [str lastPathComponent];
        //應用本身除外
        if ([str isEqualToString:@"workspace"] ) {
            continue;
        }
        
        BOOL isMyLib = NO;
        for (NSString * libName in arr) {
            if ([libName containsString:str]) {
                isMyLib = YES;
            }
        }
        if (isMyLib == NO) {
            printf("lib已被修改==?。?s",imageName);
            TLogD(@"lib已被修改==??!%s",imageName);
            exit(0);
            return NO;
        }else{
            return YES;
        }
    }
    return YES;
}

第三:防止重簽打包的簡單驗證,原理為讀出打包的證書ID,然后和預埋的比較

+ (void)prepareEnv {
    NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
    if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedPath]) {
        NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSASCIIStringEncoding error:nil];
        NSArray *embeddedProvisioningLines = [embeddedProvisioning componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

        for (int i = 0; i < [embeddedProvisioningLines count]; i++) {
            if ([[embeddedProvisioningLines objectAtIndex:i] rangeOfString:@"application-identifier"].location != NSNotFound) {
                NSInteger fromPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"<string>"].location+8;
                NSInteger toPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"</string>"].location;

                NSRange range;
                range.location = fromPosition;
                range.length = toPosition - fromPosition;
                
                NSString *fullIdentifier = [[embeddedProvisioningLines objectAtIndex:i+1] substringWithRange:range];
                
                NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
                NSString *appIdentifier = [identifierComponents firstObject];

                // 對比簽名ID
                if ([appIdentifier caseInsensitiveCompare:@“*******”] != NSOrderedSame) {
                    exit(0);
                }
                break;
            }
        }
    }
}

第四:日志敏感信息。原理,利用fishhook,hook系統(tǒng)方法“NSLog”,進行過濾處理

#import "UIApplication+NSLog.h"
#import "fishhook.h"

@implementation UIApplication (NSLog)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //定義rebinding結構體
        /*
         struct rebinding {
         const char *name;//需要HOOK的函數(shù)名稱,字符串
         void *replacement;//替換到那個新的函數(shù)上(函數(shù)指針,也就是函數(shù)的名稱)
         void **replaced;//保存原始函數(shù)指針變量的指針(它是一個二級指針!)
         };
         */
        rebind_symbols((struct rebinding[1]){{"NSLog", new_NSLog, (void *)&orig_NSLog}}, 1);
    });
}


// orig_NSLog是原有方法被替換后 把原來的實現(xiàn)方法放到另一個地址中
// new_NSLog就是替換后的方法了
static void (*orig_NSLog)(NSString *format, ...);
void(new_NSLog)(NSString *format, ...) {
    va_list args;
    if(format) {
        va_start(args, format);
        NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
        DDLogInfo(@"Hook:%@", message); //使用DDLog保存日志到本地
        #ifndef DEBUG
             orig_NSLog(@"===%@", message);//debug狀態(tài)下打印日志方便查看
        #endif
        
        va_end(args);
    }
}

@end
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容