2015-01-12 65 views
2

我正在創建關於緩衝區溢出和堆棧/堆攻擊的培訓。我正在研究一臺Ubuntu 12.04 x86_64機器,並希望展示一些示例buggy程序以及可以利用這些漏洞的方式。在Linux機器上創建並測試x86-64 ELF可執行shellcode

我想從目前發現的最基本的shellcode開始,簡單的退出調用,它應該退出程序溢出。

特此exitcall.asm

;exitcall.asm 

[SECTION .text] 

global _start 

_start: 
    xor ebx,ebx  ; zero out ebx, same function as mov ebx,0 
    mov al, 1  ; exit command to kernel 
    int 0x80 

我得從其他教程該ASM文件,架構然而,對於i386的寫入。接下來要做的是生成一個目標文件,並使其成爲一個二進制可執行文件:

# nasm -f elf64 exitcall.asm 

# ld -o exitcall exitcall.o 

# file exitcall 

     exitcall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped 

# strace ./exitcall 

     execve("./exitcall", ["./exitcall"], [/* 73 vars */]) = 0 
     write(0, NULL, 0 <unfinished ...> 
     +++ exited with 0 +++ 

# objdump -d exitcall 

     exitcall:  file format elf64-x86-64 


     Disassembly of section .text: 

     0000000000400080 <_start>: 
      400080: 31 db     xor %ebx,%ebx 
      400082: b0 01     mov $0x1,%al 
      400084: cd 80     int $0x80 

正如你所看到的二進制結果執行好,不知怎的讓我有信心(與strace的驗證口0),該ASM文件正確的。所以我現在應該做的是從它創建一個shellcode字符數組,所以我可以測試下面的示例shellprogram.c executor。我只是把十六進制值從objdump的開始讀從左到右,從上到下,導致下面的測試:

char code[] = "\x31\xdb\xb0\x01\xcd\x80"; 

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

    int (*exeshell)(); 
    exeshell = (int (*)()) code; 
    (int)(*exeshell)(); 

} 

當我編譯該文件並執行它,我得到一個分段錯誤 ,但是:

# gcc shellprogram.c -o shellprogram 

# file shellprogram 
     shellprogram: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=765bdf6201099b9784b63a0111dc16c1115118bb, not stripped 

