一、背景
Tor(The Oninon Router)提供一個匿名交流網路平臺,它使得使用者在瀏覽網頁或訪問其它網路服務時不會被跟蹤。作為該網路的一部分即所謂的“暗網”(darknet),是指只能通過Tor網路訪問的伺服器群組,這些伺服器提供包括社群論壇、電子郵件等多種服務。雖然提供這些服務都是無惡意的,初衷是用來關注侵犯人權問題,但是由於匿名的原因吸引了很多有犯罪意圖的人,比如傳播兒童色情。事後執法部門也不能追蹤到犯罪者的源IP地址。
2013年,在“暗網”伺服器上發現了一款惡意軟體,它利用特定Web瀏覽器上的安全漏洞在使用者電腦上執行一段程式碼。該程式碼收集一些使用者資訊,發往弗吉尼亞州的伺服器,之後自毀。就惡意軟體的特徵來講,它沒有明顯的惡意意圖。初步推斷是FBI植入,他們在弗吉尼亞州有辦事處,曾經也派專人開發過惡意程式,可能是他們建立了它—現在看來是真的。
二、對Shellcode的逆向分析
1、漏洞利用
漏洞利用程式碼用javascript編寫,利用一個出名的firefox瀏覽器的特定版本(Tor網路預裝的firefox)的漏洞。該漏洞利用程式碼經過了模糊處理,但通過快速掃描可以看到一長串十六進位制字元,這些字元是shellcode的前幾個標誌性位元組,即call操作碼(shellcode經常以一個jump或call開始,因此知道了這些操作碼使得識別shellcode變得容易起來)。
我不會在這裡分析這個漏洞,但是要看一下這個shellcode。
首先,讓我們用一些基本的shellcode原則設定一個場景。
2、位置無關程式碼
Shellcode的成功執行經過了獨一無二的挑戰,因為它是直接注入到一個程式而不是由Windows載入器載入。因此,我們不知道shellcode位於記憶體中的什麼地方,更關鍵的是,不知道標準的windowsAPI函式位於什麼地方(而通常情況下,Windows載入器會告訴一個程式這些資訊)。
因此,我們必須使用一系列技巧去獲得這個資訊。FBI惡意程式用了一個常用的技巧去找出它的記憶體地址:
12345 call startstart:pop ebp
call函式將執行程式移動到start標籤處,同時將程式當前執行的位置壓入堆疊中(這樣我們稍後可以從call函式返回)。
在此,我們將要用這個值,從棧裡竊取位置,堆疊彈出的值儲存到ebp暫存器。我們現在知道了下一條指令的地址,那麼就可以用它來訪問跟我們的shellcode相關的資料。
三、定位Windows API
因為正常情況下Windows載入器會載入Windows API的位置到我們的程式,所以我們不奢望執行一個shellcode時能夠知道程式的位置資訊。找出API函式慣用的方法是檢視FS段暫存器所指的執行緒資訊塊(thread information block)。我們能夠通過這個結構體去定位被我們shellcode宿主程式載入的DLLs,然後利用這些DLL的輸出直到找到目標函式為止。當然這個過程是很乏味的,所以,FBI這個shellcode使用了一個庫,包含在MetasploitFramwork內,這是由Stephen Fewer寫的一個函式解析器。它的工作原理如下:
1234567 push arguments. . .push FUNCTIONHASHcall<Stephen’sResolver>
這個函式的雜湊值是由一個簡單的hash演算法生成,以我們呼叫函式的名稱命名。這樣做的目的不是為了混淆程式碼(儘管它達到這個目的),但只允許我們用一個32位的DWORD來呼叫此函式,而不是一個長型字串(shellcode空間往往是有限的)。
值得慶幸的是,我們自己可以計算出hash值,或者用別人生成的查詢表。
四、開始
如果我們對shellcode的開始進行反彙編,如下圖:
我們一旦計算出指向API解析器的ebp暫存器值,我們就可以在windows的API進行雜湊呼叫前獲取其十六進位制數。如此,如果在查詢表裡查詢到那個值,在那個值附近查詢呼叫的函式,並且新增一些註釋,如下圖:
這段程式碼執行完整性檢查,通過用GET 開始的HTTP請求頭部資訊以確保shellcode安全執行。然後呼叫Windows API函式LoadLibrary()載入兩個動態連結庫:ws2_32.dll(用於網際網路通訊的Windows套接字型檔)和iphlpapi.dll(WindowsIP輔助庫)。
五、連線到HTTP伺服器
在必要的庫檔案都載入完之後,shellcode將執行下圖中的操作:
再一次,用相同的步驟,用雜湊值查詢一個Windows API函式:connect()函式。我們可以看見,在[ebp +0x2e1]位置的資料作為一個引數傳遞給connect()函式—從手冊我們知道,那個引數是一個sockaddr結構體(sockaddr structure)。我們知道ebp暫存器指向我們在記憶體中的地址,使用那個地址,再加上偏移量,我們就能定位出那些資料在記憶體0x2E8處(ebp=0×7)。
因此,我們在分析sockaddr之前,先給這些程式碼新增一些註釋,命名一些記憶體偏移地址,如下圖:
這個eax暫存器儲存著呼叫connect()函式的返回值,如果這個值為0(來自微軟使用者手冊)表示connect()呼叫成功。但是我們成功連線到哪兒?如果我們現在新增一些註釋到我們之前的反彙編檔案,基於我們在微軟使用者手冊中能查到的關於sockaddr結構體的資訊,我們可以這樣新增註釋,如下圖:
通過對IP地址進行whois快速查詢,只得到很少資訊。如下圖:
六、收集使用者資訊
接下來,這個惡意軟體嘗試獲得windows主機名—通常情況下這是windows機器的名字。這可能有助於確認嫌疑犯和確認他們沒有逮捕錯人。
其次,它列舉了活躍主機的hostname和IP地址。
使用SendARP()函式來發現網路中所有電腦的MAC地址。有一些“恰當”的方式做到這樣,但是shellocode只能獲得有限的空間去完成這些事。MAC地址將使用者與一張特定的網路卡繫結,於是可以通過這些網路卡的供應鏈來追蹤使用者。
最後,它要構建HTTP頭部資訊,將MAC地址放進Cookie欄位,使用者的主機名放進Host欄位,並且要以GET請求方式傳送到http://65.222.202.54/05cea4de-951d-4037-bf8f-f69055b279bb。這些十六進位制數字的意義不清楚,它們可能是任意選擇或連結一個使用者到特定的接入伺服器。
七、最後階段
這個shellcode最後階段的唯一目的就是在該shellcode結束時執行更多的shell程式碼—它這樣做的方式稍微有點迂迴,我也不知道為什麼這樣,也許是一次粗略的嘗試。
那麼,最後一歩要怎麼做。首先,它利用一些字串長度操作找出一些被嵌入在其他所有資料區的程式碼。那些程式碼計算出我們的HTTP請求字串結束的位置,跳過在shellcode結尾處的所有的無效的空操作指令,然後跳到那裡。那裡是哪裡?誰知道!我被告知有更多的shellcode(這不重要),但是我已經沒有時間來除錯這個漏洞並獲得它。
構建頭部,然後跳轉到頭部結尾處。
查詢http頭部結尾處的無效指令並且跳過它們。
八、執行程式碼
到目前為止,我以完全靜態的方式分析了這些程式碼—主要是為了完整性。通過執行這些程式碼能夠更快速的分析它們,同時可以驗證我們的分析是否正確。既然這段惡意程式碼沒有任何破壞系統的行為,因此我們可以安全的在真機上執行它。於是執行它並觀察它傳送給FBI的確切資料。因為shellcode不是一個exe可執行檔案,我需要一個shellcode載入器去執行它—-它們快速的分配需要的記憶體,載入shellcode並跳轉到該處。這是載入shellcode需要做的—-在呼叫真正的shellcode之前會自動斷開。
然後我們啟動偵錯程式跨步執行到呼叫cnnect()函式。我們不得不把這個shellcode的目標指向另一臺我們自己的機器,便於觀察執行結果。因此,我將讓他指向ip地址為192.168.0.254的77埠,然後在這個機器上執行netcat程式抓取資料。在下圖程式碼暫停的箭頭所指處,就是早期通過patch方式來修改sockaddr結構體。
然後我們繼續跨步執行到呼叫send()函式,執行它,之後我們能看見在netcat終端的輸出,它將輸出它收到的所有資料—顯示的那些資料原本是發給FBI。你可以看到,cookie裡面的ID包含了我的MAC地址,Host 頭部包含了我的desktop名。
最後,我們跨步執行到最後階段—最後的空操作可能是用來注入更多的已經提取的shellcode。在那個十六進位制檢視器視窗可以看見,我們構造的那個HTTP請求已經發出。
九、結論
這個惡意軟體從使用者瀏覽器傳送確認資訊給攻擊機,然後使使用者firefox瀏覽器崩潰。就複雜性而言,它沒有很明顯的特別之處,也沒有使用一些大家不知道的新技術。
如果這個惡意軟體作者是FBI,那麼他們需要去回答一些很嚴肅的問題。這些惡意程式被植入到非美國的伺服器上,並攻擊利用全球使用者的瀏覽器(他們當中很多人是無辜的)他們這樣做甚至可能會得到法律授權?我不這麼認為。當有人告發時FBI是否需要出示他們曾經得到過法律授權的證據?未必。我希望他們會依據使用者的電腦內發現的證據和在收到起訴時取得的證據—-儘管最初的搜尋授權可能很不靠譜。不管怎麼說,我畢竟不是一個律師。