使用LD_PRELOAD防御pwn

前言

本文介绍使用 LD_PRELOAD 防御 线下赛中常见的漏洞。

github上的相关项目:

hook 了常用的函数

https://github.com/poliva/ldpreloadhook

正文

由于可能会不允许加载 脚本 ,所以用 c 来加载(可能需要加一些没有的东西凑大小)

#include <stdio.h>  
#include <unistd.h>  
  
int main(int arg,char **args)  
{  
  
    char *argv[]={"test",NULL};//传递给执行文件的参数数组,这里包含执行文件的参数   
  
    char *envp[]={"LD_PRELOAD=./libmy_printf.so",NULL};//传递给执行文件新的环境变量数组  
  
    execve("./test",argv,envp);  
   
}  

执行当前目录的 test 文件,同时设置 LD_PRELOAD=./libmy_printf.so, 运行时加载 libmy_printf.so

.

堆相关漏洞

使用 https://github.com/DhavalKapil/libdheap

#include <stdio.h>  
#include <unistd.h>  
  
int main(int arg,char **args)  
{  
  
    char *argv[]={"test",NULL};//传递给执行文件的参数数组,这里包含执行文件的参数   
  
    char *envp[]={"LD_PRELOAD=./libdheap.so", "LIBDHEAP_EXIT_ON_ERROR=1",NULL};//传递给执行文件新的环境变量数组  
    execve("./test",argv,envp);  
   
}  

LIBDHEAP_EXIT_ON_ERROR=1 检测到异常后就会退出。

格式化字符串

hook printfsnprintf过滤关键字

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
// gcc -shared -fPIC my_printf.c -o libmy_printf.so -ldl

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int fd = 0;

void log (char * buf) {

    if(!fd){
        fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND);
    }
  write(fd, buf, strlen(buf));
  write(fd, '\n', 1);
  sync();

}


void str_remove(char *src, char *target){

        char *p;    
        char c[81];
        char *dst[254]={0};
        while((p = strstr(src,target)) != NULL) { //strstr 找不到返回 NULL 
                *p = '\0'; // 指定连接下一步(连接函数)之前 a 的终止位置; 
                strcpy (c, p+strlen(target)); // strcat 函数中的两个传入参数的内存地址不能重叠,所以这里用 c 当作 temp 
                strcat (src, c);
        } 


}




int printf(const char *format, ...)
{
        va_list list;
        char *parg;
        typeof(printf) *old_printf;

        char *tmp = malloc(strlen(format) + 1);
        strcpy(tmp, format);

        

        /*

        remove some bad string

        */
        str_remove(tmp, "$p");
        str_remove(tmp, "$x");
        str_remove(tmp, "hn");
        str_remove(tmp, "ln");
        str_remove(tmp, "$n");
        log(tmp);

        // format variable arguments
        va_start(list, tmp);
        vasprintf(&parg, tmp, list);
        va_end(list);

        // get a pointer to the function "printf"
        old_printf = dlsym(RTLD_NEXT, "printf");
        (*old_printf)("%s", parg); // and we call the function with previous arguments

        free(parg);
        free(tmp);
}


int snprintf(char *str, size_t size, const char *format, ...){
        va_list list;
        char *parg;
        typeof(snprintf) *old_snprintf;

        char *tmp = malloc(strlen(format) + 1);
        strcpy(tmp, format);

        /*

        remove some bad string

        */
        str_remove(tmp, "$p");
        str_remove(tmp, "$x");
        str_remove(tmp, "hn");
        str_remove(tmp, "ln");
        str_remove(tmp, "$n");
        log(tmp);

        // format variable arguments
        va_start(list, tmp);
        vasprintf(&parg, tmp, list);
        va_end(list);
        
        // get a pointer to the function "printf"
        old_snprintf = dlsym(RTLD_NEXT, "snprintf");
        (*old_snprintf)(str, size, "%s", parg); // and we call the function with previous arguments

        free(parg);
        free(tmp);

}

使用

gcc -shared -fPIC my_printf.c -o libmy_printf.so -ldl

编译之(32 位 加 -m 32

猜你喜欢

转载自www.cnblogs.com/hac425/p/9416928.html