Day11-Shellcode
前言 從今天開始,內容會變得更加困難。之前的題目可能有留一個後門函式,讓你可以直接開啟 shell,或是使用 system 函式來方便後續的操作。然而,現實中基本不會有這種情況,所以我們需要學習更多漏洞利用的方法,才能更符合實際的需求。 Shellcode 根據之前提到的編譯過程,經過簡化後,最終會變成下圖所示的形式: 簡單來說,最後真正執行的部分是機器碼,而這正是本章節要教授的內容:Shellcode。之所以稱為 Shellcode,是因為我們透過編寫 Assembly 程式碼,將參數寫入指定的位置,並最終呼叫 syscall,來達成我們的目標,例如開啟 shell 或讀取特定檔案。 Syscall syscall 即為 System Call,是用來與 Kernel 進行溝通的呼叫。在 CTF 中,常見的有以下兩種: execve("/bin/sh", NULL, NULL) open、read、write 這些可以分別用來啟動 shell 或進行任意的檔案讀寫。這個網站可以幫助查詢呼叫各種 syscall 時應該將各個暫存器設置為什麼值,這與前面提到的 Calling Convention 是相關的。 如何編寫 Shellcode? 編寫 Shellcode 有幾種方法,以下是幾個選項: 自己寫 Assembly,並透過 pwntools 進行轉換。 從 shellcode database 中找到需要的 Shellcode。 使用 pwntools 中的 shellcraft,記得指定 context.arch。 Lab 查看以下程式原始碼: 1#include<stdio.h> 2#include <unistd.h> 3#include <sys/mman.h> 4char shellcode[0x100]; 5int main(){ 6 setvbuf(stdout, 0, _IONBF, 0); 7 setvbuf(stdin, 0, _IONBF, 0); 8 setvbuf(stderr, 0, _IONBF, 0); 9 unsigned long addr = (unsigned long)&shellcode & ~0xfff; 10 mprotect((void *)addr, 0x1000, PROT_EXEC | PROT_READ | PROT_WRITE); 11 printf("Give me shellcode: "); 12 read(0, shellcode, 0x100); 13 printf("Overflow me: "); 14 char buffer[0x10]; 15 gets(buffer); 16 printf("Bye!\n"); 17 return 0; 18} 使用以下指令進行編譯: ...