JNI 反調試介紹

Author: Crystal

0X01 jni 反調試介紹

爲了避免我們的so文件被動態分析,我們通常在so中加入一些反調試代碼,常見的Java native反調試方法有以下幾種。 1、直接調用ptrace(PTRACE_TRACEME, 0, 0, 0)。 2、根據上面說的/proc/$pid/status中TracerPid行顯示調試程序的pid的原理, 可以寫一個方法檢查下這個值, 如果!=0就退出程序。 3、檢查代碼執行的間隔時間。 4、掃描常見調試器端口,看是否正在被調試。

0X02 環境搭建

Android 開發環境 : Android studio 2.2.2 Android NDK 開發 環境搭建: http://www.jianshu.com/p/d8cde65cb4f7

0x03 反調試技術實現

1.直接調用ptrace(PTRACE_TRACEME, 0, 0, 0) ptrace有一個很重要的特定:一個進程只能被一個進程調試。根據這個特點,只需要在自己的進程中調用ptrace就能一定程度上阻止被其他調試器調試。下面是jni 中代碼實現

代碼示例
void Debug_ptrace()
{
ptrace(PTRACE_TRACEME, 0, 0, 0);
}

2.根據/proc/$pid/status中TracerPid行顯示調試程序的pid的原理, 可以寫一個方法檢查下這個值(看TracerPid 有沒有進程附加在該進程上就退出程序)。

代碼示例
void Debug_TracerPid()
{
    int pid;
    FILE *fd;
    char filename[MAX];
    char line[MAX];
    pid = getpid();
    sprintf(filename, "/proc/%d/status", pid);// 讀取proc/pid/status中的TracerPid
    while (true) {
    fd = fopen(filename, "r");
    while (fgets(line, MAX, fd)) {
        if (strncmp(line, "TracerPid", 9) == 0) {
                int statue = atoi(&line[10]);
                LOGD("########## statue = %d,%s", statue, line);
                fclose(fd);
                if (statue != 0) {
                        LOGD("########## here");
                        int ret = kill(pid, SIGKILL);
                        LOGD("########## kill = %d", ret);
                        return;
                }
                break;
        }
    }
    sleep(CHECK_TIME);
    }
}
  1. 檢查代碼執行的間隔時間。返回的是毫秒時間,一般下斷點單步調試時間會變長,可以在關鍵代碼處加上時間判斷來達到反調試效果。 //計算代碼運行時間
代碼示例
int CalculateTime()
{
    long start, end;
    long a;
    //start time
    start = clock();
    //do something
    a = 255.0 / 16.0;
    //end time
    end = clock();
    long str = (end - start);
    return str;
}

4.掃描常見調試器端口,看是否正在被調試。IDA 常見附加調試端口爲23946端口,也可以添加其他常用調試器端口來檢測

代碼示例
int ScanPort()
{
    char szLines[1024] = {0};
    int nFind = 0;
    FILE *fp = fopen("/proc/net/tcp", "r");
    if (fp != NULL)
    {
            while (fgets(szLines, sizeof(szLines), fp))
            {           //23946端口
                    if (strstr(szLines, "00000000:5D8A"))
                    {
                            nFind = 1;
                            exit(0);
                    }
            }
            fclose(fp);
    }
    else
    {
            printf("fopen error\r\n");
    }
    if (nFind == 0)
    {
            return  0;
    }
    return 0;
} 

0x04 總結

至此,這些簡單的java native層反調試方法就總結到這裏。希望這篇文章能對需要的朋友有所幫助。

0X05 參考文獻

參考Android應用方法隱藏及反調試技術淺析的0×03反調試初探:http://www.freebuf.com/articles/terminal/80996.html 參考 jin 實現反調試 :http://burningcodes.net/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章