首页
社区
课程
招聘
[求助]ptrace No such process
发表于: 2016-11-15 16:44 6465

[求助]ptrace No such process

2016-11-15 16:44
6465
最近在学习用ptrace注入so到用户进程。昨天写了一个原生c程序用来当做被trace的目标,没有问题。
今天自己写了一个app(有一个libnative.so),想把这个libnative.so的内存中代码区的属性改为可写。但是发现注入原生c程序的代码一注入app就有问题了。
尝试了几次之后发现就连调用目标进程的mmap函数也不稳定,有时ptrace函数会失败,提示No such process

输出如下:
root@ido:/data/local # ./hook_s 5328                                           
params num:2
get_remote_fun_addr:fun[0xf72395ed], local[0xf7223000], remote[0xf7220000]
get_remote_fun_addr:fun[0xf728ef4d], local[0xf728e000], remote[0xf7396000]
get_remote_fun_addr:fun[0xf728ef55], local[0xf728e000], remote[0xf7396000]
get_remote_fun_addr:fun[0xf728f065], local[0xf728e000], remote[0xf7396000]
get remote fun addr,mmap :[0xf72365ed] dlopen :[0xf7396f4d], dlsym:[0xf7396f55], dlclose:[0xf7397065]
ptrace call ret status is 0
mmap return address :f02a5000
hook finish
root@ido:/data/local # ./hook_s 5328                                           
params num:2
get_remote_fun_addr:fun[0xf75795ed], local[0xf7563000], remote[0xf7220000]
get_remote_fun_addr:fun[0xf75cef4d], local[0xf75ce000], remote[0xf7396000]
get_remote_fun_addr:fun[0xf75cef55], local[0xf75ce000], remote[0xf7396000]
get_remote_fun_addr:fun[0xf75cf065], local[0xf75ce000], remote[0xf7396000]
get remote fun addr,mmap :[0xf72365ed] dlopen :[0xf7396f4d], dlsym:[0xf7396f55], dlclose:[0xf7397065]
ptrace call ret status is 0
mmap return address :f02a4000
hook finish
root@ido:/data/local # ./hook_s 5328                                           
params num:2
get_remote_fun_addr:fun[0xf73675ed], local[0xf7351000], remote[0xf7220000]
get_remote_fun_addr:fun[0xf73bcf4d], local[0xf73bc000], remote[0xf7396000]
get_remote_fun_addr:fun[0xf73bcf55], local[0xf73bc000], remote[0xf7396000]
get_remote_fun_addr:fun[0xf73bd065], local[0xf73bc000], remote[0xf7396000]
get remote fun addr,mmap :[0xf72365ed] dlopen :[0xf7396f4d], dlsym:[0xf7396f55], dlclose:[0xf7397065]
ptrace call ret status is 0
ptrace_getregs: No such process
hook finish


代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <asm/ptrace.h>
#include <dlfcn.h>

#define CPSR_T_MASK		( 1u << 5 )
#define ulong unsigned long

void* get_module_base(pid_t pid, const char *module_name)
{
    FILE *fp;
    unsigned long addr = 0;
    char *pch;
    char filename[32];
    char line[300];
    snprintf(filename, sizeof(filename),"/proc/%d/maps",pid);
    fp = fopen(filename,"r");
    if(fp != NULL)
    {
        while (fgets(line, sizeof(line),fp))
        {
            if(strstr(line,module_name))
            {
                pch = strtok(line,"-");
                addr = strtoul(pch,NULL,16);
                break;
            }
        }

        fclose(fp);

    }

    return  (void*) addr;

}

void* get_remote_fun_addr(pid_t target_pid, const char* module_name,void *local_fun_addr)
{
    void *local_handle, *remote_handle;
    local_handle = get_module_base(getpid(),module_name);
    remote_handle = get_module_base(target_pid,module_name);
    printf("get_remote_fun_addr:fun[%p], local[%p], remote[%p]\n",local_fun_addr,local_handle,remote_handle);
    return  (void*)((uint32_t)local_fun_addr - (uint32_t)local_handle + (uint32_t)remote_handle);
}

int ptrace_writedata(pid_t pid,long dest,char *data, size_t size)
{
    int  i, j, remain;
    char  *laddr;
    union {
        long  val;
        char chars[sizeof(ulong)];
    }d;
    j = (int) (size / 4);
    remain = (int) (size % 4);
    laddr = data;
    for ( i = 0; i < j; ++i) {
        memcpy(d.chars,laddr,4);
        if(ptrace(PTRACE_POKEDATA,pid,dest,d.val) == -1)
        {
            perror("ptrace_writedata: poke data error");
        }
        dest += 4;
        laddr+= 4;
    }
    if(remain > 0)
    {
        d.val = ptrace(PTRACE_PEEKDATA,pid,dest,0);
        for (i = 0; i<remain; ++i)
        {
            d.chars[i] = *laddr ++;
        }
        if(ptrace(PTRACE_POKEDATA,pid,dest,d.val) == -1)
        {
            perror("ptrace_writedata: poke remian data error");
        }
    }
    return 0;
}

int ptrace_getdata(pid_t pid,long dest,char *buffer,size_t size)
{
	union{
		long val;
		char chars[sizeof(long)];
	}d;
	int j = size/4;
	int remain = size%4;
	for(int i = 0; i<j ; ++i)
	{
		d.val = ptrace(PTRACE_PEEKDATA,pid,dest,NULL); 
		memcpy(buffer,d.chars,4);
		buffer+=4;
		dest+=4;
	}
	if(remain>0)
	{
		d.val = ptrace(PTRACE_PEEKDATA,pid,dest,NULL);
		memcpy(buffer,d.chars,remain);
	}
	return 0;
}

int ptrace_writestring(pid_t pid, long dest, char *str)
{
	return ptrace_writedata(pid,dest,str,strlen(str)+1);
}

int ptrace_setregs( pid_t pid, struct pt_regs *regs)
{
    if(ptrace(PTRACE_SETREGS,pid,NULL,regs) <0 )
    {
        perror("ptrace_setregs: Can't set register values");
        return -1;
    }
    return 0;
}

int ptrace_continue(pid_t pid) {
    if(ptrace(PTRACE_CONT,pid,NULL,NULL) < 0)
    {
        perror("ptrace_continue error");
        return -1;
    }
    return 0;
}


int ptrace_attach(pid_t pid)
{
	if(ptrace(PTRACE_ATTACH,pid)<0)
	{
		perror("ptrace_attach");
		return -1;
	}
	waitpid(pid,NULL,WUNTRACED);
	return 0;
}


int ptrace_dettach(pid_t pid)
{
	if(ptrace(PTRACE_DETACH,pid,NULL,NULL) < 0)
	{
		perror("ptrace dettach");
		return -1;
	}
	return 0;
}

int ptrace_getregs(pid_t pid,struct pt_regs *regs)
{
	if(ptrace(PTRACE_GETREGS,pid,NULL,regs) < 0)
	{
		perror("ptrace_getregs");
		return -1;
	}
	return 0;
}

int ptrace_call(pid_t pid, void* addr, long *params,int num_params, struct pt_regs *regs)
{
    int i;
    //前4个参数通过寄存器传递
    for (i = 0; i < num_params && i < 4 ; ++i)
    {
        regs->uregs[i] = params[i];
    }
    if(i < num_params)
    {
        regs->ARM_sp -= (num_params - i)*sizeof(long);
        ptrace_writedata(pid, regs->ARM_sp,(char*)¶ms[i], (num_params - i) * sizeof(long));
    }
    regs->ARM_pc = (long)addr;
    if(regs->ARM_pc & 1)
    {
        /* thumb指令 */
        regs->ARM_pc &= (~1u);
        regs->ARM_cpsr |= CPSR_T_MASK;
    }
    else
    {
        /* arm */
        regs->ARM_cpsr &= ~CPSR_T_MASK;
    }

    regs->ARM_lr = 0;

    if(ptrace_setregs(pid,regs) == -1
            || ptrace_continue(pid) == -1)
    {
        return -1;
    }

	int status = 0;
	waitpid(pid,&status,WUNTRACED);
	printf("ptrace call ret status is %d\n",status);
	
	//获取远程寄存器的值
	if(ptrace_getregs(pid,regs) == -1)
	{
		return -1;
	}
    return 0;
}

long ptrace_getret(struct pt_regs * regs)    	
{       
    return regs->ARM_r0;      
}

