注册 登录
自由的生活_软路由 返回首页

心想事成的个人空间 https://bbs.routerclub.com/?681 [收藏] [复制] [分享] [RSS]

日志

基于ARM的Ptrace (二)

已有 914 次阅读2013-4-6 12:59

上次在研究Ptrace for Android的时候漏了一个东西,如何hook并修改除了Syscall 以外的函数,今天顺便实现一下。

平台:Android 2.3.3

目标:利用Ptrace拦截进程的自定义函数并修改逻辑。


先看目标进程,代码相当简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
         
int flag = 1;
int count = 0;
         
int sub()
{
    printf("Sub call.\n");
    return 1;
}
         
int main()
{   
    while(flag)
    {
        printf("Sub return:%d\n", sub());
        count++;
        sleep(3);
    }
    return 0;
}

我们要做的是拦截自定义函数sub(),修改函数,跳过printf语句并把返回值改成2.

基本思路是利用Ptrace attach 以后找到函数代码段的入口点,修改相应的代码即可。如何找到函数入口点?静态看或者动态调都可以。我们代码简单,静态看就好了。


静态看的过程并不如想象的顺利,原因是IDA这货真心坑爹,解析Thumb和ARM的混合代码竟然会出错:



只好手动修改一下便于查看:


一目了然,0x84D0处开始返回指针压栈,我们只需要从0x84D2开始把代码改成如下就可以了:

1
2
MOVS R0, #2
POP {R3, PC}


因而得出trace的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
    
int long_size = sizeof(long);
    
void putdata(pid_t pid, long addr,
        char *str, int len)
{   
    char *laddr;
    int i, j;
    union u {
        long val;
        char chars[long_size];
    }data;
    i = 0;
    j = len / long_size;
    laddr = str;
    while(i < j) {
        memcpy(data.chars, laddr, long_size);
        ptrace(PTRACE_POKEDATA, pid,
                addr + i * 4, data.val);
        ++i;
        laddr += long_size;
    }
    j = len % long_size;
    if(j != 0) {
        memcpy(data.chars, laddr, j);
        ptrace(PTRACE_POKEDATA, pid,
                addr + i * 4, data.val);
    }
}
    
void tracePro(int pid)
{
    int len = 4;
    char insertcode[] = "\x02\x20\x08\xBD";
        
    putdata(pid, 0x84d2, insertcode, len);
}
    
int main(int argc, char *argv[])
{   
    if(argc != 2) {
        printf("Usage: %s <pid to be traced>\n", argv[0], argv[1]);
    return 1;
    }
        
    pid_t traced_process;
    int status;
    traced_process = atoi(argv[1]);
    if(0 != ptrace(PTRACE_ATTACH, traced_process, NULL, NULL))
    {
        printf("Trace process failed:%d.\n"errno);
    return 1;
    }
        
    tracePro(traced_process);
    ptrace(PTRACE_DETACH, traced_process, NULL, NULL);
    return 0;
}


上传至模拟器调试,一次成功:




路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )

GMT+8, 2024-5-10 19:25 , Processed in 0.142524 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2023 Discuz! Team.

返回顶部