您的位置:首页 > 其它

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

2013-04-18 17:32 344 查看
使用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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: