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

使用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, &regs);
    esp = regs.esp;
    esp -= size;
    esp = esp - esp % 4;
    regs.esp = esp;
    ptrace_writereg(pid, &regs);
    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, &regs);
//    ptrace_readreg(pid, &oldregs);
    regs.eip = addr;
    ptrace_writereg(pid, &regs);
    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, &regs);
    regs.eax = (unsigned long) pRLibName;
    regs.ecx = 0x0;
    regs.edx = RTLD_LAZY;
    ptrace_writereg(pid, &regs);
    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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值