您的位置:首页 > 其它

使用injectso技术注入mtrace,对进程进行内存检测

2013-05-31 12:51 495 查看
在开发过程中,我们可以在程序中调用mtrace函数,来对内存管理进行跟踪。可如果已经编译好的程序,我们该如何进行跟踪呢?        这里,我们可以采用injectso技术,在程序外面使被跟踪的程序调用mtrace,来实现。    因为mtrace属于libc最基本的库,所以不必采用_dl_open来载入相应的库。            主要参考    http://blog.chinaunix.net/u/30686/showart_272157.html        #include    #include    #include    #include    #include    #include    #include    #include    #include    #include    #include    #define IMAGE_ADDR 0x08048000    void ptrace_readreg(int pid, struct user_regs_struct *regs);    void ptrace_writereg(int pid, struct user_regs_struct *regs);    struct user_regs_struct oldregs;    void ptrace_attach(int pid)    {     if(ptrace(PTRACE_ATTACH, pid, NULL, NULL)     waitpid(pid, NULL, WUNTRACED);         ptrace_readreg(pid, &oldregs);    }    void ptrace_cont(int pid)    {     int stat;     if(ptrace(PTRACE_CONT, pid, NULL, NULL)     while(!WIFSTOPPED(stat))     waitpid(pid, &stat, WNOHANG);    }    void ptrace_detach(int pid)    {     ptrace_writereg(pid, &oldregs);     if(ptrace(PTRACE_DETACH, pid, NULL, NULL)    void ptrace_write(int pid, unsigned long addr, void *vptr, int len)    {     int count;     long word;     count = 0;     while(count     if(errno != 0)     printf("ptrace_write failed\t %ld\n", addr + count);     }    }    void ptrace_read(int pid, unsigned long addr, void *vptr, int len)    {     int i,count;     long word;     unsigned long *ptr = (unsigned long *)vptr;     i = count = 0;     while (count    char * ptrace_readstr(int pid, unsigned long addr)    {     char *str = (char *) malloc(64);     int i,count;     long word;     char *pa;     i = count = 0;     pa = (char *)&word;     while(i     if (pa[0] == '\0') {     str = '\0';     break;     }     else     str[i++] = pa[0];     if (pa[1] == '\0') {     str = '\0';     break;     }     else     str[i++] = pa[1];     if (pa[2] == '\0') {     str = '\0';     break;     }     else     str[i++] = pa[2];     if (pa[3] == '\0') {     str = '\0';     break;     }     else     str[i++] = pa[3];     }         return str;    }    void ptrace_readreg(int pid, struct user_regs_struct *regs)    {     if(ptrace(PTRACE_GETREGS, pid, NULL, regs))     printf("*** ptrace_readreg error ***\n");         return ;    }    void ptrace_writereg(int pid, struct user_regs_struct *regs)    {     if(ptrace(PTRACE_SETREGS, pid, NULL, regs))     printf("*** ptrace_writereg error ***\n");         return ;    }    void * ptrace_push(int pid, void *paddr, int size)    {     unsigned long esp;     struct user_regs_struct regs;     ptrace_readreg(pid, ®s);     esp = regs.esp;     esp -= size;     esp = esp - esp % 4;     regs.esp = esp;     ptrace_writereg(pid, ®s);     ptrace_write(pid, esp, paddr, size);     return (void *)esp;    }    void ptrace_call(int pid, unsigned long addr)    {     void *pc;     struct user_regs_struct regs;     int stat;     void *pra;     pc = (void *) 0x41414140;     pra = ptrace_push(pid, &pc, sizeof(pc));     ptrace_readreg(pid, ®s);    // ptrace_readreg(pid, &oldregs);     regs.eip = addr;     ptrace_writereg(pid, ®s);     ptrace_cont(pid);     while(!WIFSIGNALED(stat))     waitpid(pid, &stat, WNOHANG);        // ptrace_writereg(pid,&oldregs);    // ptrace_cont(pid);    }    int nchains;    unsigned long symtab,strtab,jmprel,totalrelsize,relsize,nrels,dyn_addr;    struct link_map * get_linkmap(int pid)    {     Elf32_Ehdr *ehdr = (Elf32_Ehdr *) malloc(sizeof(Elf32_Ehdr));     Elf32_Phdr *phdr = (Elf32_Phdr *) malloc(sizeof(Elf32_Phdr));     Elf32_Dyn *dyn = (Elf32_Dyn *) malloc(sizeof(Elf32_Dyn));     Elf32_Word got;     struct link_map *map = (struct link_map *)malloc(sizeof(struct link_map));     int i = 0;     ptrace_read(pid, IMAGE_ADDR, ehdr, sizeof(Elf32_Ehdr));     long phdr_addr;     phdr_addr = IMAGE_ADDR + ehdr->e_phoff;     printf("phdr_addr\t %p\n", phdr_addr);     ptrace_read(pid, phdr_addr, phdr, sizeof(Elf32_Phdr));     while(phdr->p_type != PT_DYNAMIC)     ptrace_read(pid, phdr_addr += sizeof(Elf32_Phdr), phdr,     sizeof(Elf32_Phdr));     long dyn_addr = phdr->p_vaddr;     printf("dyn_addr\t %p\n", dyn_addr);     ptrace_read(pid, dyn_addr, dyn, sizeof(Elf32_Dyn));     while(dyn->d_tag != DT_PLTGOT) {     ptrace_read(pid, dyn_addr + i * sizeof(Elf32_Dyn), dyn, sizeof(Elf32_Dyn));     i++;     }     got = (Elf32_Word)dyn->d_un.d_ptr;     got += 4;     printf("GOT\t\t %p\n", got);     unsigned long map_addr;     ptrace_read(pid,(unsigned long)(got), &map_addr, 4);     printf("map_addr\t %p\n", map_addr);     ptrace_read(pid, map_addr, map, sizeof(struct link_map));         free(ehdr);     free(phdr);     free(dyn);     return map;    }    void get_sym_info(int pid, struct link_map *lm)    {     Elf32_Dyn *dyn = (Elf32_Dyn *) malloc(sizeof(Elf32_Dyn));     unsigned long dyn_addr;     int ret;     dyn_addr = (unsigned long)lm->l_ld;         ptrace_read(pid, dyn_addr, dyn, sizeof(Elf32_Dyn));     while(dyn->d_tag != DT_NULL){     switch(dyn->d_tag)     {     case DT_SYMTAB:     symtab = dyn->d_un.d_ptr;     //puts("DT_SYMTAB");     break;     case DT_STRTAB:     strtab = dyn->d_un.d_ptr;     //puts("DT_STRTAB");     break;     case DT_HASH:     nchains = 0;    // ptrace_read(pid, dyn->d_un.d_ptr + lm->l_addr + 4,&nchains, sizeof(nchains));     ptrace_read(pid, dyn->d_un.d_ptr + 4,&nchains, sizeof(nchains));     //puts("DT_HASH");     break;     case DT_JMPREL:     jmprel = dyn->d_un.d_ptr;     //puts("DT_JMPREL");     break;     case DT_PLTRELSZ:     //puts("DT_PLTRELSZ");     totalrelsize = dyn->d_un.d_val;     break;     case DT_RELAENT:     relsize = dyn->d_un.d_val;     //puts("DT_RELAENT");     break;     case DT_RELENT:     relsize = dyn->d_un.d_val;     //puts("DT_RELENT");     break;     }     ptrace_read(pid, dyn_addr += sizeof(Elf32_Dyn), dyn, sizeof(Elf32_Dyn));     }     nrels = totalrelsize / relsize;     free(dyn);    }    unsigned long find_symbol_in_linkmap(int pid, struct link_map *lm, char *sym_name)    {     Elf32_Sym *sym = (Elf32_Sym *) malloc(sizeof(Elf32_Sym));     int i;     char *str;     unsigned long ret;     get_sym_info(pid, lm);     if(nchains     if (!sym->st_name || !sym->st_size || !sym->st_value)     continue;     str = (char *) ptrace_readstr(pid, strtab + sym->st_name);     if (strcmp(str, sym_name) == 0) {     free(str);     str = ptrace_readstr(pid, (unsigned long)lm->l_name);     printf("lib name [%s]\n", str);     free(str);     break;     }     free(str);     }     if (i == nchains)     ret = 0;     else     ret = lm->l_addr + sym->st_value;     free(sym);     return ret;    }    unsigned long find_symbol(int pid, struct link_map *map, char *sym_name)    {     struct link_map *lm = (struct link_map *) malloc(sizeof(struct link_map));     unsigned long sym_addr;     char *str;         sym_addr = find_symbol_in_linkmap(pid, map, sym_name);     if (sym_addr)     return sym_addr;     if (!map->l_next) return 0;     ptrace_read(pid, (unsigned long)map->l_next, lm, sizeof(struct link_map));     sym_addr = find_symbol_in_linkmap(pid, lm, sym_name);     while(!sym_addr && lm->l_next) {     ptrace_read(pid, (unsigned long)lm->l_next, lm, sizeof(struct link_map));     str = ptrace_readstr(pid, (unsigned long)lm->l_name);     if(str[0] == '\0')     continue;     printf("[%s]\n", str);     free(str);     if ((sym_addr = find_symbol_in_linkmap(pid, lm, sym_name)))     break;     }     return sym_addr;    }    void get_dyn_info(int pid);    unsigned long find_sym_in_rel(int pid, char *sym_name)    {     Elf32_Rel *rel = (Elf32_Rel *) malloc(sizeof(Elf32_Rel));     Elf32_Sym *sym = (Elf32_Sym *) malloc(sizeof(Elf32_Sym));     int i;     char *str;     unsigned long ret;     get_dyn_info(pid);     for(i = 0; ir_info)) {     ptrace_read(pid, symtab + ELF32_R_SYM(rel->r_info) *     sizeof(Elf32_Sym), sym, sizeof(Elf32_Sym));     str = ptrace_readstr(pid, strtab + sym->st_name);     if (strcmp(str, sym_name) == 0) {     free(str);     break;     }     free(str);     }     }     if (i == nrels)     ret = 0;     else     ret = rel->r_offset;     free(rel);     return ret;    }    void get_dyn_info(int pid)    {     Elf32_Dyn *dyn = (Elf32_Dyn *) malloc(sizeof(Elf32_Dyn));     int i = 0;     ptrace_read(pid, dyn_addr + i * sizeof(Elf32_Dyn), dyn, sizeof(Elf32_Dyn));     i++;     while(dyn->d_tag){     switch(dyn->d_tag)     {     case DT_SYMTAB:     puts("DT_SYMTAB");     symtab = dyn->d_un.d_ptr;     break;     case DT_STRTAB:     strtab = dyn->d_un.d_ptr;     //puts("DT_STRTAB");     break;     case DT_JMPREL:     jmprel = dyn->d_un.d_ptr;     //puts("DT_JMPREL");     printf("jmprel\t %p\n", jmprel);     break;     case DT_PLTRELSZ:     totalrelsize = dyn->d_un.d_val;     //puts("DT_PLTRELSZ");     break;     case DT_RELAENT:     relsize = dyn->d_un.d_val;     //puts("DT_RELAENT");     break;     case DT_RELENT:     relsize = dyn->d_un.d_val;     //puts("DT_RELENT");     break;     }     ptrace_read(pid, dyn_addr + i * sizeof(Elf32_Dyn), dyn, sizeof(Elf32_Dyn));     i++;     }     nrels = totalrelsize / relsize;     free(dyn);    }    void call_dl_open(int pid, unsigned long addr, char *libname)    {     void *pRLibName;     struct user_regs_struct regs;     pRLibName = ptrace_push(pid, libname, strlen(libname) + 1);     ptrace_readreg(pid, ®s);     regs.eax = (unsigned long) pRLibName;     regs.ecx = 0x0;     regs.edx = RTLD_LAZY;     ptrace_writereg(pid, ®s);     ptrace_call(pid, addr);     puts("call _dl_open ok");    }    void call_mtrace(int pid,unsigned long addr)    {     ptrace_call(pid, addr);     puts("call mtrace ok");    }    int main(int argc, char *argv[])    {     int pid;     struct link_map *map;     char sym_name[256];     unsigned long sym_addr;     unsigned long new_addr,old_addr,rel_addr;    /* if((pid = fork())     /* ??????? */     ptrace_attach(pid);     map = get_linkmap(pid);    // sym_addr = find_symbol(pid, map, "_dl_open"); /* call _dl_open */    // printf("found _dl_open at addr %p\n", sym_addr);    // call_dl_open(pid, sym_addr, "/lib/i686/libc-2.3.2.so"); /* ???????? */         strcpy(sym_name, "mtrace"); /* intercept */     sym_addr = find_symbol(pid, map, sym_name);     printf("%s addr\t %p\n", sym_name, sym_addr);     call_mtrace(pid,sym_addr);     ptrace_detach(pid);     exit(0);    }        测试程序    #include    #include    #include    #include    int main(void)    {     pid_t pid=getpid();     printf("pid=%d\n",pid);     sleep(200);         printf("asdfasdfsdf\n");     char *p=(char*)malloc(10);     malloc(20);     free(p);         return 0;    }            本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30686/showart_277361.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: