Linux ShellCode實踐

1. 關於ShellCode

ShellCode是一段二進制代碼,最早被用於獲取一個shell,因此而得名。這段二進制代碼可以被cpu識別並執行,也就是我們所說的機器碼。因爲shellcode的這個特性,漏洞攻擊最早出現的方法就是棧溢出+shellcode。而今天的主題,就是向零基礎者展示一段shellcode的產生與執行,幫助讀者舉一反三。

2. ShellCode的產生

本節涉及的環境:

  1. ubuntu18.04 x86_64虛擬機環境。
  2. gcc 7.4.0

ShellCode的產生主要分爲三個步驟:首先寫一段可以實現獲取一個shell的C代碼編譯得到可執行文件,運行驗證其正確性;其次是反編譯該可執行文件,根據得到彙編代碼編寫shellcode相關的最精簡版的彙編代碼2,編譯運行驗證正確性;最後將第二步得到可執行文件反彙編,即可得到shellcode。

2.1 ShellCode的C語言代碼

#include <stdio.h>
#include <unistd.h>

int main(int argc char *argv[])
{
	char *code[2];
	code[0] = "/bin/sh";
	code[1] = NULL;

	execve(code[0],code,NULL);
	
	return 0;
}

代碼解釋:

  • execve是在此進程中執行程序代碼的系統調用,該函數不會fork一個新進程,參數1表示新程序的程序名,參數二是參數列表,是char指針數組,參數列表結尾必須是NULL,參數3是環境變量列表,類型和參數二一樣,這裏不需要傳遞環境變量,所以設爲NULL。

  • 上面代碼功能:調用/bin/sh程序去執行/bin/sh,即創建了一個新的shell。

編譯運行:
shellcode.c 編譯運行結果

2.2 編寫ShellCode彙編代碼

先將2.1編出來的可執行文件(shellcode)反編譯:

objdump -D shellcode > shellcode.obj

查看shellcode.obj內容:
shellcode objdump 文件的main函數部分我們只截圖了main函數部分的代碼,實際上我們也只需要參考這部分的代碼。
彙編代碼解釋:

  • 第64a~64e是創建一個新的棧:先將%rbp寄存器值push到原來的棧中,然後將%rbp指向原來棧的棧頂位置,形成一個新棧,將%rsp的值-0x20,就是棧頂向下增長32個字節,至於爲啥這樣搞,是ABI決定的。
  • 第652~664是將數組的內容拷貝到新棧中,爲啥要用-0x10(%rbp),而不用%rsp,這個我也不是很明白。其中660是將code[0]中的"/bin/sh"字符串拷到-0x10(%rbp)位置,664就是code[1],因爲是NULL,所以直接寫0,爲啥是0x8(%rbp)呢,因爲“/bin/sh”是8個字節!
  • 第66c~67c是填寫execve的三個參數:674是填第三個參數(因爲是NULL所以爲0)到%edx寄存器,674是填第二個參數,因爲是char**類型,所以要填到%rsi寄存器,67c是填第一個參數到%rdi寄存器,爲啥要這樣同樣是ABI決定,中間爲啥要用%rax,%rcx寄存器,暫時沒搞清。
  • 最後67f就是調用execve函數了,後面的代碼我們可以不看了,我們暫時不考慮函數返回的執行過程。

2.3 參考彙編代碼重寫彙編代碼

接下來編寫shellcode的彙編碼:
shellcode彙編代碼
上面的邏輯和返彙編的代碼基本相似,區別在於,"/bin/sh"這個字符串我們放在了代碼裏,其地址在cl標籤的下一個指令地址。那麼如何獲取到這個地址呢,我們用一種方法來巧妙獲取:

jmp cl
pp: popq %rcx
xxxx
cl: call pp
.ascii "/bin/sh"

原理在於,call pp後會將下一條指令的地址壓入棧中,從而可以pop出來。當然寄存器我們可以用其他來替代%rcx。後面的就是設置參數和調用execve了,只是他的調用號我們要去查,我係統的是59,他它賦值給%rax後調syscall即可。

編譯運行:
shellcode運行結果
反編譯shellcode_modify文件就可以啦啦啦啦啦啦!
shellcode

  • 注意這裏的那些00不是階段符,是正常代碼哦!

ShellCode測試

最後我們要寫一個測試程序來測試:
shellcode測試代碼
運行結果:
shellcode測試結果
編譯之所以要加那兩個參數,是因爲要關閉程序的stack保護,和stack不可執行權限限制,其實不用後面那個參數,因爲我們還沒有用到棧溢出覆蓋函數返回地址,哈哈!

總結

整個過程還算比較順利,主要就是在於要理解彙編代碼,這個比較困難,這裏涉及的一些linux系統相關的知識和相關工具的使用也是要理解的。好了,有了shellcode之後,你就可以利用它去進行棧溢出攻擊啦,關於棧溢出攻擊,後面有空再寫吧,特別提醒:這裏的shellcode是不可移植的,你需要學習方法自己在自己的環境中實踐!!!而且,由於linux的NX保護(棧不可執行),把shellcode放在棧中再利用棧溢出去執行已經不可行啦!當然了,出於學習的態度,還是可以瞭解一下的,況且後面還要學習構建ROP來繞過NX保護,哈哈哈。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章