前言 在前面文章中,我們討論了 Glibc 的 malloc 和 free 流程,並介紹了一些相關的名詞。接下來,我們將探討與 Heap 相關的漏洞,而第一個要介紹的漏洞是 Use After Free。
Use After Free 顧名思義,Use After Free 指的是使用已經被 free 掉的指標(pointer)。問題的根源在於 dangling pointer。當一個指標被 free 之後,如果沒有將其設為 NULL,就會產生 dangling pointer。
Use After Free 的利用方式會隨著使用的情境有所不同,可能導致:
任意位置讀取或寫入 間接影響程式的控制流程 此外,它也可能被用來 leak 記憶體中的殘值。同樣的,另一個常見的 Heap 漏洞——double free,也是因為 dangling pointer 的存在,導致多次 free 相同的記憶體區塊。這些漏洞都可以通過特定技巧加以利用。
Lab 查看以下原始碼:
1#include<stdio.h> 2#include<stdlib.h> 3 4struct Note{ 5 void (*printnote_content)(); 6 char *content; 7}; 8 9struct Note *noteList[10]; 10int noteCount = 0; 11 12void printnote_content(struct Note *this){ 13 printf("%s\n", this->content); 14} 15 16void add_note(){ 17 int i,size; 18 if(noteCount >= 10){ 19 printf("No more space for new note\n"); 20 return; 21 } 22 for(i=0; i < 10; i++){ 23 if(noteList[i] == NULL){ 24 noteList[i] = (struct Note *)malloc(sizeof(struct Note)); 25 if(noteList[i] == NULL){ 26 printf("Memory allocation failed\n"); 27 exit(1); 28 } 29 noteList[i]->printnote_content = printnote_content; 30 printf("Enter the size of the note: "); 31 scanf("%d", &size); 32 noteList[i]->content = (char *)malloc(size); 33 if(noteList[i]->content == NULL){ 34 printf("Memory allocation failed\n"); 35 exit(1); 36 } 37 printf("Enter the content of the note: "); 38 read(0, noteList[i]->content, size); 39 noteCount++; 40 break; 41 } 42 } 43} 44 45void delete_note(){ 46 int index; 47 printf("Enter the index of the note: "); 48 scanf("%d", &index); 49 if(index < 0 || index >= noteCount){ 50 printf("Invalid index\n"); 51 exit(1); 52 } 53 if(noteList[index] != NULL){ 54 free(noteList[index]->content); 55 free(noteList[index]); 56 printf("Note deleted\n"); 57 } 58} 59 60void print_note(){ 61 int index; 62 printf("Enter the index of the note: "); 63 scanf("%d", &index); 64 if(index < 0 || index >= noteCount){ 65 printf("Invalid index\n"); 66 exit(1); 67 } 68 if(noteList[index] != NULL){ 69 noteList[index]->printnote_content(noteList[index]); 70 } 71} 72 73void backdoor(){ 74 system("/bin/sh"); 75} 76 77void menu(){ 78 printf("1. Add note\n"); 79 printf("2. Delete note\n"); 80 printf("3. Print note\n"); 81 printf("4. Exit\n"); 82 printf("Enter your choice: "); 83} 84 85int main(){ 86 setvbuf(stdout, 0, 2, 0); 87 setvbuf(stdin, 0, 2, 0); 88 setvbuf(stderr, 0, 2, 0); 89 while(1){ 90 menu(); 91 int choice; 92 scanf("%d", &choice); 93 switch(choice){ 94 case 1: 95 add_note(); 96 break; 97 case 2: 98 delete_note(); 99 break; 100 case 3: 101 print_note(); 102 break; 103 case 4: 104 exit(0); 105 break; 106 default: 107 printf("Invalid choice\n"); 108 break; 109 } 110 } 111 return 0; 112} 使用以下指令進行編譯:
...