當前位置:
首頁 > 最新 > 共享軟體中惡意代碼插入技術研究

共享軟體中惡意代碼插入技術研究

嚴正聲明:本文僅用於技術探討,嚴禁用作其他用途。


一、 前言

過去的Windows系統,漏洞百出,防不勝防,因此第三方殺毒軟體幾乎是裝機必備。隨著windows系統的不斷更新,其安全防護措施也不斷加強,傳言Windows自帶的windows defender已經可以完全替代第三方殺毒軟體的工作,那麼是否還需要安裝第三方殺毒軟體呢?

其實,惡意軟體和殺毒軟體是一對好兄弟,它們一直互相鬥爭、互相進步,隨著殺軟技術的提高,免殺技術也在不斷提高。有些惡意程序的關注重點已經不在於「幹壞事」了,它們已經把目光放在了「流量」上,畢竟現在是流量為王的時代。各種惡意程序通過廣告、捆綁等形式來發展自己,其中的重災區就是各種網站的下載工具。就連某搜索引擎提供的下載中心中的軟體都被添

加了惡意代碼。

2012年多個SSH客戶端中被發現植入後門,導致了大量SSH帳號密碼泄露;2018年5月再次發生類似事件。攻擊者是如何在正常的軟體內添加惡意代碼又不影響原程序執行的呢?

安全實驗室對他們的實現原理和方法以及殺毒軟體檢測情況進行了分析。一般給程序加惡意代碼而不影響程序運行的方式主要有兩種:添加額外區段添加shellcode和利用代碼洞添加shellcode。


添加額外區段添加shellcode是指通過添加區段把shellcode添加到一個PE文件中,其優點是不需要考慮shellcode的大小、容易實現、易於自動化。缺點是既然是「額外段」,shellcode位置固定,就好像人身體多出個「零件」,非常容易被殺軟檢測到。

通過添加區段添加shellcode,我們需要完成以下工作:

PE文件添加額外區段

把準備好的shellcode拷貝到該區段中

改變程序執行流程,先執行shellcode再運行正常程序

a) PE文件準備:

用VC6.0編譯生成一個32位MFC小程序。

示常式序下載地址:鏈接: https://pan.baidu.com/s/1r82qf1F7AUdj-jjIDrS9Ew 密碼: b5rz

b) 使用LordPE打開並編輯PE文件,添加區段

c) 編輯區段大小和屬性

區段大小為shellcode大小對0×200取整,我們暫定0×1000

因為我們的shellcode需要執行,可能被添加的shellcode執行時還要自修改,所以我們需要把區段屬性改為可讀可寫可執行。最後別忘記保存。

d) 填充區段內容

這時候我們添加的區段還只是理論存在的區段,文件本身並沒有這段內容 (文件大小未變),下面我們利用010Editor等二進位工具給文件實際添加上這段空間。

用010Editor打開我們剛才編輯的PE文件,移動到文件的最後位置0×33000,插入0×1000個位元組。

到這裡,我們就完成了一個內容完全為0的區段的添加。

e) 拷貝shellcode到新區段

拷貝一份我們準備好的Hello World!的shellcode(實現一個彈框的功能)到該區段

f) 更改PE文件的OEP到我們的shellcode起始位置

shellcode的起始虛擬地址就是我們添加區段時新區段的起始地址0×38000

更改程序的OEP為0×38000,保存

g) 在shellcode後添加跳轉到原OEP的代碼:JMP 原OEP

shellcode執行完後,為了不影響原程序運行,還需要執行原程序的代碼,原程序的代碼從哪裡開始執行呢?就是被我們修改前的OEP的值。改變代碼的執行流程需要用到指令JMP XXX。XXX就是跳轉偏移。

跳轉偏移=原OEP-JMP所在位置-5

原OEP=0×9486

JMP所在位置=新區段地址0×38000(新的OEP)+Shellcode大小0×122

跳轉偏移=0×9486-(0×38000+0×122)-5=0xFFFD135F

所以跳轉到原OEP的Opcode為 E9 5F 13 FD FF

在我們e)中添加的shellcode後添加這幾個Opcode.

h) 運行該程序

程序運行後,先彈出Hello World,shellcode正常執行,然後才運行正常程序。


PE文件有其特殊的結構,其身體是由不同的節(區段)組成的。這些節內,或節與節之間有文件執行時用不到的填充位元組0,這些被0填充的空間我們稱之為代碼洞。如果這些連續的0空間足夠放下我們的shellcode,那麼我們就可以考慮把我們的shellcode替換掉同樣大小的0,這樣殺軟的異常段檢測對我們來

說就沒用了。

代碼洞所在的段最好是可寫段,因為有些shellcode執行時會自修改,如果找到的是不可寫段,需要修改段保護屬性,而段屬性異常會被某些殺軟當作異常點檢測。當然,如果被加的shellcode不需要自修改,段屬性就沒這個要求了。

代碼洞找到後,不改變OEP的情況下,如何讓我們的shellcode被執行呢,這就需要分析你要添加shellcode的程序的執行流程了,在非敏感位置,截斷程序的執行流程,使其跳轉到我們的shellcode,shellcode執行完後再跳轉回正常流程。

代碼洞添加的優點就是shellcode位置不固定、文件本身大小不變,不容易被殺軟檢測到。缺點是需要在文件本身中搜索代碼洞,代碼洞的大小不能小於Shellcode大小,條件苛刻,實現相對困難,不容易自動化。

手工查找代碼洞並添加shellcode過程:

查找代碼洞;

找到跳轉點,跳轉到shellcode

a) 查找代碼洞

雖然節內也可能有大量的0位元組,但節內數據我們不能保證是不是有用的數據,比如初始化為0的全局變數,所以一般我們查找的代碼洞都是節與節之間的0,這些0在PE中是用來節對齊的,不會被代碼執行用到,正適合被我們拿來使用。有一個開源項目cave_miner(https://github.com/Antonin-Deniau/cave_miner)可以查找合適的代碼洞,但是實際使用不太理想。我們就自己動手去查找,你會發現這很容易實現。

還是我們的示常式序。LordPE查看PE信息。

其中文件塊對齊大小就是節的對齊單位,即每個區段都是該值的整數倍,如果該區段的有效位元組數不是該值的整數倍,就會用0補齊。這些補齊用的0就是我們要找的節間代碼洞,所以我們要找的代碼洞大小不會超過這個值。如果你的shellcode體積比這個值大,那你就要換個文件添加shellcode了。如果是指定文件添加shellcode,又沒有合適的代碼洞怎麼辦呢,那就要大量改造這個PE文件,這就違背了代碼洞添加shellcode的初衷:不改變文件大小。

如果該值合適,那麼我們就可以在節與節之間查找我們需要的代碼洞了,用LordPE查看區段信息。

紅色圈內就是每個區段在文件中的起始偏移值。我們的Helloworld的shellcode大小為0×122,用010Editor打開程序,第1個區段的起始位置0×1000,查看第1個區段前有沒有合適的代碼洞。

如上圖所示,PE頭部和第1個區段之間有大量的0,滿足我們的條件。

b) 找觸發點跳轉到Shellcode

將HelloWorld shellcode拷貝到代碼洞中的合適位置,這裡我們選擇0×300這個地方。

下面就是分析加shellcode程序,找到合適的跳轉位置,跳轉到我們的shellcode去執行。什麼樣的位置才是合適的跳轉位置呢,其實沒有什麼固定要求,只要不截斷正常指令的位置一般都符合我們的要求。但如果殺毒軟體通過沙箱來運行程序檢測異常行為,shellcode還是會被檢測到,所以一般我們選特殊的「觸發點」作為我們的跳轉偏移。比如我們當前程序,點擊確定後才會彈錯誤提示框,所以我們可以把「點擊按鈕」這個事件的觸發代碼作為跳轉點。

用X64Dbg打開處理後的程序,分析找到彈框位置(通過搜索「錯誤」這個字元串可以快速定位):

把push 0042B0C0換成JMP Shellcode位置,即JMP 400300

在Shellcode的最後位置把剛才被更改的指令恢復,並跳轉回401575

右鍵補丁保存修改後的文件

到這一步為止,我們的代碼洞加Shellcode就完成了。點擊確定,彈出HelloWorld,shellcode運行正常,再提示錯誤,程序運行正常


經過上述兩種方式添加shellcode後我們已經發現,加區段的方式容易實現自動化,而代碼洞實現則比較困難。下面我們就開始看看如何用代碼來實現加區段的方式添加shellcode。主要分以下幾步:

1. 檢測PE文件是否有效

