當前位置:
首頁 > 新聞 > 針對內核中運行的惡意軟體Uroburos的分析

針對內核中運行的惡意軟體Uroburos的分析

惡意軟體Uroburos於2014年首次被發現,作為APT攻擊中的一部分,具有較大程度的威脅。該惡意軟體與其他同類惡意軟體的不同之處在於,它是用Windows的64b(Rootkit)驅動程序,能夠繞過系統的PatchGuard防護機制。此外,驅動程序未經簽名,惡意軟體可以利用第三方驅動程序中的漏洞來實現內核執行。此前,Andrzej Dereszowski和Matthieu Kaczmarek曾針對這一惡意軟體進行了研究,各位可以參考閱讀他們的研究成果: http://artemonsecurity.com/uroburos.pdf

幾個月前,我們發現了一個新的Uroburos/Turla樣本,該樣本的發布時間為2017年。經過仔細分析和比較,我們發現其中的驅動程序基於2014年的版本做了改進,一些地方與原始版本相比具有較大的差異。本文主要對這個64位Rootkit的新增特性進行分析。

我們的分析過程將側重於從內存轉儲(Memory Dump)中識別Rootkit(就像我們在尋找威脅時所做的工作),然後我們對該惡意軟體的新通信協議進行研究。我們的目標是希望遠程發現Rootkit的存在,而無需在伺服器上進行身份驗證。需要注意的是,該Rootkit僅針對於伺服器。

本文分析的代碼位於:https://www.virustotal.com/en/file/f28f406c2fcd5139d8838b52da703fc6ffb8e5c00261d86aec90c28a20cfaa5b/analysis

為了能夠在伺服器上找到威脅,我們使用了Comae DumpIt工具,並分析該工具生成的故障轉儲(Crushdump)。

確定核心威脅

惡意軟體的驅動程序能夠很好地隱藏在內核空間之中,我們發現它不存在於載入模塊列表中,而且經確認,其他模塊的完整性都保持良好。

為了輔助分析,我們使用ExaTrack開發的內部工具,藉助該工具來檢查內核的完整性,並發現潛在的異常問題。

Windows回調(Callback)系統允許在某些事件(如進程創建)期間調用任意函數,這是我們重點關注的組件。

通過認真分析,我們發現了一個異常的地方:

>>> ccb

# Check CallBacks

[*] Checking CallbackTcpConnectionCallbackTemp : 0xfffffa8002f38360

[*] Checking CallbackTcpTimerStarvationCallbackTemp : 0xfffffa8004dfd640

[*] Checking CallbackLicensingData : 0xfffffa80024bc2f0

[...]

[*] PspLoadImageNotifyRoutine

[*] PspCreateProcessNotifyRoutine

Callback fffffa8004bc2874 -> SUSPICIOUS ***Unknown*** 48895c2408574881ec30010000488bfa

在創建進程時,會調用PspCreateProcessNotifyRoutine列表中的回調函數。如果將一些條目添加到其中,理論上就可以對新進程的數據及行為進行改動。在上一個命令中,該工具已經識別出一條可疑的條目,因為它轉向了未分配給驅動程序的內存地址。

同時,回調函數中還存在第二個異常,這個地方不太明顯,因為它不會對系統中所執行的操作產生太大影響,但會對其進行略微的改動。

[...]

[*] IopNotifyShutdownQueueHead

Name : Null

Driver Object : fffffa80032753e0

Driver : DriverNull

Address: fffff88001890000

Driver : Null.SYS

Name : 000000a6

Driver Object : fffffa8003d2adb0

Driver : Driverusbhub

Address: fffff88000da6000

Driver : usbhub.sys

[...]

>>> cirp DriverNull

Driver : DriverNull

Address: fffff88001890000

Driver : Null.SYS

DriverUnload : fffff88001895100 c:windowssystem32drivers
ull.sys

IRP_MJ_CREATE fffff88001895008 Null.SYS

IRP_MJ_CREATE_NAMED_PIPE fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_CLOSE fffff88001895008 Null.SYS

IRP_MJ_READ fffff88001895008 Null.SYS

