Author:王陽東(云安全研究員)@360信息安全部
近期, 部署于360云平臺(https://cloud.#)的”360天眼威脅感知系統”發現系統告警某合作伙伴剛開通的云主機存在異常流量,聯合排查后發現有惡意攻擊者利用redis crackit漏洞入侵服務器并種植了名為unama的惡意程序。 360云安全研究員 --“王陽東”對此惡意程序進行較為深入的分析,此樣本可能是billgates僵尸網絡的一個變種。
billgates是一個近幾年非常活躍的DDoS僵尸網絡,此程序組成的僵尸網絡遍及世界。網絡中bot節點多是一些存在弱口令或軟件漏洞的linux主機,攻擊者利用ssh爆破、exploit、1day、2day等方式對大量IP進行攻擊嘗試獲得服務器的控制權,并通過部署僵尸木馬被控端壯大僵尸網絡。僵尸網絡根據服務端命令可以實現DDoS攻擊、反彈shell等多種操作。
捕獲到的樣本文件大小為1223123
字節,MD5值為EFF1CB4E98BCC8FBCBDCA671D4C4A050
。
通過readelf得到的源代碼文件名共有44個,從源文件名猜測此程序有較多工作線程。
靜態分析后發現此樣本不同部分間的代碼風格差異較大:main函數的代碼比較簡單粗糙,而主功能類CManager及附屬類部分卻展現出病毒作者對C++的熟練應用。
初始化操作:
程序使用自定義算法從.rodata段解密出配置信息并保存,獲取程序文件大小與配置信息中的對應值進行對比實現簡單的自校驗,然后在父進程路徑中查找gdb實現反調試。
調用自定義解密函數,獲取硬編碼數據進行拼接,得到如DbSecuritySpt、selinux、getty、/tmp/moni.lod、/tmp/gates.lod等字符串并存儲到全局變量。檢查當前程序路徑確定要執行的功能。 路徑和功能的關系如下:
程序路徑 | 后門種類 | 功能函數 | 主要功能 |
---|---|---|---|
/usr/bin/.sshd |
MainMonitor | Monitor,守護進程 | |
未知路徑 (與其它類型不匹配) | 1 | MainBeikong 安裝等操作,并執行主要功能 | |
/usr/bin/bsd-port/getty |
2 | MainBackdoor | 主要功能執行程序 |
/bin/ 、/usr/bin/ 、/usr/sbin/ 下netstat、lsof、ps或ss |
3 | MainSystool | 運行/usr/bin/dpkgd 下備份的系統工具并過濾輸出信息 |
若是0,1,2類后門則從硬編碼中拼接一串十六進制數字符串(其實是兩部分十六進制數,以大寫字母O分隔,看似一串),
根據后門類型解密對應部分的十六進制數串,0,1類后門得到的配置是173.254.230.84:3411:1:1:yz:1,
2類后門得到的配置是fk.appledoesnt.com:30000:1:1:yz:1
。用冒號分隔字符串得到6個配置項并保存。
檢測文件名是否是“update_temporary”,若是則執行DoUpdate并退出。
執行對應的功能函數。
MainMonitor(守護進程):
進入daemon,產生pid文件/tmp/moni.lod
,讀取/tmp/notify.file
內容并保存,創建線程類CThreadMonGates并啟動監視線程,主線程循環sleep掛起。監視線程每分鐘判斷一下/tmp/gates.lod
文件(MainBackdoor功能進程的pid file), 若文件不存在則復制自身到從notify.file中獲取到的文件路徑并執行新路徑下的程序。
MainBeikong(程序安裝):
進入daemon模式,調用KillChaos結束/tmp/moni.lod
和/tmp/gates.lod
指向的舊進程 (病毒作者搞錯了strcmp的返回值,所以這里的代碼并沒有什么卵用),再次結束/tmp/moni.lod
,結束/tmp/bill.lock
并刪除bill.lock。再次結束/tmp/gates.lod
并設置自身pid文件。在/etc/init.d
、/etc/rc(1-5).d
等路徑設置S97DbSecuritySpt啟動項。
結束/usr/bin/bsd-port/
下getty.lock和udevd.lock對應的進程,刪除udevd.lock,復制自身到/usr/bin/bsd-port/getty(對應MainBackdoor)
并啟動。將當前程序路徑寫入/tmp/notify.file
(守護進程使用),復制當前文件到/usr/bin/.sshd
(對應MainMonitor)并啟動。執行MainProcess函數。MainProcess函數包含了木馬的主要功能。
之所以在安裝操作中執行猜測是因為病毒的一處配置錯誤:
由于之前以字母O分隔的兩串hex順序搞反了,導致2類后門(木馬功能主體)得到的是fk.appledoesnt.com這一無效域名,而1類后門(安裝程序)卻能得到173.254.230.84:3411這個有效IP,所以在沒有找到問題原因的情況下在安裝函數最后加入主功能函數(MainProcess)也不失為一種臨時解決方案。
MainSystool(系統工具替換):
獲取當前程序名及參數,調用/usr/bin/dpkgd/
下對應的原始系統程序(netstat 、lsof、ps、ss)。從原始系統程序的輸出中過濾掉包含木馬所在目錄、服務端通信端口等信息的行。
MainBackdoor(木馬功能主體):
進入daemon,設置pid文件,以 S99selinux為服務名創建啟動項。移動系統程序ps、ss、netstat、lsof到/usr/bin/dpkgd/
目錄,復制自身到/bin
、/usr/bin
、/usr/sbin
下替換ps、ss、netstat、lsof等系統程序,執行主功能函數MainProcess。
MainProcess函數:
主功能函數MainProcess首先掛起2秒,刪除升級用的臨時文件(./update_temporary
),根據/etc/resolv.conf
和谷歌dns(8.8.8.8、8.8.4.4)初始化CDNSCache類的實例g_dnsCache
。
初始化g_cnfgDoing
(嘗試讀取conf.n文件)、g_cmdDoing
(嘗試讀取cmd.n文件)、g_statBase
類實例,將g_sProvinceDns
中330個IP轉為數字形式存入g_provinceDns
對象。嘗試通過insmod加載當前目錄下的xpacket.ko驅動(未發現此文件)。從/usr/lib/libamplify.so
中讀取IP存入g_AmpResource
結構(未發現此文件)。初始化CManager(1076字節),設置信號處理函數,無限循環sleep。
CManager類包含了bot的所有功能,此類擁有很多成員,每個成員實現一定的功能,其主要成員對應列表大致如下:
成員 | 偏移 | 功能 |
---|---|---|
vectorIPs | 0x00 | 控制服務器IP地址(可存在多個) |
CThreadSignaledMessageList |
0x0c | CCmdMsg的消息隊列(線程安全) CCmdMsg包含控制服務器下發的控制指令 |
CThreadTaskGates | 0xe4 | 任務分發線程類,等待CCmdMsg消息隊列 |
CThreadClientStatus | 0xe8 | 狀態更新線程類,每秒更新cpu及網絡使用情況 |
CThreadSignaledMessageList |
0xf0 | CThreadConnection的隊列(線程安全) |
CThreadLoopCmd | 0x1c8 | 循環等待信號,并最終執行cmd.n文件配置的命令 |
CThreadFakeDetect | 0x1cc | 測驗bot有效性的類 |
CThreadSignaledMessageList |
0x1d0 | CThreadShell的隊列(線程安全) CThreadShell用來保持一個反向連接的shell會話 |
CThreadDoFun | 0x2ac | 通過一些計算判斷bot文件有效性并設置g_bReal 變量 |
CThreadKillChaos | 0x2b0 | 每5分鐘檢查pid file并執行清理 |
CInitResponse | 0x2b4 | 初始化數據包,包含當前被控機器的一些狀態數據 |
CThreadMutex_Operation | 0x378 | CManager互斥量,線程安全 |
SetOfCThreadFXConn | 0x390 | CThreadFXConnection類組成的set (C++ STL) |
CTask | 0x400 | 包含控制服務器下發的命令信息 |
CManager::Initialize
函數對成員進行了初始化操作,根據g_cmdDoing
檢查是否有未處理的命令,若有則立刻執行。
初始化完成員變量后執行CManager::MainProcess
,根據g_iGatsIsFx
的值(此時為1)設置程序工作在被控端模式,獲取vectorIPs中的IP (此時只有strConnTgts指向的IP)針對每個IP初始化一個CThreadFXConnection并加入set,完成后無限循環sleep。
CThreadFXConnection線程類最終調用CManager::FXConnectionProcess
建立與控制服務器的TCP連接,連接建立后調用CManager::ConnectionProcess
初始化CInitResponse對象并發送一個通知數據包:
其中CInitResponse中包含IP(c0 a8 7a 87) 192.168.122.135,系統版本信息,Cpu及內存等信息。
發送完初始化包后,CManager::ConnectionProcess
進入收發數據的循環,通過CManager::RecvCommand
接收數據并封裝到CCmdMsg結構,將CCmdMsg加入CThreadSignaledMessageList<CCmdMsg>
隊列。
通過CManager::SendClientStatus
發送bot狀態。
CCmdMsg由CManager::TastGatesProcess
線程負責從接收隊列中取出并分發(CThreadTaskGates線程類啟動的線程)。
CCmdMsg大致類型如下:
類型 | 功能 |
---|---|
1 | 調用CManager::DoAtkStartCommand初始化一個DDoS攻擊 |
2 | 根據CManager狀態選擇執行CManager::StopUpdate停止更新或CManager::StopAtkTask停止攻擊 |
3 | 調用CManager::DoConfigCommand更新g_cnfgDoing及conf.n配置文件 |
5 | 調用CManager::DoUpdateCommand更新程序文件 |
7 | 調用CManager::DoCommandCommand更新CCmdDoing對象 |
8 | 調用CManager::DoFakeDetectCommand |
9 | 調用CManager::DoShellCommand建立到指定IP及端口的反彈shell連接 |
CManager類大致結構如下:
DDoS攻擊最終通過CManager::DoAtkStartCommand
實現,這個函數讀取CCmdMsg中的CTask對象,根據CConfigDoing(conf.n)全局配置設置CThreadAtkCtrl線程對象。CThreadAtkCtrl::ProcessMain
會根據配置執行普通攻擊或內核級攻擊。普通攻擊通過CThreadAtkCtrl::DoNormalSubTask
執行,該函數最終調用CThreadAtkCtrl::StartNormalSubTask
,根據每個任務初始化一個CThreadNormalAtkExcutor線程類。最終線程函數為CThreadNormalAtkExcutor::ProcessMain
,此函數會根據CSubTask.taskType的值初始化一個CPacketAttack的子類用于執行相應的攻擊,type值與攻擊類型的對應關系如下:
CSubTask.taskType | 子類 | 攻擊方式 |
---|---|---|
0x10、0x11(var_06=0) | CAttackSyn | SYN半連接 |
0x10、0x11(var_06=1) | CAttackCompress | 自定義IP、TCP頭 |
0x20 | CAttackUdp | UDP |
0x21、0x23、0x24 | CAttackDns | 隨機子域名攻擊 |
0x22 | CAttackAmp | DNS放大 |
0x25 | CAttackPrx | 某種DNS攻擊 |
0x30 | CAttackIcmp | ping |
0x40 | CTcpAttack | 任意TCP數據,發送攻擊者自定義的數據內容 |
0x41 | CAttackCc | CC |
0x42 | CAttackIe | 未實現,重新設置成0x41 |
CThreadNormalAtkExcutor::ProcessMain
根據配置調用Create成員構造特定類型所需的數據。
調用成員函數Do,Do調用MakePacket構造攻擊數據包,調用UpdateCurVariant修改數據包的一些屬性(如TCP順序號等),調用SendPacket發送數據包。Do函數被循環調用,直到預定數目的攻擊完成。
內核攻擊通過調用CThreadAtkCtrl::DoKernelSubTask
執行(type 0x43),
該函數最終調用CThreadAtkCtrl::StartKernelSubTask
,初始化CThreadKernelAtkExcutor。
最終執行線程為CThreadKernelAtkExcutor::ProcessMain
。
此函數fork當前進程,在每個CPU上執行函數CThreadKernelAtkExcutor::KCfgDev
,此函數發送命令rem_device_all
(移除所有設備)、add_device ethN
(添加網卡N)、max_before_softirq
(改變數據包內核中斷閾值)到pktgen設備,N為0、1、2等,指向網卡名稱。pktgen設備位于/proc/net/pktgen/kpktgend_X
,其中X為當前cpu號。病毒作者在這里犯了一個錯誤,kpktgend_X
中X指關聯到當前包產生器的cpu號,但病毒作者在這里用的是網卡號,這個錯誤導致病毒在生成數據包時只用到了一個cpu,無法充分利用多核多cpu的性能。完成pktgen設備的初始化后,CThreadKernelAtkExcutor::ProcessMain
調用CThreadKernelAtkExcutor::KCfgCfg
,此函數通過/proc/net/pktgen/ethN
配置包產生器。配置包含攻擊目標IP端口、發送攻擊數據包數目、包大小隨機范圍、數據包之間的等待時間、源IP隨機范圍、源端口隨機范圍等信息。設置完pktgen的參數后CThreadKernelAtkExcutor::ProcessMain
向/proc/net/pktgen/pgctrl
寫入start來啟動攻擊。
修改bot的控制服務器IP到本機并編寫簡單的控制端腳本,在虛擬機中進行tcp rst攻擊實驗:
在設置攻擊目標為192.168.122.1:9876,數據包大小范圍為128-500,線程數目為200,攻擊次數100并關閉Cpu負載均衡開關后得到的攻擊數據包如下:
可以看到單個bot在此次攻擊中共發送了21268252個攻擊數據包,數量驚人。
由于Cpu使用率限制選項設為關閉,bot最大化使用系統資源,雙核cpu達到192.4%的利用率。
通過此樣本可以發現黑產團隊的DDoS攻擊實力已經到了”比較嫻熟”的地步,而根據樣本中不同部分的不同代碼風格猜測黑產團隊可能存在多人多團隊合作的編程方式或“黑吃黑”的代碼盜用情況,也許。
IT基礎技術不斷發展的今天,追逐利益的黑產團隊依然在不懈的利用剛暴露出來的漏洞攻擊著那些疏忽的操作系統,威脅著用戶的數據安全。用戶愿意將他們的數據、過程實現、想法放到我們的云平臺,是因為他們相信我們能讓這些數據的隱私和安全得到有力的保證,360云安全團隊持續為您構建一個安全云。