安全圈 | 专注于最新网络信息安全讯息新闻

首页

將網路流量分解為asm指令

作者 landy 时间 2020-03-03
all

將網路流量分解為asm指令v0.3.0

新發佈的haka版本(v0.3.0)採用了一個新的模塊來將網路資料分解成指令。這有助於在網絡級別檢測模糊外殼程式碼,如[raid05]1所示。反組譯工具利用了支持多種體系結構(x86、arm、mips等)的Capstoneengine。

在這裡,我們將試圖回答一個著名的網絡取證挑戰的問題8。質詢提供apcap並請求轉儲用於攻擊漏洞的外殼程式碼,然後提供此外殼程式碼執行的操作清單。

外殼程式碼通常由一個nop底座預處理,如下圖所示。我們在第一次嘗試中假設nop底座由nop指令構成(操作碼0x90)。

對於已經完成此挑戰的用戶,我們從問題5中知道,攻擊利用了smb服務(埠445)中存在的漏洞。所以我們寫了一個安全規則來檢查這個流程。如果檢測到外殼程式碼,則啟動反彙編以轉儲其內容:

local tcp_connection = require('protocol/tcp_connection') local rem = require('regexp/pcre') local re = rem.re:compile('%x90{100,}') local asm = require('misc/asm') local dasm = asm.new_disassembler('x86', '32') dasm:setsyntax('att') haka.rule { hook = tcp_connection.events.receive_data, options = { streamed = true, }, eval = function (flow, iter, direction) if flow.dstport ~= 445 then return end if re:match(iter, false) then -- raise an alert haka.alert{ description = "nop sled detected", targets = { haka.alert.service(flow.dstport, "smb") } } -- dump instructions following nop sled dasm:dump_instructions(iter) end end }

我們使用規則運算式來檢測由100多個nop組成的nop sled,並在匹配時發出警報。pattern matching函數更新指針位於外殼程式碼開頭的運算子,如上圖所示。然後,我們使用反彙編模塊來轉儲所有指令

[email protected]:~/workspace/haka/$ hakapcap dump-shellcode.lua attack-trace.pcap ... alert: id = 1 time = Tue Nov 25 10:09:01 2014 description = nop sled detected targets = { service: 445, smb } 0x00000000 jmp 0x12 eb 10 0x00000002 popl %edx 5a 0x00000003 decl %edx 4a 0x00000004 xorl %ecx, %ecx 33 c9 0x00000006 movw $0x17d, %cx 66 b9 7d 01 0x0000000a xorb $-0x67, (%edx, %ecx) 80 34 0a 99 0x0000000e loop 0xa e2 fa 0x00000010 jmp 0x17 eb 05 0x00000012 calll 2 e8 eb ff ff ff 0x00000017 jo 0xffffffffffffffae 70 95 0x00000019 cwtl 98 ...

對於那些熟悉外殼程式碼混淆科技的人來說,這是一個非對稱的外殼程式碼,它以破譯程式開始(見下圖)。

第一條指令檢索edx寄存器中加密外殼程式碼(從偏移量0x17開始)的地址。然後,我們有一個descriptionloop,它將加密外殼程式碼(大小為0x17d)的每個位元組與key0x99進行异或運算。

在下麵,我們編寫了一個第二安全規則,它將在緩衝區中收集外殼程式碼,解密其內容,然後輸出外殼程式碼指令:

local tcp_connection = require('protocol/tcp_connection') local rem = require('regexp/pcre') local re = rem.re:compile('%x90{100,}') local asm = require('misc/asm') local dasm = asm.new_disassembler('x86', '32') dasm:setsyntax('att') haka.rule { hook = tcp_connection.events.receive_data, options = { streamed = true, }, eval = function (flow, iter, direction) if flow.dstport ~= 445 then return end if re:match(iter, false) then -- shellcode info extracted from previous dump local key = 0x99 local decipher_routine_size = 0x17 local shellcode_size = 0x17d -- fill shellcode buffer from stream local code = haka.vbuffer_allocate(0) local size = 0 local sub for sub in iter:foreach_available() do code:append(haka.vbuffer_from(sub:asstring())) size = size + #sub if size >= shellcode_size then break end end -- remove superfluous data code:sub(decipher_routine_size + shellcode_size):erase() -- decipher shellcode local byte for i = decipher_routine_size, #code-1 do byte = bit32.bxor(code:sub(i):asbits(0, 8), key) code:sub(i):setbits(0, 8, byte) end -- dump shellcode local start = code:pos(decipher_routine_size) dasm:dump_instructions(start) end end }

轉儲顯示了外殼程式碼的真正指令。

[email protected]:~/workspace/haka/$ hakapcap dump-shellcode.lua attack-trace.pcap ... 0x00000000 jmp 0x111 e9 0c 01 00 00 0x00000005 popl %edx 5a ... ... 0x00000111 calll 5 e8 ef fe ff ff 0x00000116 incl %edi 47 0x00000117 je 0x16a 65 74 50 0x0000011a jb 0x18b 72 6f 0x0000011c arpl %ax, 0x64(%ecx) 63 41 64 ... ... 0x00000175 jae 0x1e7 65 73 6f 0x00000178 arpl %bp, 0x65(%ebx) 63 6b 65 0x0000017b je 0x17d 74 00

注意,上面的程式碼利用了bit32 lib,它只在Lua 5. 2中可用。由於Haka在默認情况下使用LuaJit解釋Lua程式碼,所以在從原始程式碼構建Haka時,應該選擇Lua選項(-DBUILD=Lua),或者找到另一種方法來獲取xor位元組。

-DBUILD=lua

外殼程式碼首先在edx寄存器上存儲地址0x00000116。這個地址好像有數據。對上述安全規則結尾的輕微修改證實了我們的假設:

--local start = code:pos(decipher_routine_size) --dasm:dump_instructions(start) local data = code:sub(decipher_routine_size + 0x116):asstring() print(safe_string(data))

Haka輸出外殼程式碼使用的原語和庫的清單。更準確地說,這是一個經典的bindshell程式碼: