首页
社区
课程
招聘
[原创]Linux so injector demo
发表于: 2013-11-4 16:40 5838

[原创]Linux so injector demo

2013-11-4 16:40
5838
我的英文名是 the king of demo,请叫我DEMO之王,谢谢
注入任意so动态链接库到指定pid进程,用法
so_injector  xxxxx.so target_pid


get_module_base
ptrace_writedata

这几个函数是直接copy的
http://bbs.pediy.com/showthread.php?t=141355

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>

#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <stdint.h>

void* get_module_base(pid_t pid, const char* module_name)
{
        FILE *fp;
        long addr = 0;
        char *pch;
        char filename[32];
        char line[1024];

        if (pid < 0) {
                /* self process */
                snprintf(filename, sizeof(filename), "/proc/self/maps");
        } else {
                snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
        }

        fp = fopen(filename, "r");
        if (fp == NULL)
                return NULL;

        while (fgets(line, sizeof(line), fp)) {
                if (strstr(line, module_name)) {
                        pch = strtok( line, "-");
                        addr = strtoul(pch, NULL, 16);

                        if (addr == 0x8000)
                                addr = 0;

                        break;
                }
        }

        fclose(fp);

        return (void *)addr;
}

int ptrace_writedata(pid_t pid, uint8_t *dest, uint8_t *data, size_t size)
{
        uint32_t i, j, remain;
        uint8_t *laddr;

        union u {
                long val;
                char chars[sizeof(long)];
        } d;

        j = size / 4;
        remain = size % 4;

        laddr = data;

        for (i = 0; i < j; i++) {
                memcpy(d.chars, laddr, 4);
                ptrace(PTRACE_POKETEXT, pid, dest, d.val);

                dest  += 4;
                laddr += 4;
        }

        if (remain > 0) {
                d.val = ptrace( PTRACE_PEEKTEXT, pid, dest, 0 );
                for (i = 0; i < remain; i++) {
                        d.chars[i] = *laddr++;
                }

                ptrace(PTRACE_POKETEXT, pid, dest, d.val);
        }

        return 0;
}

//libc  -> __libc_dlopen_mode
//libdl -> dlopen

void * __libc_dlopen_mode (const char *name, int mode);

#if __WORDSIZE == 64

#define REGS_IP(r)   r.regs.rip
#define REGS_SP(r)   r.regs.rsp
#define REGS_AX(r)   r.regs.rax

#else

#define REGS_IP(r)   r.regs.eip
#define REGS_SP(r)   r.regs.esp
#define REGS_AX(r)   r.regs.eax

#endif

int main(int argc, char** argv)
{
        pid_t pid = 0;
        int status = 0;
        struct user oregs, iregs;
        uintptr_t p, dlopen_addr;
        uint8_t *sp;

        if (argc < 3) {
                printf("usage:so_injector so_path target_pid\n");
                return -1;
        }

        pid = atoi(argv[2]);
        dlopen_addr = (uintptr_t)dlsym(NULL, "dlopen") +
                      ((uintptr_t)get_module_base(pid, "libdl") -
                       (uintptr_t)get_module_base(-1, "libdl"));

        printf("dlopen_addr:%p\n", (void*)dlopen_addr);

        if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0)
                return -1;

        waitpid(-1, &status, 0);

        ptrace(PTRACE_GETREGS, pid, NULL, &oregs);
        iregs = oregs;

        /*
         * write args to stacks
         * lib_name_string
         * arg2 mode
         * arg1 pLibName
         * ret_addr     <-      SP
         */
        REGS_SP(iregs) = REGS_SP(iregs) - 0x200;
        sp = (uint8_t *)REGS_SP(iregs);

        p = 0;
        ptrace_writedata(pid, sp, (uint8_t*)&p, sizeof(p));

        p = (uintptr_t)sp + 3*sizeof(size_t);
        ptrace_writedata(pid, sp + sizeof(size_t), (uint8_t*)&p, sizeof(p));

        p = RTLD_LAZY | RTLD_GLOBAL;
        ptrace_writedata(pid, sp + 2*sizeof(size_t), (uint8_t*)&p, sizeof(p));

        ptrace_writedata(pid, sp + 3*sizeof(size_t), (uint8_t*)argv[1], strlen(argv[1]) + 1);

#if __WORDSIZE == 64
        iregs.regs.rdi = (uintptr_t)sp + 3*sizeof(size_t);         //arg1
        iregs.regs.rsi = RTLD_LAZY | RTLD_GLOBAL;       //arg2
#endif

        REGS_IP(iregs) = dlopen_addr;
        REGS_AX(iregs) = 0;

        //ptrace continue
        ptrace(PTRACE_SETREGS, pid, NULL, &iregs);
        ptrace(PTRACE_CONT, pid, NULL, NULL);
        waitpid(pid, &status, 0);

        ptrace(PTRACE_GETREGS, pid, NULL, &iregs);
        printf("call dlopen_addr:%p ret %p %p %x\n",
               (void*)dlopen_addr,
               (void*)REGS_AX(iregs),
               (void*)REGS_IP(iregs),
               status
              );

        //restore context and exit
        ptrace(PTRACE_SETREGS, pid, NULL, &oregs);
        ptrace(PTRACE_CONT, pid, NULL, NULL);
        ptrace(PTRACE_DETACH, pid, NULL, NULL);

        return 0;
}

test.so是一个测试so,加载后就会在tmp目录下输出一个日志,ubuntu10.4 x64测试ok


[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 1491
活跃值: (975)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
2
代码是干嘛使的,楼主给介绍下撒
2013-11-4 16:52
0
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
3
重新编辑了下,就是一个so注入器,可以注入任意so到任意进程
2013-11-4 17:04
0
雪    币: 11
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
支持 32  and  64 ?
2013-11-4 17:27
0
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
5
支持,不过我没有实际编译测试32的,应该没问题
2013-11-4 17:51
0
雪    币: 297
活跃值: (235)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
6
表示看不懂
楼主是不是发错地方了
2013-11-4 19:46
0
雪    币: 1149
活跃值: (833)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
7
x32 改了一下古河的那份 ,用起来一直还算稳定
2013-11-4 20:44
0
游客
登录 | 注册 方可回帖
返回
//