反除錯&反反除錯 -- 利用sysctl檢測偵錯程式是否存在

馬萬旻發表於2018-07-04

防護

當一個程式被除錯時,該程式會有一個標誌位來標記他正在被標記。sysctl函式可用於檢視當前程式的資訊。

  • 使用該函式,需要匯入系統庫#import <sys/sysctl.h>

  • 函式介紹

    /*
    函式的返回值若為0時,證明沒有錯誤,其他數字為錯誤碼。
    arg1 傳入一個陣列,該陣列中的第一個元素指定本請求定向到核心的哪個子系統。第二個及其後元素依次細化指定該系統的某個部分。
    arg2 陣列中的元素數目
    arg3 一個結構體,指向一個供核心存放該值的緩衝區,存放程式查詢結果
    arg4 緩衝區的大小
    arg5/arg6 為了設定某個新值,arg5引數指向一個大小為arg6引數值的緩衝區。如果不準備指定一個新值,那麼arg5應為一個空指標,arg6因為0.
    */
    int sysctl(int *, u_int, void *, size_t *, void *, size_t);
    複製程式碼
  • 函式使用

    int name[4];//存放位元組碼,查詢資訊
    name[0] = CTL_KERN;//核心檢視
    name[1] = KERN_PROC;//程式檢視
    name[2] = KERN_PROC_PID//程式ID
    name[3] = getpid();//獲取pid,據說這個可以直接傳0???
    
    struct kinfo_proc info;//接受程式查詢結果資訊的結構體
    size_t info_size = sizeof(info);//結構體的大小
    
    int proc_err = sysctrl(name, sizeof(name)/sizeof(*name), info, info_size, 0, 0);
    assert(proc_err == 0);//出現異常,出發斷言
    
    //info.kp_proc.p_flag中存放的是標誌位(二進位制),在proc.h檔案中有p_flag的巨集定義,通過&運算可知對應標誌位的值是否為0。(若結果值為0則對應標誌位為0)。其中P_TRACED為正在跟蹤除錯過程。
    ((info.kp_proc.p_flag & P_TRACED) != 0)的結果即為是否處於除錯狀態。
    複製程式碼

進攻

可以通過fishhook交換掉系統的sysctl函式,原始碼很少,網上分析很多。關於fishhook的更多東西,具體請百度,這裡直接使用。

程式碼如下:

//函式指標,儲存原方法。
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){
    int err = sysctl_p(name, namelen, info, infosize, newinfo, newinfosize);
    //判斷是否是查詢程式資訊
    if (namelen == 4
        &&name[0] == CTL_KERN
        &&name[1] == KERN_PROC
        &&name[2] == KERN_PROC_PID
        &&info
        &&((int)*infosize == sizeof(struct kinfo_proc))) {
        //接受結果的結構體
        struct kinfo_proc* sys_info = (struct kinfo_proc *)info;
        //通過標誌位確認是否為除錯狀態
        if ((sys_info->kp_proc.p_flag & P_TRACED) != 0) {
            //進行異或運算修改標誌位
            sys_info->kp_proc.p_flag ^= P_TRACED;
        }
    }
    return err;
}
複製程式碼

然後在+(void)load;方法中交換系統的sysctl方法

rebind_symbols((struct rebinding[1]){{"sysctl",mySysctl,(void *)&sysctl_p}}, 1);
複製程式碼

防護

對於fishhook交換系統函式的進攻方式,我們可以通過將sysctl函式呼叫放到動態庫中,以保證檢測函式可以在進攻注入的程式碼之前執行。動態庫的載入順序為Build Phases下的Link Binary With Libaraies中的排列順序。

相關文章