使用injectso 技术注入mtrace,对进程进行内存检测。 | |
| |
来源: ChinaUnix博客 日期: 2007.04.13 17:28 (共有条评论) 我要评论 | |
在开发过程中,我们可以在程序中调用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; } |
使用injectso 技术注入mtrace,对进程进行内存检测
最新推荐文章于 2021-04-29 03:46:02 发布