IRP_MJ_WRITE fffff88001895008 Null.SYS

IRP_MJ_QUERY_INFORMATION fffff88001895008 Null.SYS

IRP_MJ_SET_INFORMATION fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_QUERY_EA fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_SET_EA fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_FLUSH_BUFFERS fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_QUERY_VOLUME_INFORMATION fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_SET_VOLUME_INFORMATION fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_DIRECTORY_CONTROL fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_FILE_SYSTEM_CONTROL fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_DEVICE_CONTROL fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_INTERNAL_DEVICE_CONTROL fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_SHUTDOWN fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_LOCK_CONTROL fffff88001895008 Null.SYS

IRP_MJ_CLEANUP fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_CREATE_MAILSLOT fffff80002abb1d4 ntoskrnl.exe

IRP_MJ_QUERY_SECURITY fffff80002abb1d4 ntoskrnl.exe

在系統關閉時,要調用的模塊列表中會引用「DriverNull」驅動程序。但實際上,這個驅動程序不應該放在此列表中。我們發現,其IRP表似乎沒有被修改,它指向了ntoskrnl(對於IRP_MJ_SHUTDOWN介面)。我們認為這種行為是沒有意義的。

接下來,我們繼續分析。在Windows的輸入輸出(IO)處理程序中,有很多過濾系統。同時,在這些IO中,網路共分為幾個部分,我們在這裡將對其中的一個進行深入研究,也就是NetIO。

NetIO也提供了一個回調系統,允許對交換的網路數據進行操作,這些回調被稱為「Callout」。但是,由於進行的是網路回調,所以其結構沒有被記錄,也沒有出現在Windows符號文件之中。上述這些特性,使之成為了植入惡意軟體的最佳之選。在轉儲中,我們可以找到5個回調,這些回調指向不屬於任何驅動程序的代碼。

>>> cnetio

[*] NetIo Callouts (callbacks) : fffffa8004965000 (4790)

Callback fffffa8004bd9580 -> SUSPICIOUS ***Unknown*** 488bc448895808488950105556574154

Callback fffffa8004bca6b0 -> SUSPICIOUS ***Unknown*** 33c0c3cc40534883ec20488b89500100

Callback fffffa8004bd9af8 -> SUSPICIOUS ***Unknown*** 4883ec286683f91474066683f916750f

Callback fffffa8004bd9ca0 -> SUSPICIOUS ***Unknown*** 48895c24084889742410574883ec4048

Callback fffffa8004bd9de0 -> SUSPICIOUS ***Unknown*** 4c8bdc49895b0849896b104989731857

稍後,我們將會仔細研究其中的一個函數。

在這裡,我們最後要尋找試圖隱藏在Windows中的已載入的驅動程序。

>>> pe

[...]

[OK] fffff88001899000 : SystemRootSystem32DriversBeep.SYS

[OK] fffff88000da6000 : SystemRootsystem32DRIVERSusbhub.sys

[NO] fffffa8004bb8000 (Header overwritten)

[OK] fffff88006a00000 : SystemRootsystem32DRIVERSE1G6032E.sys

[OK] fffff880017d2000 : SystemRootSystem32DriversNpfs.SYS

[...]

>>> dq fffffa8004bb8000 100

FFFFFA8004BB8000 0000000300000000 0000FFFF00000004 ....?...?...||..

FFFFFA8004BB8010 00000000000000B8 0000000000000040 ........@.......

FFFFFA8004BB8020 0000000000000000 0000000000000000 ................

FFFFFA8004BB8030 0000000000000000 000000D800000000 ................

FFFFFA8004BB8040 CD09B4000EBA1F0E 685421CD4C01B821 ??.?....!.?L.!Th

FFFFFA8004BB8050 72676F7270207369 6F6E6E6163206D61 is program canno

FFFFFA8004BB8060 6E75722065622074 20534F44206E6920 t be run in DOS

FFFFFA8004BB8070 0A0D0D2E65646F6D 0000000000000024 mode....$.......