int main(int argc ,char **argv)
{
    
	printf("params num:%d\n",argc);
    pid_t target_pid = atoi(*(argv + 1));
	//路径信息
	char *libc_module = "/system/lib/libc.so";//搜索
	char *link_module = "/system/bin/linker";//搜索
	char *hook_module = "/data/local/libhook.so";//定位
    char *hook_fun = "start_hook";//搜索

	if(ptrace_attach(target_pid) == -1)
	{
		return EXIT_FAILURE;
	}
	//寄存器信息
	struct pt_regs regs,original_regs;
	//函数地址
	void *mmap_ddr, *dlopen_addr, *dlsym_addr, *dlclose_addr;
	//mmap分配内存地址
	long mmap_base;
	//保存寄存器信息
	if(ptrace_getregs(target_pid, ®s) == -1)
	{
		goto exit;	
	}
	memcpy(&original_regs,®s,sizeof(struct pt_regs));
	mmap_ddr = get_remote_fun_addr(target_pid,libc_module,(void*)mmap);
	dlopen_addr = get_remote_fun_addr(target_pid,link_module,(void*)dlopen);
	dlsym_addr  = get_remote_fun_addr(target_pid,link_module,(void*)dlsym);
	dlclose_addr= get_remote_fun_addr(target_pid,link_module,(void*)dlclose);
	printf("get remote fun addr,mmap :[%p] dlopen :[%p], dlsym:[%p], dlclose:[%p]\n",mmap_ddr,dlopen_addr,dlsym_addr,dlclose_addr);
	//参数数组
	long params[10];
	params[0] = 0;
	params[1] = 1024;
	params[2] = PROT_READ | PROT_WRITE | PROT_EXEC;
	params[3] = MAP_ANONYMOUS | MAP_PRIVATE;
	params[4] = 0;
	params[5] = 0;
	if(ptrace_call(target_pid,mmap_ddr,params,6,®s) == -1)
	{
		goto exit;	
	}
	//获取mmap新分配内存的首地址
	mmap_base = ptrace_getret(®s);
	printf("mmap return address :%lx\n",mmap_base);	
/*	//将libhook.so路径名写入tracee内存空间
	if(ptrace_writestring(target_pid,mmap_base,hook_module) < 0 )
	{
		goto exit;
	}
	char str_buffer[100];
	ptrace_getdata(target_pid,mmap_base,str_buffer,strlen(hook_module)+1);;
	printf("write module path result :%s\n",str_buffer);
	//dlopen函数参数
	params[0] = mmap_base;
	params[1] = RTLD_NOW | RTLD_GLOBAL;
	printf("----------------call remote dlopen with [%lx], [%lx]\n",params[0],params[1]);
	//调用dlopen函数
	if(ptrace_call(target_pid,dlopen_addr,params,2,®s) < 0 )
	{
		goto exit;
	}
	long hook_module_base = ptrace_getret(®s);
	printf("----------------load hook module at %lx\n",hook_module_base);
    //将调用函数的名字写入远程内存空间
	if(ptrace_writestring(target_pid,mmap_base,hook_fun) <0 )
	{
		goto exit;
	}
	ptrace_getdata(target_pid,mmap_base,str_buffer,strlen(hook_fun)+1);
	printf("write hook fun result :%s\n",str_buffer);
	//设置dlsym参数,返回值为远程函数地址
	params[0] = hook_module_base;
	params[1] = mmap_base;
	printf("call remote dlsym with [%lx], [%lx]\n",params[0],params[1]);
	if(ptrace_call(target_pid,dlsym_addr,params,2,®s) < 0)
	{
		goto exit;
	}
	long hook_fun_addr = ptrace_getret(®s);
	printf("----------------remote hook fun addr %lx\n",hook_fun_addr);
	
	if(ptrace_call(target_pid,(void*)hook_fun_addr,NULL,0,®s) < 0)
	{
		puts("can't call hook mudule function");
	} */ 
exit:
	if(ptrace_setregs(target_pid,&original_regs) == -1)
	{
		puts("can't resume registers");
	}
	ptrace_dettach(target_pid);
	puts("hook finish");
	return 0;
}


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

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 230
活跃值: (610)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
If  the  parent  process  would  like  the  child  to  stop  (for  example,  after  user  input  in  a  debugger),  it  can  simply  send  it  a  SIGSTOP  through  the  usual  methods.  Again,  technically  any  unused  signal  besides  SIGKILL  would  do  the  job,  but  its  best  to  avoid  ambiguity.  It  is  important  to  ensure  that  the  child  task  is  stopped  before  doing  anything  to  it;  otherwise  ptrace  will  return  an  ESRCH  error:  “no  such  process”.
目标进程必须是stopping的。
不知道有没有帮助
2018-3-7 01:25
0
游客
登录 | 注册 方可回帖
返回
//