首页
社区
课程
招聘
[分享]Android古河注入代码有关crash的问题
发表于: 2015-1-7 17:54 10084

[分享]Android古河注入代码有关crash的问题

2015-1-7 17:54
10084
最近用了古河大哥的有关Inject注入的代码,发现会常出现crash的问题。
通过研究debuggerd发现,其实古河大哥写的inject对进程attach_status只是做了一些简单的判断。
其实,crash问题出现的根本原因是因为系统调用的阻塞导致的,在debuggerd源码内有相关的解决办法,就是对tid线程进行PTRACE_ATTACH,知道发生SIGSTOP后再注入。这个过程如果没做好,就执行ptrace_cont肯定会撞车的。进程没有发出SIGSTOP就表示本次ATTACH没成功。

因此,只需要模仿debuggerd的代码局部调整一下就OK了。

tid_attach_status = ptrace(PTRACE_ATTACH, tid, 0, 0);
    int ptrace_error = errno;
if(tid_attach_status < 0) {
//这里的错误是指ATTACH失败,导致的原因可能是对方进程有反ATTACH的功能,
//或者根本没有此进程,并不是导致crash的根本原因
        LOG("ptrace attach failed: %s\n", strerror(ptrace_error));
        goto done;
    }
//一旦ATTACH成功了,就不需要再次PTRACE_ATTACH了,一直监听status吧
//底下来自debuggerd源码,不可直接使用,还要结合古河大哥的代码才行
const int sleep_time_usec = 200000;         /* 0.2 seconds */
    const int max_total_sleep_usec = 3000000;   /* 3 seconds */
    int loop_limit = max_total_sleep_usec / sleep_time_usec;
    for(;;) {
        if (loop_limit-- == 0) {
            LOG("timed out waiting for pid=%d tid=%d uid=%d to die\n",
                cr.pid, tid, cr.uid);
            goto done;
        }
        n = waitpid(tid, &status, __WALL | WNOHANG);

        if (n == 0) {
            /* not ready yet */
            XLOG("not ready yet\n");
            usleep(sleep_time_usec);
            continue;
        }

        if(n < 0) {
            if(errno == EAGAIN) continue;
            LOG("waitpid failed: %s\n", strerror(errno));
            goto done;
        }

        XLOG("waitpid: n=%d status=%08x\n", n, status);

        if(WIFSTOPPED(status)){
            n = WSTOPSIG(status);
            switch(n) {
            case SIGSTOP:
               //关键时刻来了,既然对方已经被你HOOL住了,开始干活了。
                XLOG("stopped -- continuing\n");
                n = ptrace(PTRACE_CONT, tid, 0, 0);
                if(n) {
                    LOG("ptrace failed: %s\n", strerror(errno));
                    goto done;
                }
                continue;
            //买糕的,这下面要是出问题了,就表示你HOOL住的对象被人抢了。我做过一个测试,
//注入了com.android.settings。当我在干活的时候还没干完,我操作了settings界面,
//又crash了。不知道大家有没有关于crash修复的东西,或者什么别的办法来避免这类操作的异常。
            case SIGILL:
            case SIGABRT:
            case SIGBUS:
            case SIGFPE:
            case SIGSEGV:
            case SIGSTKFLT: {
                XLOG("stopped -- fatal signal\n");
                need_cleanup = engrave_tombstone(cr.pid, tid, debug_uid, n);
                kill(tid, SIGSTOP);
                goto done;
            }

            default:
                XLOG("stopped -- unexpected signal\n");
                goto done;
            }
        } else {
            XLOG("unexpected waitpid response\n");
            goto done;
        }
    }

另外debuggerd还千叮万嘱的告诉大家,你的父进程别忘了把一些信号屏蔽,否则,对方进程一抛出如下信号,你就死定了。
signal(SIGILL, SIG_DFL);
    signal(SIGABRT, SIG_DFL);
    signal(SIGBUS, SIG_DFL);
    signal(SIGFPE, SIG_DFL);
    signal(SIGSEGV, SIG_DFL);
    signal(SIGSTKFLT, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
以上代码必须在你的main函数内,在inject干活之前执行。

因为我主要做的是注入com.android.settings,不知道怎么的老是会自动kill掉,导致我已经注入的代码还要重新注入,这时候如果用户在操作settings界面,那就会出现crash。这类问题有什么好的解决办法呢?

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 203
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
经常碰到crash问题,百度有文章说是寄存器的问题
2015-7-8 14:45
0
游客
登录 | 注册 方可回帖
返回
//