首页
社区
课程
招聘
[旧帖] [原创]Linux bin进程感染 0.00雪花
发表于: 2016-3-19 20:42 1976

[旧帖] [原创]Linux bin进程感染 0.00雪花

2016-3-19 20:42
1976
曾经逆过一个应用,核心逻辑在run 这是bin进程运行,run进程与主进程通信。run进程由 exec bin进程启动的。exec进程是由主进程启动的。当时需要对run这个进程进行hook,所以使用LD_PRELOAD  hook经exec对run进程感染,hook run进程。在此分享一下,有错误的地方感谢指出。
先给咱小白兄弟们引下路,篇幅问题想了解更多关于PRELOAD  hook麻烦移步到google。loader加载会把LD_PRELOAD 指向so中的符号覆盖相同符号名的符号,用自己的函数替换系统库的函数,实现PRELOAD  hook。
本次分享由4个c文件组成。exec 负责启动第一个bin 并指定LD_PRELOAD 参数为libmyfopen.so 这个so 中实现了两个函数,fopen() 与execve()。这两个函数定义与libc的fopen() 与execve()函数一样。所以系统再加载libc.so 时导出符号表fope()n与execve()就被libmyfopen.so这两个函数占了。run只负责启动run1。因为run的evecve()已经被hook,run调用execve()启动run1时,run1的fopen() 与execve()也被hook了。这些变化能从log输出看出来。
以下代码:
首先是exec.c //负责启动run 这个bin,并把自己的so 指定为LD_PRELOAD 参数。
#include <stdio.h>
#include <unistd.h>
#include <jni.h>
#include <android/log.h>
#define TAG "huacai_uncle"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

int main(int argc, char **argv) {
        char preload_lib[50];
        sprintf(preload_lib, "LD_PRELOAD=%s", argv[1]);
        LOGI("LD_PRELOAD=%s",argv[1]);
        char * const args[] = { "./run", NULL };
        char * const envs[] = { preload_lib, NULL };
        execve("./run", args, envs);
        LOGI("ex done.");
        return 0;
}

然后是run.c //第一个bin 这个bin启动第二个bin
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include<unistd.h>
#include<sys/types.h>
#include <jni.h>
#include <android/log.h>
#define TAG "huacai_uncle"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

int main(int argc, char **argv)
{

        FILE * handler = fopen("/data/local/tmp/run","r");
        if(handler != NULL){
                LOGI("run %s\n",getenv("LD_PRELOAD"));
        }
        char *const args[] = {"./run1",NULL};
        execve("./run1",args,NULL);
        LOGI("run done.");
        return 0;
}

最后是run1.c 这个bin
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include<unistd.h>
#include<sys/types.h>
#include <jni.h>
#include <android/log.h>
#define TAG "huacai_uncle"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

int main(int argc, char **argv)
{

        FILE * handler = fopen("/data/local/tmp/run1","r");
        printf("run1 done.");
        LOGI("run1 done.");
        return 0;
}

再看一下preload so. myfopen.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <jni.h>
#include <android/log.h>

#define TAG "huacai_uncle"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

FILE * fopen(const char * path, const char * mode) {
        if (path == NULL || strlen(path) == 0) {
                LOGI("preload hook fopen path is NULL");
                return NULL ;
        }
        LOGI("preload hook fopen path: %s   mode: %s", path, mode);
        FILE * (*FOPEN_FUNC)(const char * path, const char * mode) = NULL;
        void *handle;
        char *error;
        FILE *ret;
        //打开动态链接库
        handle = dlopen(LIB_PATH, RTLD_LAZY);
        if (!handle) {
                LOGI("can not dlopen /system/lib/libc.so");
                fprintf(stderr, "%s\n", dlerror());
        }
        //清除之前存在的错误
        dlerror();
        //获取一个函数
        FOPEN_FUNC = dlsym(handle, "fopen");
        if ((error = dlerror()) != NULL) {
                LOGI("can not dlsym fopen");
                fprintf(stderr, "%s\n", error);
        }
        //用原来的参数运行
        ret = (*FOPEN_FUNC)(path, mode);
        //关闭动态链接库
        dlclose(handle);
        return ret;
}

//---------------------hook exec----------------------//
int execve(const char *filename, char * const argv[], char * const envp[]) {
        LOGI("preload hook execve filename: %s", filename);
        int (*EXECVE_FUNC)(const char *filename, char * const argv[],
                        char * const envp[]) = NULL;
        void *handle;
        char *error;
        int ret;
        //打开动态链接库
        handle = dlopen("/system/lib/libc.so", RTLD_LAZY);
        if (!handle) {
                LOGI("can not dlopen /system/lib/libc.so");
                fprintf(stderr, "%s\n", dlerror());
        }
        //清除之前存在的错误
        dlerror();
        //获取一个函数
        EXECVE_FUNC = dlsym(handle, "execve");
        if ((error = dlerror()) != NULL) {
                LOGI("can not dlsym execve");
                fprintf(stderr, "%s\n", error);
        }
        char * const envs[] = { "LD_PRELOAD=/data/local/tmp/libmyfopen.so", NULL };
        //用原来的参数运行
        ret = (*EXECVE_FUNC)(filename, argv, envs);
        //关闭动态链接库
        dlclose(handle);
        return ret;
}

实际操作:
把exec run run1 libmyfopen.so push进/data/local/tmp/
root@g2:/data/local/tmp # ./exec /data/local/tmp/libmyfopen.c

输出:
tag: huacai_uncle
LD_PRELOAD=/data/local/tmp/libmyfopen.so
preload hook fopen path: /data/local/tmp/run   mode: r
run /data/local/tmp/libmyfopen.so
preload hook execve filename: ./run1
preload hook fopen path: /data/local/tmp/run1   mode: r
run1 done.

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//