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/

猜你喜欢

转载自blog.csdn.net/u014715599/article/details/81221040
JNI
今日推荐