近日,Xshell官方發佈公告稱其軟件中存在後門。咱們的實習生同窗對該後門進行了詳細的分析,確認這是一個具有惡意代碼下載執行和數據回傳等能力的高級木馬。html
後門代碼存在於nssock2.dll
中,採用了多層加密shellcode、花指令、線程注入等各類方式逃避殺軟查殺和對抗人工分析。整體流程以下算法
經過BinDiff跟最新版的nssock2.dll
比較能夠很容易的發現一個解密shellcode的函數shell
去掉花指令分析,進入到shellcode後主要功能是先查詢HKCU\SOFTWARE\%d
或HKLM\SOFTWARE\%d
下的Data
值是否存在,%d
是把硬盤的序列號異或0xD592FC92
api
若是Data
值存在就用其中的key解密第二層的shellcode並執行,反之就會發送DNS請求獲取配置信息存儲到Data
鍵再解密第二層的shellcode並執行服務器
獲取配置信息時首先經過根據當前年月的DGA(域名生成算法)生成一個域名,其算法以下dom
而後會根據GUID、主機名和用戶名等信息生成一個前綴進行加密與以前生成的域名拼接後發送DNS請求並獲取配置信息函數
加密主要分兩步,第一步以下ui
第二步以下加密
DNS服務器爲8.8.8.8
、8.8.4.4
、4.2.2.1
、4.2.2.2
和當前主機的DNS服務器,接收到key後解密第二層shellcode的代碼以下spa
這裏很是有意思,算法跟從dll進入第一層shellcode時的解密算法一致,想到CTF的套路嘗試設爲相同的key,key1爲0xC9BED351
,key2爲0xA85DA1C9
,而後就成功解密出了第二層shellcode。
根據卡巴斯基的報告,第二層shellcode爲Root
插件,入口函數很像DllMain
主要功能是先設置異常處理函數,並會把異常記錄到%ALLUSERSPROFILE%\error.log
,而後初始化函數指針表(會在其餘插件中被調用),並加載5個插件
動態調試步入load_plugin
函數就能把5個插件的shellcode dump出來,加載完5個插件後會調用ID爲103
的插件(Install)的第二個函數
主要功能是先修改當前進程權限,再調用ID爲102
的插件(Config)的第二個函數
另外還會用winlogon.exe
進程的權限建立svchost.exe
進程進行線程注入,調試線程注入的shellcode能夠先在VirtualAllocEx
後下斷獲取到相應進程中的虛擬地址,而後在ResumeThread
時下斷,中斷後附加相應進程並在以前獲取的虛擬地址處下斷,執行ResumeThread
後會在以前的虛擬地址處中斷,以後就能夠繼續調試了,初步分析注入的shellcode就是Root
插件
根據磁盤序列號建立互斥體:Global\% 16-48 random latin characters%
主要功能是監聽根據磁盤序列號生成的註冊表項HKLM
或HKCU\SOFTWARE\Microsoft\%5-12 random characters%
監聽到有值改變後會解密並校驗是不是合法的插件並加載和初始化
此插件主要是跟配置信息的讀寫相關,其路徑根據磁盤序列號生成,本機是C:\ProgramData\MQGOMQQ\TOYMWGMQ\UMGSAIE\DIWEYK
,在每次初始化插件時都會被重寫
默認的C&C
地址是dns://www.notped.com
此插件主要是跟C&C
服務器通訊並把命令分發到相應的插件執行,首先根據協議類型選擇發送請求的插件
若是是URL
就會向根據年月的DGA生成的域名發送HTTP
請求來獲得真正的C&C
服務器地址
另外此插件也會收集更詳細的主機信息,依次調用GetSystemTime
、gethostbyname
、GlobalMemroryStatusEx
、GetNativeSystemInfo
、GetDiskFreeSpaceExA
、EnumDisplaySettingsW
、GetSystemDefaultLCID
、QueryPerformanceFrequency
、QueryPerformanceCounter
、GetCurrentProcessId
、RtlGetVersion
、GetSystemMetrics
、GetNetworkParams
和GetAccountSid
此插件主要是用於基於DNS協議的C&C
通訊
此後門用了多種手段來增長分析難度,是一個基於插件的完善的攻擊平臺,請儘快升級到最新版本。以上分析若有謬誤之處,歡迎斧正。
from idaapi import *
from ctypes import *
addr = 0x274DFC8
seed = c_uint(Byte(addr) | (Byte(addr + 1) << 8))
result = [None] * 4096
for i in range(4090):
result[i] = chr((seed.value & 0xff) ^ Byte(addr + 2 + i))
seed = c_uint(c_uint(c_uint(0x41120000 * seed.value).value - c_uint(0x434CBEEE * (seed.value >> 16)).value).value - 0x2F878E0F)
end = result.index('\x00')
print ''.join(result[:end])
域名 | 日期 |
---|---|
ribotqtonut.com | 2017年7月 |
nylalobghyhirgh.com | 2017年8月 |
jkvmdmjyfcvkf.com | 2017年9月 |
bafyvoruzgjitwr.com | 2017年10月 |
xmponmzmxkxkh.com | 2017年11月 |
notped.com | 默認C&C 域名 |