没有将free的指针设为null——UAF漏洞

UAF

UAF 又名 use after free
意思就是使用了已经被free过的堆

  • 如果内存被释放了之后 这个指针如果没有被设为NULL 之后又被使用了就又很大的可能可以继续正常运行
  • 当又有程序对那片地方进行了修改,在继续运行就会发生很奇怪的问题
    简单的例子
#include 
#include 
typedef struct name {
  char *myname;
  void (*func)(char *str);
} NAME;
void myprint(char *str) { printf("%s\n", str); }
void printmyname() { printf("call print my name\n"); }
int main() {
  NAME *a;
  a = (NAME *)malloc(sizeof(struct name));
  a->func = myprint;
  a->myname = "I can also use it";
  a->func("this is my function");
  // free without modify
  free(a);
  a->func("I can also use it");
  // free with modify
  a->func = printmyname;
  a->func("this is my function");
  // set NULL
  a = NULL;
  printf("this pogram will crash...\n");
  a->func("can not be printed...");
}

运行结果

this is my function
I can also use it
call print my name
this pogram will crash...
[1]    38738 segmentation fault (core dumped)  ./use_after_free

发现当a的指针没有变为NULL时指向的那片地址还是可以继续使用

  • 注意
  • uaf的前提这个变量最好是全局变量,存储到bss段上的时候才更容易的使用,因为在一个函数里面uaf 只会存储在栈上就不能一直使用

看一段代码

#include 
#include 
#include 

struct note {
    void (*printnote)();
    char *content ;
};

struct note *notelist[5];
int count = 0; 

void print_note_content(struct note *this){
    puts(this->content);
}
void add_note(){
    int i ;
    char buf[8];
    int size ;
    if(count > 5){
        puts("Full");
        return ;
    }
    for(i = 0 ; i < 5 ; i ++){
        if(!notelist[i]){
            notelist[i] = (struct note*)malloc(sizeof(struct note));
            if(!notelist[i]){
                puts("Alloca Error");
                exit(-1);
            }
            notelist[i]->printnote = print_note_content;
            printf("Note size :");
            read(0,buf,8);
            size = atoi(buf);
            notelist[i]->content = (char *)malloc(size);
            if(!notelist[i]->content){
                puts("Alloca Error");
                exit(-1);
            }
            printf("Content :");
            read(0,notelist[i]->content,size);
            puts("Success !");
            count++;
            break;
        }
    }
}

void del_note(){
    char buf[4];
    int idx ;
    printf("Index :");
    read(0,buf,4);
    idx = atoi(buf);
    if(idx < 0 || idx >= count){
        puts("Out of bound!");
        _exit(0);
    }
    if(notelist[idx]){
        free(notelist[idx]->content);
        free(notelist[idx]);
        puts("Success");
    }
}

void print_note(){
    char buf[4];
    int idx ;
    printf("Index :");
    read(0,buf,4);
    idx = atoi(buf);
    if(idx < 0 || idx >= count){
        puts("Out of bound!");
        _exit(0);
    }
    if(notelist[idx]){
        notelist[idx]->printnote(notelist[idx]);
    }
}

void magic(){
    system("cat /home/hacknote/flag");
}


void menu(){
    puts("----------------------");
    puts("       HackNote       "); 
    puts("----------------------");
    puts(" 1. Add note          ");
    puts(" 2. Delete note       ");
    puts(" 3. Print note        ");
    puts(" 4. Exit              ");
    puts("----------------------");
    printf("Your choice :");
};

int main(){
    setvbuf(stdout,0,2,0);
    setvbuf(stdin,0,2,0);
    char buf[4];
    while(1){
        menu();
        read(0,buf,4);
        switch(atoi(buf)){
            case 1 :
                add_note();
                break ;
            case 2 :
                del_note();
                break ;
            case 3 :
                print_note();
                break ;
            case 4 :
                exit(0);
                break ;
            default :
                puts("Invalid choice");
                break ;

        }
    }
    return 0;
}

代码只有125行是个很简单的笔记本功能
有一个magic函数在代码中没有被使用是用来读取/home/hacknote/flag内容的

void del_note(){
    char buf[4];
    int idx ;
    printf("Index :");
    read(0,buf,4);
    idx = atoi(buf);
    if(idx < 0 || idx >= count){
        puts("Out of bound!");
        _exit(0);
    }
    if(notelist[idx]){
        free(notelist[idx]->content);
        free(notelist[idx]);
        puts("Success");
    }
}

可以看到notelist[idx]没有被设置为NULL
所以按照之前的问题我们仍然可以调用

void print_note_content(struct note *this){
    puts(this->content);
}

这个函数



调用了之后发现存在错误调试一下



因为free了之后那块内存为0了所以调用的时候就会报错,我们也无法直接在哪个地址上写上我们需要的函数,所以我们只能通过曲线救国的方式来实现,再add_note一次修改那片内存的数据为magic地址就可以了

先看一下/home/hacknote/flag的数据
然后运行


成功的运行了magic函数

你可能感兴趣的:(没有将free的指针设为null——UAF漏洞)