# strace ./shellprogram 
     execve("./shellprogram", ["./shellprogram"], [/* 73 vars */]) = 0 
     brk(0)         = 0x602000 
     access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
     mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7ff8000 
     access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
     open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 
     fstat(3, {st_mode=S_IFREG|0644, st_size=134914, ...}) = 0 
     mmap(NULL, 134914, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7fd7000 
     close(3)        = 0 
     access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
     open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
     read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832 
     fstat(3, {st_mode=S_IFREG|0755, st_size=1845024, ...}) = 0 
     mmap(NULL, 3953344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff7a14000 
     mprotect(0x7ffff7bcf000, 2097152, PROT_NONE) = 0 
     mmap(0x7ffff7dcf000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bb000) = 0x7ffff7dcf000 
     mmap(0x7ffff7dd5000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dd5000 
     close(3)        = 0 
     mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fd6000 
     mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fd4000 
     arch_prctl(ARCH_SET_FS, 0x7ffff7fd4740) = 0 
     mprotect(0x7ffff7dcf000, 16384, PROT_READ) = 0 
     mprotect(0x600000, 4096, PROT_READ)  = 0 
     mprotect(0x7ffff7ffc000, 4096, PROT_READ) = 0 
     munmap(0x7ffff7fd7000, 134914)   = 0 
     --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x601038} --- 
     +++ killed by SIGSEGV (core dumped) +++ 
     Segmentation fault (core dumped) 

有沒有人有一個想法,我在做事情錯了。我的策略是將二進制elf64文件轉換爲shellcode字符串錯誤,還是原始asm不是64位兼容?

我讀的地方,以產生I可以使用的shellcode下面XXD linux命令:

# xxd -i exitcall 

    unsigned char exitcall[] = { 
     0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 
     0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 
     0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xdb, 0xb0, 0x01, 
     0xcd, 0x80, 0x00, 0x2e, 0x73, 0x79, 0x6d, 0x74, 0x61, 0x62, 0x00, 0x2e, 
     0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x73, 0x68, 0x73, 0x74, 
     0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
     0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 
     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0xe8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
     0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x03, 0x00, 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
     0x04, 0x00, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x04, 0x00, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 
     0x10, 0x00, 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 
     0x10, 0x00, 0x01, 0x00, 0x86, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 
     0x10, 0x00, 0x01, 0x00, 0x86, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 
     0x10, 0x00, 0x01, 0x00, 0x88, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x78, 0x69, 
     0x74, 0x63, 0x61, 0x6c, 0x6c, 0x2e, 0x61, 0x73, 0x6d, 0x00, 0x5f, 0x73, 
     0x74, 0x61, 0x72, 0x74, 0x00, 0x5f, 0x5f, 0x62, 0x73, 0x73, 0x5f, 0x73, 
     0x74, 0x61, 0x72, 0x74, 0x00, 0x5f, 0x65, 0x64, 0x61, 0x74, 0x61, 0x00, 
     0x5f, 0x65, 0x6e, 0x64, 0x00 
    }; 
    unsigned int exitcall_len = 725; 

# objdump -d exitcall 

     exitcall:  file format elf64-x86-64 

     Disassembly of section .text: 

     0000000000400080 <_start>: 
      400080: 31 db     xor %ebx,%ebx 
      400082: b0 01     mov $0x1,%al 
      400084: cd 80     int $0x80 

這個陣列是相當長的時間,然後從objdump的所述一個(可執行部分的顯示彙編內容)並且還包含很多空字節,這在shell代碼中是不可取的,因爲null(00)之後的shellcode不會被執行。

我試着用一個樣例Hello World.asm來嘗試相同的策略,試圖使它與x86-64兼容,並使用shell程序進行測試......也失敗了。有沒有人有一些關於如何編寫shellcode兼容asm的好材料(即不使用字符串的數據部分並使地址獨立)?

任何幫助真的很感激, Boeboe。

+1

你的_exploit_是如此的「經典」,以至於內存保護已經到位,使它難以執行你想要的。您的shellcode字符串被視爲數據,因此包含它的內存頁被標記爲不可執行。試圖執行反正會使CPU產生一個異常,操作系統將通過將你的過程遺忘而處理這個異常。你必須另外做的是用'mprotect()'標記包含數據的內存頁面爲可讀+可執行文件('PROT_READ | PROT_EXEC')。提醒'mprotect'只能改變_whole pages_。 –

+0

爲了演示目的,我添加了以下GCC標誌以繞過默認編譯器保護機制:\t「CFLAGS = -g -w -fno-stack-protector -z execstack」。我認爲這將刪除「標記爲不可執行」的問題......? – Boeboe

+0

但這並沒有什麼區別;你的第一個shellcode是一個全局的'char'數組。它根本不在堆棧中,它在'rdata'部分。您需要調用'mprotect((void *)((intptr_t)code&〜0xFFF),8192,PROT_READ | PROT_EXEC)'或類似的命令來使數據部分包含該shellcode可執行文件。 –

回答

3

問題是,測試程序shellprogram.c是不正確的,因爲我想用它的目的,如@Iwillnotexist Idonotexist所述。由於操作系統強制執行內存保護,您無法執行數據。

的起作用(製備含炭[]的shellcode可讀&可執行數據節)中的溶液調用的最終結果:

#include <unistd.h> 
#include <sys/mman.h> 

unsigned char code[] = { 
    0x31, 0xdb, 0xb0, 0x01, 0xcd, 0x80 
}; 

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

    mprotect((void*)((intptr_t)code & ~0xFFF), 8192, PROT_READ|PROT_EXEC); 

    int (*exeshell)(); 
    exeshell = (int (*)()) code; 
    (int)(*exeshell)(); 

    printf("Failed to execute shellcode"); 

} 

mprotect((void*)((intptr_t)code & ~0xFFF), 8192, PROT_READ|PROT_EXEC); 

爲簡單exitcall例如最終結果最終結果「you win!\ r \ n」給控制檯:

#include <unistd.h> 
#include <sys/mman.h> 

unsigned char code[] = { 
    0xeb, 0x19, 0x31, 0xc0, 0x31, 0xdb, 0x31, 0xd2, 0x31, 0xc9, 0xb0, 0x04, 
    0xb3, 0x01, 0x59, 0xb2, 0x0a, 0xcd, 0x80, 0x31, 0xc0, 0xb0, 0x01, 0x31, 
    0xdb, 0xcd, 0x80, 0xe8, 0xe2, 0xff, 0xff, 0xff, 0x79, 0x6f, 0x75, 0x20, 
    0x77, 0x69, 0x6e, 0x21, 0x0d, 0x0a 
}; 


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

    mprotect((void*)((intptr_t)code & ~0xFFF), 8192, PROT_READ|PROT_EXEC); 

    int (*exeshell)(); 
    exeshell = (int (*)()) code; 
    (int)(*exeshell)(); 

    printf("Failed to execute shellcode"); 

} 

再次感謝您展示解決方案!

+0

恭喜您計算出它!對於你自己和將來的讀者,'&〜0xFFF'將地址對齊到一個頁面,'8192'是x86系統上的常見頁面大小的兩倍(4096字節,但這可能會改變!),在這種情況下,足以覆蓋一切。如果你有更大的shellcode,增加這個值。這是必要的,因爲'mprotect'只能改變頁面粒度的保護。 –

0

如果它可以幫助您使用來自32位應用程序的內存寄存器指針 - 您需要用RAX和RBX替換EAX和EBX以獲得64位。

一年後期,我知道,無疑你已經走了,但我想我會提到它!

+0

他正在使用的寄存器都不被用作指針。另外,'xor ebx,ebx' *會清除完整的64位寄存器,因爲對32位寄存器的所有寫入都會將64位寄存器的高32位清零。 32位'int 0x80' ABI可用於64位進程。如果有任何問題,它可能是eax高24位的垃圾。我猜Linux只會查看'al',而不是'eax',以獲取系統調用編號,否則他很高興高位已經被清零(他們在實踐中正在啓動過程中,即使ABI沒有不需要它。) –

相關問題