2. 提取shellcode文件中的shellcode並獲取shellcode大小

3. 添加新區段,把shellcode拷貝到新區段

4. 更改OEP到新區段,並添加跳轉到原OEP的OPCODE

a) 檢測PE文件

檢測PE文件是否符合要求:

b) 提取Shellcode

解析Shellcode文件,獲取Shellcode大小,並加密,加密後和解密Shellcode組合成新Shellcode。

解密Shellcode為:

c) 添加Shellcode段

添加Shellcode區段:我們需要改變原文件的區段信息,添加一個新的區段,並在文件後追加對應大小的區段。添加的區段信息包括:區段名、區段在文件中的大小、區段文件偏移、區段的虛擬大小,區段在內存中的偏移、區段保護屬性。

拷貝Shellcode到新區段

d) 更改OEP

e) 生成新文件

整合上面幾步的代碼,生成新文件:


手工完成加Shellcode後,最終成品會被殺毒軟體檢測到嗎?我們分別將這幾種添加方法生成的樣本上傳到VirusTotal去檢測一下(https://www.virustotal.com/#/home/upload).

a) 增加區段加原始Shellcode:報毒率15/65。

這時候添加的Shellcode,殺軟可以通過檢測shellcode特點、檢測異常區段、OEP位置等來檢測異常。後面我們會依次驗證。

b ) 加密的Shellcode

shellcode的實現一般有其共通點:訪問PEB、查找Kernel32.dll、查找需要用到的函數等。因此這些特徵可能被殺軟作為異常檢測的點,所以我們用一個加密的Shellcode隱藏這些特徵來進行測試

準備加密的HelloWorld Shellcode,替換未加密的Shellcode,更改章二中的第e、g兩步,再檢測。

shellcode怎麼加密呢?在這裡我們把Helloworld!的shellcode用010editor工具2進位異或一下,這裡我們選擇用02異或:

異或後的shellcode已經被改變,想要執行需要我們再異或恢復過來,所以我們在加密後的shellcode前添加一些恢復shellcode的指令來實現自修改。

下面解釋下這段指令:

PUSHAD:保存環境變數,和最後的POPAD恢復環境呼應。

call xxx,和pop eax用於獲取pop eax所在行的地址,這樣無論我們的shellcode在哪,都能定位到shellcode的位置了。

lea esi, [eax+0x19],用於獲取我們被加密的shellcode的起始地址,因為我們的shellcode要放在這段解密指令的後面,所以距離pop eax正好0×19個位元組。

xor ecx,ecx和mov cx,121,是需要解密的次數,就是我們的shellcode大小-1

loop 0×00409496(不同實驗該值不同,就是mov al, [esi+ecx*1]的地址)

xor byte ptr [esi+ecx*1], 0×02

這幾行代碼就是把我們的shellcode從後向前依次與0×02異或解密

把這段指令的位元組碼提取出來:

選中409486~4094A4的範圍,shift+C複製。

010Editor新建文件:

切換到16進位格式;

ctrl+shift+v,粘貼:

其中,第1行的最後兩個位元組21 01就是我們的被解密shellcode的大小-1,第2行的兩個02就是我們的解密key.以後只需要改變這幾個值,我們就可以實現任意shellcode的加解密了。把我們加密後的Helloworld shellcode添加到上面位元組碼的後面,就是我們加密後的自解密shellcode了:

用加密後的shellcode替換原來的shellcode,後面添加上JMP OEP的OPCODE(怎麼計算前面已經說過):E9 40 13 FD FF

發現報毒率有所降低,與之前報毒的公司也不同,說明被加密的shellcode更安全。

c) 不可執行的shellcode段

在章二c)中我們添加的shellcode段要求可讀可寫可執行,這樣一個PE文件就有兩個可執行區段了,殺軟可以通過這點來進行異常檢測。

所以我們把區段屬性中的可執行屬性去掉。

去掉可執行屬性後,我們的shellcode還怎麼執行呢?把該PE文件的數據執行保護(DEP)關閉,這樣就可以在非代碼區跑代碼了。

用010Editor打開要去除DEP屬性的PE文件,010Editor已經自動解析了PE文件格式。右側(或下側)找到IMAGE_NT_HEADERS,展開,找到IMAGE_OPTIONAL_HEADER32,繼續展開,找到struct DLL_CHARACTERISTICS DllCharacteristics,把其中的WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT : 1雙擊設置為0即可。

