linux-inject:注入代码到运行的Linux进程中

1.下载代码

git clone https://github.com/gaffe23/linux-inject.git
cd linux-inject
make

2.开启2个终端,其中一个终端执行

cd ~/workspace/linux-inject,运行./sample-target

另外一个终端执行

sudo ./inject -n sample-target sample-library.so

注入sample-library.so到一个进程中,进程是通过-n name指定的sample-target。如果你需要注入到指定PID的进程,你可以使用-p PID的方式。

但这有可能无法工作,因为Linux3.4中有一个名为Yama的安全模块可以禁用 ptrace-based代码注入(或者是在代码注入期间有其他的拦截方式)。要想让它在这种情况下正常工作,你需要运行这些命令之一(出于安全考虑,我更喜欢第二个):再次尝试注入,你会在sample-target输出的“sleeping…”中看到“I just got loaded”。

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # 允许任何进程注入代码到相同用户启动的进程中,root用户可以注入所有进程echo 2 | sudo tee /proc/sys/kernel/yama/ptrace_scope # 只允许root用户注入代码

3.向目标进程注入自己实现的代码

#include <stdio.h>
__attribute__((constructor)) void hello() 
{    
	puts("Hello world!");
}

这段C语言代码应该很容易理解,attribute((constructor))可能会使人迷惑。它的意思是说在函数库加载之后尽快运行这个函数。换句话说,这个函数就是要注入到进程中的代码。

编译:

gcc -shared -fPIC -o libhello.so hello.c

首先需要运行sample-target,然后我们尝试注入:

sudo ./inject -n sample-target libhello.so

在长串的“sleeping…”中你应该会看到“Hello world!”。
4.延伸问题
如果你尝试循环puts(“Hello world!”);,它会不断打印"Hello world!",主程序在注入的library结束之前不会恢复运行。也就是说,你不会再看到“sleeping…
要解决这个问题,你可以将注入的代码运行在单独的线程中,例如下面这段修改的代码:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void* thread(void* a) {
    while (1) {
        puts("Hello world!");
        usleep(1000000);
    }
    return NULL;
}
__attribute__((constructor))
void hello() {
    pthread_t t;
    pthread_create(&t, NULL, thread, NULL);
}

它应该可以正常工作。但如果你注入sample-target,因为sample-target并没有链接libpthread这个库,因此,任何使用pthread的函数都不能正常工作。当然,如果你通过添加参数-lpthread链接了libpthread,它会正常工作。
如果我们不想重新编译目标程序,我们也可以使用一个linux-inject所依赖的函数:__libc_dlopen_mode()。为什么不是dlopen(),因为dlopen()需要链接libdl,而__libc_dlopen_mode()包含在标准C库中(这里是glibc).
这里是代码样例:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <dlfcn.h>
/* Forward declare these functions */
void* __libc_dlopen_mode(const char*, int);
void* __libc_dlsym(void*, const char*);
int   __libc_dlclose(void*);
void* thread(void* a) {
    while (1) {
        puts("Hello world!");
        usleep(1000000);
    }
}
__attribute__((constructor))
void hello() {
    /* Note libpthread.so.0. For some reason,
       using the symbolic link (libpthread.so) will not work */
    void* pthread_lib = __libc_dlopen_mode("libpthread.so.0", RTLD_LAZY);
    int(*pthread_lib_create)(void*,void*,void*(*)(void*),void*);
    pthread_t t;
    *(void**)(&pthread_lib_create) = __libc_dlsym(pthread_lib, "pthread_create");
    pthread_lib_create(&t, NULL, thread, NULL);
    __libc_dlclose(pthread_lib);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值