前述的網路 IDS/IPS 不只追蹤連線,還能檢查封包本身——通常尋找標示攻擊的模式。

IDS 特徵與其弱點#

例如一條尋找含 /bin/sh 字串封包的簡單規則,能抓到許多含 shellcode 的封包。我們的 /bin/sh 因為以四位元組區塊 push 到堆疊已略微混淆,但 IDS 也能找含 /bin//sh 的封包。

這類特徵對抓「用網路下載的漏洞利用的 script kiddie」相當有效,但用隱藏所有洩露字串的自訂 shellcode 就能輕易繞過

字串編碼#

要隱藏字串,只需對字串每個位元組加 5;push 到堆疊後,shellcode 再對堆疊上每個位元組減 5,在堆疊上建出想要的字串——傳輸途中保持隱藏。

(gdb) print /x 0x0068732f + 0x05050505   # "/sh\x00" 編碼 +5
$1 = 0x056d7834
(gdb) print /x 0x6e69622f + 0x05050505   # "/bin" 編碼 +5
$2 = 0x736e6734

shellcode push 編碼位元組,再用迴圈解碼:

push 0x056d7834   ; push 編碼的 "/sh\x00"
push 0x736e6734   ; push 編碼的 "/bin"
mov ebx, esp
push BYTE 0x8 / pop edx    ; 要解碼 8 位元組
decode_loop:
  sub BYTE [ebx+edx], 0x5
  dec edx
  jns decode_loop

除錯時用兩個 int3 指令(0xcc,除錯中斷點)夾在解碼前後,就能在 GDB 中看清字串正確解回 "/bin/sh"。驗證後用 sedint3 註解掉即可。這種會修改自身的 shellcode 稱為多型(polymorphic)shellcode

如何隱藏 NOP sled#

NOP sled 是另一個易被偵測的特徵:大塊的 0x90 並不常見,網路安全機制看到就大概認定是漏洞利用。

要避開這個特徵,可用其他單位元組指令取代 NOP——好幾個遞增/遞減指令同時也是可列印的 ASCII 字元

指令十六進位ASCII
inc eax0x40@
inc ebx0x43C
inc ecx0x41A
inc edx0x42B
dec eax0x48H
dec ebx0x4BK
dec ecx0x49I
dec edx0x4AJ

由於使用這些暫存器前都會先清零,可安全地用 @CABHKIJ 的隨機組合當 NOP sled。用 C 寫個 sled 生成程式搭配 BASH 腳本,就能讓漏洞利用緩衝區避開專門找 NOP sled 的 IDS。