檢測結果如下:報毒率顯著降低

d) 不變的OEP

經過上述b、c兩步後,還剩一個我們猜測易被檢測的點:OEP的位置。正常的PE文件,其OEP一般在第1或第2個區段,被「處理」過的程序,比如加殼程序,才會把OEP設置到其他區段。這次我們嘗試不改變程序的OEP,來實現加Shellcode。

要實現不改變程序的OEP,又能先執行Shellcode,我們需要解決兩個問題:1. 把原程序OEP處的前5個位元組改成跳轉到shellcode的指令。2. 在shellcode後面恢復原OEP被修改的5個位元組,跳轉回原OEP。

修改原OEP處的5個位元組跳轉到我們的shellcode處:跳轉偏移=新OEP-原OEP-5=0×38000-0×9486-5=0x2EB75。原OEP為0×9486,參考區段表(下圖),OEP在文件中的位置和相對虛擬地址相同,也為0×9486。

利用010Editor修改該位置(9486h)處的5個位元組,修改之前記錄下這5個位元組,後面還要在Shellcode里還原它們。

修改前:

修改後:

恢復OEP並跳轉到原OEP的Shellcode如下:

其中,99 99 99 99是跳轉到原OEP的偏移,66 66 66 66是原OEP的值,11 11 11 11 11是原OEP處的5個位元組(還記得上面修改前的5個位元組嗎55 8B EC 6A FF)。這幾個值是需要修改的。

偏移=原OEP-當前地址-5;

原OEP=9486

當前地址=0×38000(新OEP)+後門Shellcode大小(0×141)+7(恢復Shellcode中E9 99 99 99 99前面的位元組數)=0×38148

故偏移=0×9486-0×38148-5=0xFFFD1339

修改完畢後,不要忘記給這段跳轉到原OEP的shellcode加密。在這裡我們使用異或方式簡單的加密一下。然後在前面添加b)中的自解密shellcode:

其中0×178為Shellcode的大小-1,02為解密key

注意:因為跳轉到原OEP的shellcode後要添加上面這段自解密shellcode,所以跳轉偏移需要再減去解密shellcode的大小0x1f,最終偏移為0xFFFD131A.加密後的恢復shellcode如下:

把該Shellcode拼接到c)中的shellcode後,注意把原Shellcode後面的5個位元組JMP OEP刪除,完成程序能正常運行。繼續病毒檢測:

結果發現報毒率反而變高了,和OEP設置在shellcode段相比,我們沒有改變OEP的值,而是改變OEP處的跳轉,那麼是不是OEP跨段跳轉會是一個異常檢測點呢,又或是我們後來添加的這段跳轉回原OEP的shellcode呢。因為我們的恢復shellcode是加密的,所以和之前相比不應該報毒率變高才對,所以它出問題的概率應該不高。因此,我們把OEP處的跳轉給它還原成原來的值,相當於只是附加了shellcode,但是什麼都不做,再檢測一遍。

報毒率又降低了,說明我們不改變OEP的值,更改OEP處的跳轉作用不大。但這步檢測讓我們知道:更改OEP處的代碼比把OEP設置在shellcode段更容易被檢測到、OEP在正常段不容易被檢測到。

區段添加的shellcode的免殺率我們已經有所了解,下面我們看下代碼洞的表現。

e) 代碼洞添加的shellcode:

這就能看出來代碼洞添加shellcode的強大之處了。但是通過第三章我們也發現,代碼洞添加shellcode需要特殊文件特殊對待,不容易自動化。


在現有的工具中插馬、植入後門非常容易,那麼應該如何防範呢?

a) 首先是提高安全意識,不要隨意從網上下載執行軟體、下載最好去官方網站下載

b) 下載後檢查文件的數字簽名是否有效且為官方數字簽名。

c) 及時安裝安全軟體,雖然大部分惡意代碼發布時都具備免殺功能,但是隨著病毒庫的升級,對於惡意代碼檢測能力也在不斷提高,所以及時安裝、升級安全軟體是自我保護的一個重要方法。


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

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


請您繼續閱讀更多來自 瘋貓網路 的精彩文章:

小技巧——病毒分析中關閉ASLR
使用帶外數據從電子表格獲取數據

TAG:瘋貓網路 |