日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Ransomware Locky Analysis

發(fā)布時(shí)間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Ransomware Locky Analysis 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Locky的變種非常的多,這個(gè)樣本來(lái)自下面的Url,是最新的一種變種。?

這是程序在剛開(kāi)始執(zhí)行時(shí)與釋放了Image并替換了之后的對(duì)比,很明顯發(fā)生了進(jìn)程替換,因此進(jìn)行分析之前有必要把它內(nèi)部釋放出來(lái)的image提取出來(lái),分析這個(gè)image才能搞清楚它是如何做加密的。

?

?Locky存在一個(gè)未知的殼,IDA并不能檢測(cè)出這個(gè)殼,因?yàn)樗膶?dǎo)入表等信息并沒(méi)有被破壞。它在運(yùn)行起來(lái)后
,執(zhí)行相當(dāng)大量的垃圾代碼干擾調(diào)試,依據(jù)是在調(diào)試的過(guò)程中它進(jìn)行相當(dāng)多的寄存器操作但6個(gè)通用寄存器的值始終是0。

這這些垃圾代碼中隱藏著它獲取Kernel32.dll的Addr的邏輯,它會(huì)獲取Kernel32的BaseAddress并通過(guò)偏移計(jì)算出API的地址。

它會(huì)調(diào)用VirtualAlloc分配一塊可寫可執(zhí)行的內(nèi)存塊,大小是61BB,可執(zhí)行意味著會(huì)釋放代碼到這塊內(nèi)存區(qū)中,應(yīng)該著重分析。(0x404587

TextSegment中存在一部分未被IDA識(shí)別的func,位置在(0x402940)。這部分代碼的作用是將一些數(shù)據(jù)(在TextSegment中)釋放到剛才通過(guò)VirtualAlloc分配的內(nèi)存中去。

GenerateShellCodes(PVOID?lpShellCodes,?BYTE* pDataInTextSegment,?DWORD?dwLen,?DWORD?dwHEX);

其中bl寄存器用來(lái)作為臨時(shí)存儲(chǔ)一個(gè)字節(jié)的寄存器,ebx寄存器用作計(jì)數(shù)器,它從函數(shù)參數(shù)中獲得Data的Length,然后遞減,如果等于0就跳出循環(huán),esi是指向VirtualAlloc返回的內(nèi)存地址。處理完畢后,會(huì)在指定的位置寫入一堆數(shù)據(jù),這些數(shù)據(jù)還需要進(jìn)行異或處理才能變成真正可以被執(zhí)行的代碼。

以下是沒(méi)有被處理的數(shù)據(jù),只是單純的填充了緩沖區(qū)。

它的解這部分Code的算法如下:

其中dwHEX是這個(gè)處理函數(shù)的第四個(gè)參數(shù)。解完了以后的數(shù)據(jù)如下:

下面已經(jīng)完成了部分ShellCodes的釋放,接下來(lái)將跳轉(zhuǎn)到ShellCode去執(zhí)行代碼。

這段ShellCode的目的釋放一個(gè)被壓縮的PE文件,并加載這個(gè)PE文件,整個(gè)過(guò)程沒(méi)有釋放任何文件出來(lái),無(wú)法被監(jiān)控軟件發(fā)現(xiàn),釋放PE文件使用了非常精巧的方式加載到當(dāng)前進(jìn)程中,并完成了進(jìn)程替換。

被釋放的ShellCode本身還有很多代碼沒(méi)有釋放出來(lái),在ShellCode的Offset=247處有一個(gè)func用于釋放ShellCode中的代碼(釋放不太嚴(yán)謹(jǐn),應(yīng)該是通過(guò)一些異或操作把原來(lái)不是代碼的數(shù)據(jù)轉(zhuǎn)換成代碼)。

這個(gè)操作會(huì)將ShellCode頭部的一些代碼釋放出來(lái)。在后面經(jīng)過(guò)調(diào)試發(fā)現(xiàn),這個(gè)func會(huì)被反復(fù)的多次調(diào)用,用于釋放存在ShellCode中的數(shù)據(jù)(轉(zhuǎn)換成可以被執(zhí)行的CPU代碼)。因此這里應(yīng)該是釋放ShellCode自身代碼的邏輯。

sub_1D1020用來(lái)獲得Kernel32的BaseAddr:

GetModuleHandle

?

?

再被釋放的ShellCode+1020處有一個(gè)Func(SC_GetModuleAddr)它用來(lái)根據(jù)傳入的HardCode得到對(duì)應(yīng)的Module的基地址,例如Kernel32.dll Advapi32.dll等。

LPVOID SC_GetModuleAddr(DWORD dwHEX);

對(duì)應(yīng)的在ShellCode+1122處有一個(gè)Func(SC_GetFuncAddr)它用來(lái)根據(jù)傳入的HardCode得到對(duì)應(yīng)的func的基地址,例如Kernel32的GetProcAddress等。

PFUNC?SC_GetFuncAddr(DWORD?dwHEX,?LPVOID?lpModuleBaseAddr);

如下圖:

ShellCode會(huì)調(diào)用這段代碼GetProcAddress,并傳入Module的基地址以及要獲取的函數(shù)名。這里函數(shù)的名字被嵌入到了ShellCode中,被解釋稱代碼了,需要重新解析成字符串。注冊(cè)服務(wù),隱藏自己的行為。

后面的邏輯大致符合如下描述:

  • 首先通過(guò)壓入一些特定的HEX值獲取GetProcAddr的地址。
  • 然后傳入要用到的API所在的dll的基地址以及在ShellCode中隱藏的函數(shù)名。
  • 使用獲得的API,不緩存,下次再用還要走這個(gè)邏輯。
  • 例如:用同樣的方法獲得了EnumServicesStatusExA的函數(shù)地址。

    這里調(diào)用GlobalAlloc(ShellCode+001D0686)在堆上分配內(nèi)存分配的內(nèi)存用0初始化,大小是0x4214。(可能是一個(gè)結(jié)構(gòu))因?yàn)楸会尫诺袅恕?/p>

    這里又使用API分配了一塊內(nèi)存,大小是1799C。頁(yè)屬性是可讀寫不可執(zhí)行。這個(gè)函數(shù)的參數(shù)很值得注意,居然是當(dāng)前進(jìn)程的基地址。

    這里從當(dāng)前的進(jìn)程中釋放了一堆壓縮數(shù)據(jù)到剛才分配的內(nèi)存中,然后又繼續(xù)調(diào)用VirtualAlloc分配了一塊大小1AE00的內(nèi)存,頁(yè)屬性依然是可讀寫不可以執(zhí)行,這塊內(nèi)存用于解壓縮剛才釋放的壓縮數(shù)據(jù)。

    程序接下來(lái)調(diào)用了RtlDecompressBuffer這個(gè)Undocument的API。用于釋放壓縮的數(shù)據(jù)到指定的Buffer中。釋放出來(lái)的文件是一個(gè)PE Image。(ShellCode+318E)

    把這個(gè)PE dump出來(lái)之后可以從導(dǎo)入表中發(fā)現(xiàn)一堆Crypt相關(guān)的API,它就是真正加密用戶數(shù)據(jù)的PE。

    到這里后面的分析都與Ransomware沒(méi)有關(guān)系了,只要能拿到內(nèi)部的加密數(shù)據(jù)的文件進(jìn)行分析就可以了。下面是這段ShellCode作為加載器還有一些什么具體行為的分析。

    這里釋放了壓縮數(shù)據(jù)所占用的內(nèi)存。

    這里打開(kāi)了通過(guò)獲取當(dāng)前殼進(jìn)程的ImagePath,然后調(diào)用CreateFile打開(kāi)文件并計(jì)算文件的Size。

    計(jì)算出來(lái)的文件大小是31000,然后調(diào)用VirtualAlloc分配相同大小的空間。下面是VirtualAlloc的參數(shù)。可讀可寫不可以執(zhí)行。

    ?

    然后調(diào)用ReadFile從當(dāng)前Image的文件中讀取數(shù)據(jù),一次讀取完畢。

    然后關(guān)閉文件。

    現(xiàn)在內(nèi)存中有2份PE文件了,一份原始的殼的Image,還有一個(gè)被脫殼后真正做加密工作的Image。

    上面是原始?xì)さ腜E數(shù)據(jù)

    上面是被脫殼后的PE數(shù)據(jù)

    判斷它最后會(huì)還原回去,不然沒(méi)有必要保存一份在內(nèi)存中。這樣可以不用釋放文件,監(jiān)控軟件監(jiān)控不到,非常精明的設(shè)計(jì)。

    這里調(diào)用VirtualProtect來(lái)對(duì)0x400000位置的當(dāng)前Image設(shè)置可寫權(quán)限,要開(kāi)始覆蓋當(dāng)前的數(shù)據(jù)了。

    開(kāi)始將Image的內(nèi)容清空:

    然后從debug021:001D17E9開(kāi)始的一大段代碼用于填充新數(shù)據(jù)到當(dāng)前的Image中去。好大的一段代碼,因?yàn)閮?nèi)存中的PEOffset與加載到內(nèi)存后的Offset不一樣,所以需要小心的分段加載PE數(shù)據(jù),這里的代碼類似一個(gè)進(jìn)程加載器。

    寫完后的數(shù)據(jù)已經(jīng)與上面釋放出來(lái)的PE一樣了(對(duì)照0x200000地址數(shù)據(jù)),這里發(fā)生了進(jìn)程替換,它肯定還要找到新的PEEntryPoint開(kāi)始新的調(diào)用。

    調(diào)用RtlZeroMemory把釋放出來(lái)的在內(nèi)存中的做加密的PEImage擦除掉。

    然后調(diào)用VirtualFree釋放掉內(nèi)存(清理現(xiàn)場(chǎng))。

    ?

    現(xiàn)在調(diào)用VirtualProtect把在0x400000位置的新的PEImage頁(yè)屬性設(shè)為只讀。

    PEHeader,第一個(gè)頁(yè)面。繼續(xù)設(shè)置代碼段為可執(zhí)行可讀。

    到這里,新的PE已經(jīng)加載完畢了,應(yīng)該可以準(zhǔn)備執(zhí)行了。

    這里會(huì)把一些API用到的都取出來(lái)保存在棧上,后面用。有一些,不過(guò)我最關(guān)注的是CreateThread,然后它會(huì)清理ShellCode,清理犯罪現(xiàn)場(chǎng)。通過(guò)使用下面的API調(diào)用。清理的過(guò)程分幾個(gè)階段,頭部的ShellCode還保留,只是把除了頭部以外的都清理成0.

    可以看到從F6之后都是0了。

    然后調(diào)用VirtualFree把這整段Code刪除掉。到這里ShellCode的使命已經(jīng)完成,簡(jiǎn)單來(lái)說(shuō)它的目的就是將內(nèi)部的一個(gè)PE釋放出來(lái),并替換當(dāng)前進(jìn)程,并把當(dāng)前進(jìn)程的數(shù)據(jù)緩存到內(nèi)存中。

    然后,程序會(huì)執(zhí)行CreateThread,執(zhí)行新的PE代碼。

    405152就是新的進(jìn)程的EntryPoint,可以通過(guò)對(duì)提取的PEImage的分析佐證。

    至此,脫殼完成并且成功的分析到了這個(gè)殼的運(yùn)作機(jī)制。

    =========================運(yùn)行測(cè)試==========================

    這3個(gè)Sample的行為觀測(cè)很相似,但是從反匯編角度分析的話,技術(shù)在不斷的演進(jìn)。雖然都沒(méi)有檢測(cè)到殼的存在,但是在運(yùn)行的過(guò)程中會(huì)從代碼段或數(shù)據(jù)段釋放code出來(lái)執(zhí)行,也許有進(jìn)程替換。也懷疑有虛擬機(jī)檢查,因?yàn)槎紱](méi)有行為出現(xiàn)。

    ========================脫殼后分析========================

    脫殼后的程序可以正常運(yùn)行,但是之前也講過(guò)即使在物理機(jī)器上也沒(méi)有跑出行為,所以進(jìn)一步分析原因,以及分析Locky的整體運(yùn)作方式。

    這段程序的entrypoint據(jù)我判斷是手動(dòng)編寫的,非經(jīng)過(guò)編譯器產(chǎn)生。他在開(kāi)始調(diào)用C runtime的入口之前做了一些自定義的隱蔽工作,這并非編譯器的行為。它的詭異行為如下面所述:.reloc是一個(gè)配置塊,它的數(shù)據(jù)結(jié)構(gòu)用C來(lái)表述如下:

    程序會(huì)根據(jù)這個(gè)結(jié)構(gòu)的信息做對(duì)應(yīng)的處理,例如如果選擇模仿svchost,它就會(huì)偽裝成svchost,如果選擇自動(dòng)啟動(dòng),就會(huì)在注冊(cè)表中注冊(cè)自己,如果選擇了地區(qū)保護(hù),就會(huì)只針對(duì)相應(yīng)的地區(qū)展開(kāi)攻擊,等待時(shí)間被用來(lái)隱蔽自身,不立即運(yùn)行。

    ?

  • 脫殼后的程序在它的PE文件中偽裝了一個(gè).reloc的段,這個(gè)段中藏了4個(gè)IP地址。
  • 其中有2個(gè)目前仍然可以ping通。這些IP地址在內(nèi)存中的位置,被它保存到了一個(gè)全局指針中。

    ?

  • 它會(huì)去Hook NtQueryVirtualMemory,并針對(duì)所有的可執(zhí)行內(nèi)存頁(yè)查詢返回篡改后的結(jié)果。這個(gè)操作用來(lái)AntiDebug。
  • MEM_IMAGE

    0x1000000

    Indicates that the memory pages within the region are mapped into the view of an image section.

    ?

  • 程序會(huì)取出真正的.reloc段,并在內(nèi)存中分配一塊內(nèi)存,把當(dāng)前的Image拷貝到新的內(nèi)存地址,并用當(dāng)前Image與新內(nèi)存中的Image的diff addr去處理.reloc段,使得執(zhí)行新內(nèi)存時(shí)能夠定位到正確的函數(shù)地址(外部導(dǎo)入)。
  • 這個(gè)操作使得原始Image程序的main函數(shù)不會(huì)被進(jìn)入,反調(diào)試。


    Jump2NewImage會(huì)跳轉(zhuǎn)到已經(jīng)解決了重定位問(wèn)題的新的在內(nèi)存中Image中,并開(kāi)始從pop這條指令開(kāi)始執(zhí)行,從下面圖可以看出指令是一致的。

    這里已經(jīng)分析出了它實(shí)際會(huì)返回到調(diào)用指令的下一跳指令中,只不過(guò)不再是同一個(gè)內(nèi)存中的Image,解決這個(gè)問(wèn)題直接打掉patch就可以。如下圖:

    將PerpareForRunInOtherImage打上Patch,這個(gè)func的目的是反調(diào)試,會(huì)堅(jiān)持程序斷點(diǎn),同時(shí)它會(huì)跳到一個(gè)內(nèi)存中的其它位置執(zhí)行相同的程序,同時(shí)調(diào)整重定向表,因此在這個(gè)函數(shù)內(nèi)部打patch沒(méi)用,因?yàn)橹囟ㄏ虮肀恍薷暮髸?huì)導(dǎo)致程序崩潰。

    最簡(jiǎn)單的修改方法。現(xiàn)在,所有的障礙都已經(jīng)掃除可以調(diào)試并分析這個(gè)Sample了。

    程序在進(jìn)入主函數(shù)之后,立即安裝一個(gè)頂級(jí)的未處理異常處理器,會(huì)在發(fā)生無(wú)法解決的異常后重新啟動(dòng)自己。

    然后程序會(huì)把藏在上述中起迷惑作用的.reloc段中的4個(gè)Ip地址以及包含Ip地址的數(shù)據(jù)結(jié)構(gòu)取出來(lái),Ip地址會(huì)被放到一個(gè)vector中保存起來(lái)。

    從上面的一張內(nèi)存截圖可以看到,IP地址是使用逗號(hào)分隔的。

    查找逗號(hào)在String中。

    加入全局的std::vector<std::string>中。

    接下來(lái)它會(huì)檢查藏在.reloc中的數(shù)據(jù)結(jié)構(gòu)中的相應(yīng)的值。

    它會(huì)避開(kāi)俄語(yǔ)區(qū)用戶,LABEL_21處有個(gè)function,調(diào)用它會(huì)先將當(dāng)前程序的File找到,然后移除所有屬性,隨后生成一個(gè)臨時(shí)目錄,將Image移動(dòng)過(guò)去,可能會(huì)失敗,會(huì)采用MOVEFILE_DELAY_UNTIL_REBOOT來(lái)調(diào)用MoveFileEx標(biāo)記為重啟刪除。緊接著構(gòu)造一個(gè)“cmd.exe /C del /Q /F”串并把原路徑文件加入到這個(gè)串的后面,調(diào)用CreateProcess來(lái)刪除文件,最后退出程序。

    接下來(lái)會(huì)根據(jù)藏在.reloc中的數(shù)據(jù)然后根據(jù)數(shù)值去等待,目前等待的時(shí)間超過(guò)3天,這是我們無(wú)論如何都沒(méi)有跑出行為的原因。

    這里打上patch,跳過(guò)這些邏輯,使得程序可以正常運(yùn)行,避免一些內(nèi)部邏輯導(dǎo)致的程序不運(yùn)作不能反映出真實(shí)行為。

    接下來(lái)的代碼會(huì)通過(guò)”GetVolumeNameForVolumeMountPoint”API,根據(jù)Volume獲取一個(gè)GUID,然后對(duì)這個(gè)GUID進(jìn)行hash得到一個(gè)hash值,再通過(guò)這個(gè)hash值得到一個(gè)字符串并把它鏈接到HKLM\Software\{xxxxxxxxxxx}用于創(chuàng)建一個(gè)注冊(cè)表項(xiàng)。

    緊接著它會(huì)用藏在.reloc中的數(shù)據(jù)結(jié)構(gòu)中的值判斷是否需要模仿svchost運(yùn)行,如果是它會(huì)將自己Copy到一個(gè)隨機(jī)目錄并重命名為svchost.exe,并通過(guò)CreateProcess重啟進(jìn)程并結(jié)束自己的當(dāng)前運(yùn)行。

    接下來(lái)會(huì)先去獲取本地機(jī)器的信息,之前通過(guò)Volume的GUID算出的一個(gè)hash被用作機(jī)器信息的ID,這部分?jǐn)?shù)據(jù)會(huì)被提交到作者的服務(wù)器上面去。

    “id=D2BCC112BD05308A&act=getkey&affid=3&lang=en&corp=0&serv=0&os=Windows+7&sp=1&x64=0”

    然后用MD5對(duì)這部分?jǐn)?shù)據(jù)進(jìn)行hash:

    程序接下來(lái)將系統(tǒng)信息的hash數(shù)據(jù)追加到系統(tǒng)信息的頭部,作者可以利用這個(gè)hash值校驗(yàn)數(shù)據(jù)一致性,然后通過(guò)一個(gè)循環(huán)移位加異或算法對(duì)這部分?jǐn)?shù)據(jù)加密,如下圖。

    接下來(lái)它準(zhǔn)備要發(fā)送數(shù)據(jù)到作者的WebServer上面去,最開(kāi)始說(shuō)了作者在偽裝的.reloc中藏了一些配置信息,同時(shí)包含4個(gè)主機(jī)地址,在程序一開(kāi)始,這四個(gè)主機(jī)地址被加入了一個(gè)vector中,程序通過(guò)獲取一個(gè)隨機(jī)數(shù)字,并對(duì)存儲(chǔ)在vector中的ip_addrnum取余數(shù)來(lái)隨機(jī)選擇一個(gè)Ip地址用于訪問(wèn)。

    它先構(gòu)建一個(gè)http地址:使用上面的信息創(chuàng)建一個(gè)http對(duì)象,然后設(shè)置一些參數(shù):

    發(fā)送和接收的延遲設(shè)置為30000,重試次數(shù)1次。

    這里發(fā)生了問(wèn)題,首先我可以連接到服務(wù)器,但是在向?qū)Ψ桨l(fā)送數(shù)據(jù)的時(shí)候,失敗了返回的HttpError 403 Forbidden:資源不可用。服務(wù)器理解客戶的請(qǐng)求,但拒絕處理它。通常由于服務(wù)器上文件或目錄的權(quán)限設(shè)置導(dǎo)致。所以這個(gè)sample因?yàn)闊o(wú)法將用戶信息上傳出去,陷入了一個(gè)軟件異常,不會(huì)繼續(xù)執(zhí)行加密操作。這里得想辦法讓他跳過(guò)這個(gè)發(fā)送的步驟直接去加密用戶數(shù)據(jù)。以下是嘗試發(fā)送的數(shù)據(jù),包含了用戶的SysInfo和一個(gè)用于校驗(yàn)的Hash被循環(huán)左移右移異或擾亂后的數(shù)據(jù)。

    ?

    修改2處檢查點(diǎn),讓它不發(fā)送Crypt信息,直接開(kāi)始加密文件,但我判斷在發(fā)送了用戶的SysInfo后,服務(wù)器可能會(huì)計(jì)算一個(gè)PublicKey并通過(guò)網(wǎng)絡(luò)返回到本地,因?yàn)長(zhǎng)ocky如果請(qǐng)求不到網(wǎng)絡(luò)的話它不會(huì)做任何事情,因此判斷可能不存在Default的Key。

    ?

    上面的判斷是正確的,因?yàn)樵谙旅娴姆治鲋?#xff0c;當(dāng)準(zhǔn)備開(kāi)始加密數(shù)據(jù)的時(shí)候,程序調(diào)用了一個(gè)API函數(shù):CryptImportKey,在這個(gè)函數(shù)的參數(shù)中送入了一個(gè)全局變量,通過(guò)IDA xref我可以看到這個(gè)全局變量既是服務(wù)器返回的數(shù)據(jù),因此可以判斷出程序使用用戶機(jī)器的相關(guān)信息計(jì)算出一個(gè)PublicKey,用這個(gè)Key對(duì)數(shù)據(jù)進(jìn)行加密(部分,或加密對(duì)稱加密的Key),因此這個(gè)API也許可以去Hook,然后替換一個(gè)自己的Key,用于日后解密。

    ?

    我們打上Patch,讓他不發(fā)送用戶信息到服務(wù)器上面去,直接開(kāi)始加密文件,進(jìn)入到枚舉驅(qū)動(dòng)器資源的階段(我看過(guò)的所有Ransomware都有這個(gè)步驟),首先它會(huì)去枚舉網(wǎng)絡(luò)驅(qū)動(dòng)器,例如Nas,這里我們不管它,因?yàn)樵诿杜e網(wǎng)絡(luò)驅(qū)動(dòng)器的時(shí)候虛擬機(jī)調(diào)試會(huì)拋出異常,我也patch了。

    ?

    枚舉到的所有網(wǎng)絡(luò)驅(qū)動(dòng)器資源它會(huì)先將它們放到一個(gè)vector<std::string>向量描述的鏈表中保存起來(lái)。

    接下來(lái)會(huì)繼續(xù)枚舉本地磁盤驅(qū)動(dòng)器,下面會(huì)有一堆的判定條件是否要處理這個(gè)磁盤,首先會(huì)排除所有帶有remote屬性的,并且如果是可以拔插的如USB也不處理,如果磁盤的總大小低于A00000(1MB)跳過(guò),如果磁盤類型是Fixed、Removable以及Ramdisk都不處理,如果磁盤信息中包含的SystemFlags超過(guò)了19也不處理,邏輯如下:

    程序?qū)⑺蟹弦蟮拇疟P依次加入vector中保存起來(lái),最后會(huì)返回這個(gè)vector(其實(shí)這是一個(gè)在棧上的vector,程序最后會(huì)將這個(gè)vector的內(nèi)容復(fù)制到作為入?yún)⒌耐獠縱ector中)。

    ?

    當(dāng)準(zhǔn)備好所有的可以加密的驅(qū)動(dòng)器后,程序會(huì)針對(duì)每一個(gè)驅(qū)動(dòng)器啟動(dòng)一個(gè)線程來(lái)執(zhí)行加密工作,在線程加密的同時(shí),程序會(huì)刪除掉系統(tǒng)還原的影子盤,最后程序會(huì)block自己知道wait到了所有的線程執(zhí)行完畢的event。在這個(gè)進(jìn)入waiting之前,它會(huì)根據(jù).reloc中的配置選擇是不是要安裝自啟動(dòng)。這些操作都完畢后,主線程進(jìn)入wait狀態(tài)。

    接著程序會(huì)進(jìn)入到線程中執(zhí)行,線程執(zhí)行的代碼是加密用戶數(shù)據(jù)。加密線程首先枚舉當(dāng)前驅(qū)動(dòng)器中的所有文件,并加入到vector中。這個(gè)過(guò)程中,篩選的文件會(huì)過(guò)濾掉一些指定的文件路徑,也會(huì)過(guò)濾掉不感興趣的后綴名文件。

    過(guò)濾特定的文件路徑

    過(guò)濾特定的后綴

    ?

    Locky也是按照訪問(wèn)時(shí)間順序排序的,也就是說(shuō)最后被訪問(wèn)的文件最先被加密,不過(guò)它存在一個(gè)Bug,它會(huì)先找最后被訪問(wèn)的文件夾,比如在一個(gè)超大文件夾中有一個(gè)文件被修改了,那么這個(gè)文件夾的訪問(wèn)時(shí)間也會(huì)被修改,但是這個(gè)文件夾中其它的文件很長(zhǎng)一段時(shí)間都沒(méi)有被訪問(wèn),Locky會(huì)最先加密這個(gè)文件夾中size最小的文件,直到加密完整個(gè)文件夾,才去找下一個(gè)文件夾,如果下一個(gè)文件夾中所有的文件都是最近訪問(wèn)過(guò)的,它也會(huì)優(yōu)先加密只有一個(gè)文件是最后訪問(wèn)時(shí)間的文件夾,Locky沒(méi)有處理這種情況。

    在我的機(jī)器中,它會(huì)優(yōu)先加密IDA文件夾。顯然Ransomware也存在如何精確定位有價(jià)值信息這個(gè)問(wèn)題。

    接著,程序開(kāi)始將通過(guò)WebServer計(jì)算得到的對(duì)應(yīng)用戶SysInfo的PublicKey從內(nèi)存中取出來(lái),通過(guò)API:CryptImportKey來(lái)得到一個(gè)PublicKey對(duì)象。因?yàn)檫@里我們之前分析無(wú)法訪問(wèn)Locky作者的WebServer 403拒絕訪問(wèn)了,因此這里會(huì)丟出軟件異常,無(wú)法開(kāi)始加密數(shù)據(jù)。

    這里的pbData是從全局對(duì)象中取出來(lái)的,因?yàn)檫@里沒(méi)有publickey,我需要構(gòu)造一個(gè)自己Key送進(jìn)去,讓他繼續(xù)工作,因此我生成了一個(gè)公私鑰對(duì)送了一個(gè)自己的PublicKey給程序。

    PublicKey

    ?

    這里程序初始化了一個(gè)內(nèi)部使用的CryptObject,它的數(shù)據(jù)結(jié)構(gòu)如下:

    其中hKey是已經(jīng)導(dǎo)入的PublicKey的句柄,剩下的16個(gè)字節(jié)是對(duì)應(yīng)于用戶Machine的系統(tǒng)信息產(chǎn)生的Hash被用于用戶標(biāo)識(shí)。

    初始化完CryptObject后,程序得到了PublicKey以及User的機(jī)器ID,將這個(gè)對(duì)象傳入EncryptFile開(kāi)始執(zhí)行加密工作。

    加密函數(shù)除了Crypt對(duì)象外,還吃一個(gè)filename,來(lái)決定加密哪一個(gè)文件。

    在內(nèi)部,程序會(huì)根據(jù)傳進(jìn)來(lái)的filename計(jì)算一個(gè)hash,然后CryptObj中包含一個(gè)User機(jī)器的ID,新文件名=UserMachineID+filename_hash+.locky;

    接著程序會(huì)打開(kāi)需要加密的文件,并把源文件重命名為上面的這種文件名,Locky接著會(huì)去檢查是否有硬件加速可以用,如果有的話采用增強(qiáng)指令集加速加密的過(guò)程。

    Advanced Encryption Standard Instruction Set (or the Intel Advanced Encryption Standard New Instructions; AES-NI) is an extension to the x86 instruction set architecture for microprocessors from Intel and AMD proposed by Intel in March 2008.[1] The purpose of the instruction set is to improve the speed of applications performing encryption and decryption using the Advanced Encryption Standard (AES).

    ?

    Locky通過(guò)WindowsAPI CryptGenRandom生成一個(gè)16字節(jié)的種子值。

    如果有硬件加速可以用(目前CPU基本都支持硬件加速),分配一個(gè)以16字節(jié)對(duì)齊的內(nèi)存塊。接著用16字節(jié)種子初始化這個(gè)內(nèi)存塊。

    隨后,Locky使用之前傳進(jìn)來(lái)的PublicKey調(diào)用API:CryptEncrypt對(duì)種子值進(jìn)行加密。

    Size=16,pbBuffer存儲(chǔ)的是通過(guò)CryptGenRandom生成的隨機(jī)值。

    ?

    如果加密后的返回的數(shù)據(jù)塊的大小不等于256,那么會(huì)丟出異常,這里的作用是判斷生成的Key長(zhǎng)度是不是正確。

    ?

    在這個(gè)加密函數(shù)中,有一個(gè)數(shù)據(jù)結(jié)構(gòu)和派生自一個(gè)基類的兩個(gè)類值得說(shuō)一下,其中EncryptBlock這個(gè)數(shù)據(jù)結(jié)構(gòu)大致的作用是用來(lái)保存當(dāng)前加密用的上下文,它保存了兩個(gè)固定的用于xor的4字節(jié)數(shù)據(jù),用戶的SysInfo的ID,一個(gè)128位的種子值(通過(guò)CryptGenRandom得到),一個(gè)MAX_LEN長(zhǎng)度的雙字節(jié)數(shù)組用于保存當(dāng)前文件的文件名,還有代表當(dāng)前文件屬性的bitmap,以及文件size,結(jié)構(gòu)如下。

    ?

    另外兩個(gè)類對(duì)象是Encrypto的主體,它們都用Encrypto派生出來(lái),一個(gè)帶有硬件加速功能EncryptoAC,一個(gè)沒(méi)有帶有硬件加速功能EncryptoNoAC。

    ?

    我只分析了帶有硬件加速的對(duì)象,它有5個(gè)方法,它的數(shù)據(jù)成員中包含一個(gè)AESkey,它是用EncryptBlock中的128位隨機(jī)數(shù)生成的(需要知道的是,當(dāng)用這個(gè)隨機(jī)數(shù)初始化完畢AESKey之后,隨機(jī)數(shù)即被作者用PublicKey加密了),生成的算法如下:

    ?

    生成完AESKey之后,加密對(duì)象會(huì)先將當(dāng)前加密上下文用AESKey加密了,

    緊接著,將文件待加密的文件讀到內(nèi)存中,然后加密文件。

    這里可能發(fā)現(xiàn)參數(shù)不一樣了,實(shí)際上因?yàn)榇嬖趦蓚€(gè)加密對(duì)象,根據(jù)是否支持硬件加速選擇不同的加密對(duì)象,所以IDA這里翻譯的有點(diǎn)問(wèn)題,不用在意,實(shí)際上就是一個(gè)function。

    緊接著會(huì)把加密后的文件寫入磁盤,完成一個(gè)文件的加密工作,剩下的工作有寫一些幫助(勒索)文件向用戶提示應(yīng)該如何轉(zhuǎn)賬之類的操作,不細(xì)說(shuō)了。下面總結(jié)一下Locky的加密邏輯。

    ?

  • 準(zhǔn)備用戶信息,通過(guò)用戶的磁盤Volume上面的GUID以及系統(tǒng)信息計(jì)算一個(gè)Hash并作為用戶標(biāo)識(shí)。
  • 上傳用戶SysInfo,服務(wù)器根據(jù)上傳的資料生成一個(gè)PublicKey。
  • 枚舉所有文件,找最新被使用的文件,根據(jù)文件名計(jì)算Hash,來(lái)定位文件。
  • 構(gòu)造解密塊,Size=0x344,內(nèi)部有兩個(gè)常量DWORD,可能用于Locky作者鑒別Locky的Magic以及Version,內(nèi)部還包含加密文件的原路徑,文件大小,文件屬性。包含用于鑒別用戶的MachineID,同時(shí)包含一個(gè)128位隨機(jī)數(shù)。
  • 導(dǎo)入之前從服務(wù)器獲得的PublicKey,并用解密塊中的128位隨機(jī)數(shù)生成一個(gè)AESKey,之后立刻用PublicKey加密128位隨機(jī)數(shù)。
  • 打開(kāi)文件,用AESKey加密文件。
  • 用AESKey加密解密塊(部分,只加密文件名,文件信息,文件尺寸等信息,頭部的用用戶MachineID和被RSA加密的隨機(jī)數(shù)部分不在進(jìn)行二次加密)。
  • 將被加密的文件寫到新文件,新文件的文件名為UserMachineID+FileHash+”.Locky”。
  • 在新文件的尾部追加解密塊,完成整個(gè)加密過(guò)程。
  • ?

    ?

    解密邏輯,猜測(cè):

  • 通過(guò)UserMachineID檢索用戶的PrivateKey。
  • 打開(kāi)文件,取出解密塊頭部,用PrivateKey解密?隨機(jī)數(shù)?,用隨機(jī)數(shù)生成AESKey。
  • 用AESKey解開(kāi)揭秘塊,取出文件原名。
  • 用AESKey解開(kāi)文件,并寫到新文件,并恢復(fù)原名。
  • ?

    目前解法就是暴力破解隨機(jī)數(shù),看起來(lái)是不可行的。

    ?

    從solution的角度,有兩個(gè)點(diǎn),一個(gè)是生成隨機(jī)數(shù)的地方,Hook:CryptGenRandrom,然后替換一個(gè)自己的隨機(jī)數(shù),這樣我們可以用自己的隨機(jī)數(shù)推出AESKey,這樣就可以解開(kāi)文件。

    ?

    另外一個(gè)辦法,Hook:CryptImportKey,將從WebServer返回的PublicKey替換成自己的Key,這樣我們可以用自己的PrivateKey解開(kāi)解密塊中的隨機(jī)值,推出AESKey,也可以解開(kāi)文件。

    ?

    下面有一組測(cè)試用的資料:由于安全原因就不上傳了,有興趣可以@ tedzhang2891@gmail.com與我聯(lián)系。


    原文地址:?http://ec2-52-196-167-189.ap-northeast-1.compute.amazonaws.com/wordpress/index.php/2016/08/07/ransomware-locky-analysis/

    總結(jié)

    以上是生活随笔為你收集整理的Ransomware Locky Analysis的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲国产精品视频一区 | 国产精品国产精品国产专区不卡 | 毛片在线观看视频 | 国语精品久久 | 永久免费看片在线播放 | 成人激情综合 | 2022av在线| 国产福利在线看 | 欧美极品videos精品 | 亚洲一级在线 | 一本—道久久a久久精品蜜桃 | 欧美人与动牲交xxxxbbbb | 亚洲av综合色区无码另类小说 | 91视频爱爱 | 欧美性猛交aaaa片黑人 | 欧美男同又粗又长又大 | 国产91色| 欧美理论在线 | 在线观看三区 | 欧美三级视频在线播放 | 黄色av网站在线观看 | 国产偷自拍| 亚洲高清在线播放 | 精品国产乱码久久久久久蜜柚 | 国产鲁鲁视频在线观看免费 | yy6080久久| 伊人成人在线视频 | 日本中文字幕第一页 | 欧美黄色录像视频 | 久久澡| 免费视频色 | 国产在线观看一区二区三区 | 黄a视频| 国产无遮挡又黄又爽 | 91爱爱com| 日韩欧美综合视频 | 奇米影视777四色 | jiuse九色 | 日韩欧美视频在线免费观看 | 先锋av资源网站 | 野战少妇38p | 美女试爆场恐怖电影在线观看 | 中文字幕乱码人妻无码久久95 | av怡红院 | 五月色婷婷综合 | 手机在线毛片 | 国产视频123区 | 国产专区一区 | 成年人拍拍视频 | 人妻少妇一区二区 | 先锋资源网av| 69色堂 | 日韩六区 | 成人三级影院 | 成人综合区 | 麻豆国产一区二区三区四区 | 久久国产主播 | 亚洲人在线观看视频 | 伊人网免费视频 | 国产成人精品av久久 | 中文字幕成人动漫 | 久久看看| wwwxxxx国产 | 77久久| 午夜看黄神器 | 国产做受入口竹菊 | 亚洲欧美va天堂人熟伦 | 特黄做受又粗又大又硬老头 | 一区二区久久精品66国产精品 | 欧美天堂 | 亚洲视频999 | 欧美日韩激情在线一区二区三区 | 国产一区二区三区四区视频 | 午夜精品福利一区二区三区蜜桃 | 91鲁| 免费av看片| 国产精品女人精品久久久天天 | 国产91精品久久久久 | 奇米精品一区二区三区四区 | 日韩女优一区 | 国产第3页 | 艳母日本动漫在线观看 | 色综合a| 观看av| 一区二区精 | 国产一区二区在线不卡 | 日韩成人精品视频 | 国产成人精品亚洲 | 一区二区三区播放 | 亚洲激情午夜 | 情侣自拍av| 欧洲免费av | 日韩不卡一区二区三区 | 男朋友是消防员第一季 | 亚洲高清无码久久 | 成人一区二区三区 | 国产熟妇一区二区三区四区 | 久久av导航 | 熟女肥臀白浆大屁股一区二区 |