FFFFFA8004BB8080 095520395A3B417D 0955203909552039 }A;Z9 U.9 U.9 U.

FFFFFA8004BB8090 095520A609542039 0955203C092E28A6 9 T.. U..(..

FFFFFA8004BB80A0 0955203B0928E61E 095520510938E61E ?.(.; U.?.8.Q U.

FFFFFA8004BB80B0 09552038092FE61E 09552038092DE61E ?./.8 U.?.-.8 U.

FFFFFA8004BB80C0 0955203968636952 0000000000000000 Rich9 U.........

FFFFFA8004BB80D0 0000000000000000 0006866400000000 ............d.?.

FFFFFA8004BB80E0 000000005900F3CF 202200F000000000 ...Y.........."

FFFFFA8004BB80F0 00042E000008020B 000000000001BC00 ??....?...?.....

>>> list fffffa8004bb8000 fffffa8004bbb000

FFFFFA8004BB8000 rwx-

FFFFFA8004BB9000 rwx-

FFFFFA8004BBA000 rwx-

在這裡,可以發現一個重要的異常。驅動程序存在於內存中,並且已經覆蓋其MZ和PE頭部,從而可以在原始內存搜索中隱藏其自身。它的地址與我們此前遇到的回調函數相對應,並且它以RWX許可權進行映射。

目前發現的種種證據,都表明了該惡意軟體是從內核運行的。現在,我們將分析它的一些代碼(主要是網路通信部分),以進一步了解其工作原理。

驅動程序分析

入口點

在初始化期間,驅動程序將迅速瞄準「空」的設備。惡意軟體檢索指向該對象的指針,並將其註冊在前文提到的「關閉」回調列表中。此外,它還註冊了在進程創建期間調用的回調函數。

[...]

if ( (unsigned int)get_top_deviceObjet(L"\Device\Null", &device_obj_null)

&& (result = get_top_deviceObjet(L"\Device\Beep", &device_obj_null), (_DWORD)result) )

{

__asm { xchg rbx, qword ptr cs:isNullDeviceFailed }

}

else

{

v5 = IoRegisterShutdownNotification(device_obj_null);

if ( v5 || (drvobj_null = device_obj_null->DriverObject, (v5 = sub_4E21C(byte_1188D)) != 0) )

[...]

PsSetCreateProcessNotifyRoutine(cbCreateProcess, 0i64);

[...]

加密字元串

為了避免惡意軟體被反病毒軟體識別出來,所有與Uroburos相關的字元都會被加密。每個加密數據塊大小為0x40位元組,並使用前一個0x40位元組進行異或(XOR)操作。

解密函數如下代碼所示,由此,我們接下來的分析過程將會順利很多。

在文末,提供了加密函數的YARA規則。

網路攔截

如上所示,網路回調已經安裝。惡意軟體通過函數FwpsCalloutRegister0(該函數允許添加網路過濾器)來註冊,並且能控制驅動程序是否傳輸接收到的數據。

v20 = addCalloutAddress(

&stru_14930,

&a2,

DeviceObject,

(__int64)intercept_packet,

(__int64)&ret_null,

(__int64)a6,

(__int64)&v47,

(__int64)&v34,

&a9,

&a10);

「intercept_packet」函數(位於內存轉儲中地址fffffa8004bd9580處)將對經過網路連接的數據進行分析。有趣的是,它並不會查看經過139埠的數據,只會查看其他埠收到的數據。

if ( v9 || LOWORD(a1->layerId) == 20 && a1->pIP_infos->src_port == 139 )

return;

if ( LOWORD(a1->layerId) == 22 && a1->pIP_infos->src_port == 139 )

return;

[...]

fwpsCopyStreamDataToBuffer0(v8, datas_tcp_buffer, *(_QWORD *)(v8 + 48), &v31);

[...]

buffer_type_2 = find_and_decode_datas(datas_tcp_buffer, v24, *((_DWORD *)v11 + 0x1FF) == 0, &a4a);

「find_and_decode_datas」函數負責測試不同的已接受通信協議。在這裡我們將研究HTTP通信。目標是研究如何遠程確定某台伺服器是否已被Uroburos攻陷。

惡意軟體會驗證收到的消息是否為標準的HTTP請求,然後會在HTTP標頭的一個參數中查找隱藏的信息。

if ( space_offset_1 != 3i64

|| ((v18 = *(_WORD *)Buf

(_WORD)str_GET)

|| (v19 = Buf[2], v18 = (unsigned __int8)v19

{

if ( space_offset_1 != 4 || *(_DWORD *)Buf != str_POST )

return 0i64;

}

[...]

if ( *(_DWORD *)start_word_2 != *(_DWORD *)"http://"

[...]

if ( v33 != *(_DWORD *)"HTTP/" || (v35 = v32[4], v34 = v35

aHttp_0[4]) )

[...]

|| !(unsigned int)check_and_decode_buffer(&Buf[nextline], v14, response_tag, out_decoded_b64, v7) )

[...]

「check_and_decode_buffer」函數將會查找第一個「:」字元,並嘗試在相應的HTTP參數中查找隱藏信息。

v15 = memchr(v10, ":", (unsigned int)(v14 - 1));

if ( !v15 || *((_BYTE *)v15 + 1) != " " )

return (unsigned int)v5;

然後,通過一些校驗和(Checksum)驗證信息是否完整。

v10 = get_checksum(datas, 12);

result = (unsigned __int64)reverse_littleendian(v10) == *(_DWORD *)v4;

校驗和函數使用修改後的「threefish256」演算法。

crypto_it(v3, v6, (v5 - 1) >> 5, 32);

[...]

memcpy((void *)(v3 + *(_QWORD *)(v3 + 8) + 64), v6, v5);

*(_QWORD *)(v3 + 8) += v5;

該過程會運行3次散列函數,來計算出最終的散列值。最終獲得的散列值,將會以4位元組為單位進行截斷,並以此作為校驗和。我們猜測,針對每個目標,都有一個不同的密鑰。同時還有一個在惡意軟體及其運營者之間共享的密鑰,該密鑰用於計算哈希值,但不會在請求中發送。

要傳遞的信息位於每一行的末尾,其格式為7位元組內容+1位元組校驗和,該校驗和只是前7個位元組的總和。隨後,惡意軟體會對這8個位元組進行Base64編碼。

後面,將會對HTTP請求數據進行如下修改:

有趣的是,「Code」元素在最終的查詢中並不存在。實際上可以使用4個值,並且它們會在驗證過程中由惡意軟體強制執行。

當伺服器與此類型的請求(在已經打開的埠上)進行通信時,Rootkit將負責響應(數據不會傳遞到用戶空間)。

如果收到的消息符合特定格式,驅動程序就會發送可變大小的響應內容,並以隨機位元組進行填充。

if ( reply_datas[6] & 2 )

{

v8 = 8 * (rand() % -32);

v4 = v8;

v9 = &v21[-v8];

if ( v8 )

{

v10 = v8;

do

{

*v9++ = rand();

--v10;

}

while ( v10 );

}

}

*(_BYTE *)(v7 + 0xBE0);

sprintf(Dest, "HTTP/1.1 200 OK
Content-Length: %u
Connection: %s

",(unsigned int)(v4 + 8));

只有前8個位元組會對特定格式進行響應,其他所有數據都是隨機的。針對該內容的完整性檢查將會強制執行,並將結果存儲在第8個位元組中。這一校驗和過程與上文中分析的過程類似。因此,我們可以基於此,開發一個PoC,來遠程檢查伺服器是否已經被此版本的惡意軟體貢獻:

> request_builder.py 192.168.48.133 8080

datas :

0000000000000000 E8 F6 E8 4E 72 61 03 EA C8 B3 DD 8D 25 D0 26 12 ...Nra.....%.&

0000000000000010 B7 F9 50 E5 8C D2 01 62 A0 37 2F FB AD C8 91 DA ..P...b.7/.....

0000000000000020 44 A5 53 C7 1D 76 0E 4D AC AF F7 18 F4 12 57 A2 D.S.vM....W.

0000000000000030 A0 75 3B 0F 50 C5 6C 55 31 4B A1 9F D0 2E F4 F4 .u;P.lU1K......

0000000000000040 30 39 93 13 1A DF B8 A2 B4 7C DB 88 55 DE 26 98 09.....|..U.&.

0000000000000050 98 04 29 6F AF 25 CF 9F FA F5 90 0D D8 23 E9 97 .)o.%.......#..

[*] checksum OK – Host is compromised

PoC請參考:http://www.exatrack.com/public/uroburos_poc.py

2014年與2017年版本的對比

與2014年的原始版本相比,存在一些相同和不同之處,接下來將簡要列舉我們所發現的一些內容。

1、文件名稱和服務名稱沒有發生變化,從而導致任何IoC都可以輕鬆檢測到。

2、驅動程序總會載入VirtualBox漏洞利用方法,因此在每次重新引導系統時都會進行內核漏洞利用。

3、新版本中刪除了繞過PatchGuard機制的部分,這一改動會對內核修改產生一定限制。

Driver 2014:

if ( v2 )

installService(v3);

v4 = PG_bypass();

if ( v4 )

goto LABEL_16;

ObjectAttributes.Length = 48;

ObjectAttributes.RootDirectory = 0i64;

Driver 2017:

if ( v2 )

installService(cp_DriverObject);

ObjectAttributes.RootDirectory = 0i64;

ObjectAttributes.SecurityDescriptor = 0i64;

DriverNull驅動程序仍然使用,並且DeviceFWPMCALLOUT設備仍然會附加到該驅動程序之中。

>>> drv_stack DriverNull

- Stack of device name : DeviceFWPMCALLOUT

Driver Object : fffffa80032753e0

Driver : DriverNull

Address: fffff88001890000

Driver : Null.SYS

- Stack of device name : DeviceNull

Driver Object : fffffa80032753e0

Driver : DriverNull

Address: fffff88001890000

Driver : Null.SYS

在新版本惡意軟體中,字元串加密這一部分與原始版本沒有變化。我們可以看到,在IopNotifyShutdownQueueHead中註冊「Null」驅動程序是一個非常有效的思路,但在該惡意軟體中還沒有看到其具體用途。惡意軟體編寫者可能會藉助這一回調函數,在關閉時寫入註冊表項,從而保證持久性。

新版本對校驗機制進行了改進,同時惡意軟體使用了Threefish演算法,並對消息的格式進行調整,這些舉措的目的可能是為了改變惡意軟體的特徵,以逃避檢測。

總體而言,新版本Rootkit仍然存在較大的風險,並且在原版本基礎上進行了一些加強。儘管新版本中也有一些疏漏,例如沒有修改文件和註冊表項的名稱,這可能表明該Rootkit只會在隔離的伺服器上運行。

與用戶空間組件相比,位於內核的惡意軟體更難被檢測,因此我們預測這一類型的惡意軟體仍然會存在一段時間,威脅用戶的安全。

YARA規則

rule Sig

{

strings:

$strings_crypt = { 4d 8b c1 41 ba 40 00 00 00 41 ?? ?? ?? 41 ?? ?? 49 83 c0 01 49 83 ea 01 75 ??}

$hash_part1 = { 49 c1 c3 0e 4e ?? ?? ?? 4c 33 dd 4c 03 c7 4c 03 c1 48 c1 c0 10 49 33 c0 4d 03 c3 48 03 e8 48 c1 c8 0c 48 33 c5 49 c1 cb 07 4d 33 d8 4c 03 c0 49 03 eb 49 c1 c3 17 4c 33 dd 48 c1 c8 18 49 33 c0 4d 03 c3 48 03 e8 49 c1 cb 1b 4d 33 d8 4c 03 df 4c 03 d9 48 c1 c0 05 48 33 c5 4a ?? ?? ?? ??}

condition:

1 of them

}


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

加密貨幣挖礦殭屍通過潛在的垃圾網站攻擊運行SSH服務的設備
沒想到吧!ISP竟然會共享你的DNS查詢數據

TAG:嘶吼RoarTalk |