OffensiveNim - 我将 Nim 武器化的实验(https://nim-lang.org/)

Created at: 2020-11-09 07:46:06
Language: Nim
License: BSD-2-Clause

进攻型尼姆

进攻型尼姆

我将Nim武器化以进行植入物开发和一般进攻行动的实验。

目录

为什么是尼姆?

  • 直接编译为 C、C++、Objective-C 和 Javascript。
  • 由于它不依赖于虚拟机/运行时,因此不会像其他语言(例如 Golang)那样产生我喜欢称之为“THICC 恶意软件”的东西
  • 受 Python 启发的语法,允许快速创建本地有效负载和原型。
  • 拥有极其成熟的FFI(Foreign Function Interface)能力。
  • 避免让你实际使用 C/C++ 编写,从而避免在你的软件中引入许多安全问题。
  • 从 *nix/MacOS 到 Windows 的超级简单交叉编译,只需要你安装
    mingw
    工具链并将单个标志传递给 nim 编译器。
  • Nim 编译器和生成的可执行文件支持所有主要平台,如 Windows、Linux、BSD 和 macOS。甚至可以编译到Nintendo Switch,IOS和Android。请参阅Nim 编译器使用指南中的交叉编译部分
  • 技术上讲,你可以在 Nim 中编写你的植入程序和 c2 后端,因为你可以将代码直接编译为 Javascript。甚至对 WebAssembly 的一些初步支持

此 repo 中有效的示例

文件 描述
pop_bin.nim 使用 Winim 库调用
MessageBox
WinApi
pop_winim_bin.nim 调用
MessageBox
该Winim libary
pop_winim_lib.nim 创建带有导出的 Windows DLL 的示例
DllMain
execute_assembly_bin.nim 承载 CLR,从内存中反射性地执行 .NET 程序集
clr_host_cpp_embed_bin.nim 通过直接嵌入 C++ 代码承载 CLR,从磁盘执行 .NET 程序集
scshell_c_embed_bin.nim 展示如何通过直接在 Nim 中嵌入SCShell (C)来快速武器化现有的 C 代码
fltmc_bin.nim 枚举所有 Minifilter 驱动程序
blockdlls_acg_ppid_spoof_bin.nim 创建一个挂起的进程,将其 PPID 欺骗到 explorer.exe,同时启用 BlockDLLs 和 ACG
named_pipe_client_bin.nim 命名管道客户端
named_pipe_server_bin.nim 命名管道服务器
embed_rsrc_bin.nim 在编译时嵌入资源(zip 文件)并在运行时提取内容
self_delete_bin.nim 一种删除磁盘上锁定或当前正在运行的可执行文件的方法。@jonasLyk发现的方法
encrypt_decrypt_bin.nim 使用Nimcrypto库的AES256(CTR 模式)加密/解密
amsi_patch_bin.nim 从当前进程中修补 AMSI
etw_patch_bin.nim 从当前进程中修补 ETW(由 提供)
wmiquery_bin.nim 使用 WMI 查询正在运行的进程和已安装的 AV
out_compressed_dll_bin.nim 压缩、Base-64 编码并输出 PowerShell 代码以在内存中加载托管 dll。将原始 PowerSploit 脚本移植到 Nim。
dynamic_shellcode_local_inject_bin.nim POC 在本地注入动态恢复的 shellcode,而不是将其硬编码到数组中。
shellcode_callback_bin.nim 使用回调函数执行 shellcode
shellcode_bin.nim 创建一个挂起的进程并用
VirtualAllocEx
/注入 shellcode
CreateRemoteThread
。还演示了使用编译时定义来检测 arch、os 等。
shellcode_inline_asm_bin.nim 使用内联汇编执行 shellcode
syscalls_bin.nim 显示如何进行直接系统调用
execute_powershell_bin.nim 托管 CLR 并通过非托管运行空间执行 PowerShell
passfilter_lib.nim 通过(ab)使用密码复杂性过滤器将密码更改记录到文件中
minidump_bin.nim 使用创建 lsass 的内存转储
MiniDumpWriteDump
http_request_bin.nim 演示了几种发出 HTTP 请求的方法
execute_sct_bin.nim
.sct
文件执行通过
GetObject()
scriptcontrol_bin.nim 使用
MSScriptControl
COM 对象动态执行 VBScript 和 JScript
excel_com_bin.nim 使用 Excel COM 对象和宏注入 shellcode
键盘记录器_bin.nim 键盘记录器使用
SetWindowsHookEx
memfd_python_interpreter_bin.nim 使用
memfd_create
syscall 将二进制文件加载到匿名文件中并使用
execve
syscall执行它。
uuid_exec_bin.nim 将 UUID 数组中的 shellcode 植入堆空间并使用
EnumSystemLocalesA
回调来执行 shellcode。

WIP 示例

文件 描述
amsi_patch_2_bin.nim 使用不同的方法从当前进程中修补 AMSI(WIP,感谢帮助
excel_4_com_bin.nim 使用 Excel COM 对象和 Excel 4 宏 ( WIP )注入 shellcode

编译此 repo 中的示例

这个存储库不提供二进制文件,你必须自己编译它们。

这个 repo 被设置为将示例 Nim 源文件从 *nix/MacOS 交叉编译到 Windows,但是它们应该可以直接在 Windows 上编译它们(不要认为你将能够使用编译它们的 Makefile tho一口气完成)。

使用你的系统包管理器安装 Nim(对于 windows使用官方网站上的安装程序

  • brew install nim
  • apt install nim
  • choco install nim

(Nim也提供了一个docker镜像,但是不知道交叉编译的时候是怎么工作的,需要研究一下)

你现在应该可以使用

nim
&
nimble
命令,前者是 Nim 编译器,后者是 Nim 的包管理器。

安装

Mingw
交叉编译到 Windows 所需的工具链(如果你在 Windows 上编译不需要):

  • *尼克斯:
    apt-get install mingw-w64
  • 苹果系统:
    brew install mingw-w64

最后,安装宏伟的Winim库,以及zippynimcrypto

  • nimble install winim zippy nimcrypto

然后 cd 进入此存储库的根目录并运行

make
.

You should find the binaries and dlls in the

bin/
directory

Cross Compiling

See the cross-compilation section in the Nim compiler usage guide, for a lot more details.

Cross compiling to Windows from MacOs/*nix requires the

mingw
toolchain, usually a matter of just
brew install mingw-w64
or
apt install mingw-w64
.

You then just have to pass the

-d=mingw
flag to the nim compiler.

E.g.

nim c -d=mingw --app=console --cpu=amd64 source.nim

Interfacing with C/C++

See the insane FFI section in the Nim manual.

If you're familiar with csharps P/Invoke it's essentially the same concept albeit a looks a tad bit uglier:

Calling

MessageBox
example

type
    HANDLE* = int
    HWND* = HANDLE
    UINT* = int32
    LPCSTR* = cstring

proc MessageBox*(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT): int32 
  {.discardable, stdcall, dynlib: "user32", importc: "MessageBoxA".}

MessageBox(0, "Hello, world !", "Nim is Powerful", 0)

For any complex Windows API calls use the Winim library, saves an insane amount of time and doesn't add too much to the executable size (see below) depending on how you import it.

Even has COM support!!!

Creating Windows DLLs with an exported
DllMain

Big thanks to the person who posted this on the Nim forum.

The Nim compiler tries to create a

DllMain
function for you automatically at compile time whenever you tell it to create a windows DLL, however, it doesn't actually export it for some reason. In order to have an exported
DllMain
you need to pass
--nomain
and define a
DllMain
function yourself with the appropriate pragmas (
stdcall, exportc, dynlib
).

你还需要

NimMain
从你的调用
DllMain
来初始化 Nim 的垃圾收集器。(非常重要,否则你的电脑会爆炸)。

例子:

import winim/lean

proc NimMain() {.cdecl, importc.}

proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} =
  NimMain()
  
  if fdwReason == DLL_PROCESS_ATTACH:
    MessageBox(0, "Hello, world !", "Nim is Powerful", 0)

  return true

编译:

nim c -d=mingw --app=lib --nomain --cpu=amd64 mynim.dll

优化可执行文件的大小

取自Nim 的常见问题解答页面

对于最大的尺寸减少使用以下标志

-d:danger -d:strip --opt:size

此外,我发现你可以通过传递

--passc=-flto --passl=-flto
给编译器来挤出更多字节。另请查看
Makefile
此 repo 中的 。

这些标志显减小了大小:当从 MacOSX 交叉编译时,shellcode 注入示例从 484.3 KB 变为 46.5 KB!

反射加载 Nim 可执行文件

非常感谢@Shitsecure 解决了这个问题!

默认情况下,Nim 不会生成带有重定位表的 PE,这是大多数反射加载 EXE 的工具所需要的。

要生成带有重定位部分的 Nim 可执行文件你需要向链接器传递一些额外的标志。

具体来说:

--passL:-Wl,--dynamicbase

完整示例命令:

nim c --passL:-Wl,--dynamicbase my_awesome_malwarez.nim

使用 Winim 库与不使用 Winim 库时的可执行文件大小差异

令人难以置信的是,尺寸差异几乎可以忽略不计。尤其是当你应用上述大小优化时。

这两个示例

pop_bin.nim
pop_winim_bin.nim
就是为此目的而创建的。

前者

MessageBox
手动定义WinAPI调用,后者使用Winim库(具体
winim/lean
只是核心SDK,看这里),结果:

byt3bl33d3r@ecl1ps3 OffensiveNim % ls -lah bin
-rwxr-xr-x  1 byt3bl33d3r  25K Nov 20 18:32 pop_bin_32.exe
-rwxr-xr-x  1 byt3bl33d3r  32K Nov 20 18:32 pop_bin_64.exe
-rwxr-xr-x  1 byt3bl33d3r  26K Nov 20 18:33 pop_winim_bin_32.exe
-rwxr-xr-x  1 byt3bl33d3r  34K Nov 20 18:32 pop_winim_bin_64.exe

如果你用

import winim/com
它导入整个 Winim 库,它只会增加大约 20 KB 左右,考虑到它抽象的功能量,100% 值得额外的大小:

byt3bl33d3r@ecl1ps3 OffensiveNim % ls -lah bin
-rwxr-xr-x  1 byt3bl33d3r  42K Nov 20 19:20 pop_winim_bin_32.exe
-rwxr-xr-x  1 byt3bl33d3r  53K Nov 20 19:20 pop_winim_bin_64.exe

操作安全注意事项

由于 Nim 如何

LoadLibrary
使用它的 FFI动态解析 DLL ,你的任何外部导入函数实际上都不会出现在可执行文件静态导入中(有关更多信息,请参阅此博客文章):

如果你将 Nim 源代码编译为 DLL,那么

NimMain
无论你是否指定自己的
DllMain
. 这可能被用作签名,不知道有多少商店在他们的开发堆栈中实际使用 Nim。绝对脱颖而出。

将 C 代码转换为 Nim

https://github.com/nim-lang/c2nim

用它翻译了一堆小的C代码片段,没试过什么大的。

语言桥梁

调试

将该

repr()
函数与
echo
,结合使用,支持几乎所有 (??) 数据类型,甚至结构体!

这篇博文了解更多

搭建开发环境

VSCode 有一个运行良好的 Nim 扩展。这似乎也是目前唯一的选择。

你可以按照以下步骤从 Visual Studio 中自动编译 Nim 代码:

  1. Code Runner
    作为扩展添加到你的 Visual Studio 代码,你可以通过浏览到扩展选项卡并搜索代码运行器来执行此操作: 代码运行器

  2. 安装 Code Runner 后,你可以通过按 (

    Ctrl+,
    在 Windows 或
    Ctrl+Shift+p
    Mac 上)在 Visual Studio 代码中配置它。你还可以浏览到设置菜单,如下所示:

    • 在 Windows/Linux 上文件 > 首选项 > 设置
    • 在 MacOS 代码 > 首选项 > 设置

进入设置窗口后,键入

code-runner.executor
执行人

从现在开始,你可以选择通过修改来改变NIM执行

executorMap
或者你可以改变
execution by Glob
。我个人建议修改 glob,一个例子如下: glob示例

此配置会将名称中包含 gui 的任何 nim 文件编译为 gui 应用程序,并将它们放在你的 nim 文件所在目录的已编译的 gui 文件夹中。 保存配置后,你现在可以按下播放按钮在 VSC 中,你的代码将自行编译: 按下播放按钮

它确实也会在正确的文件夹中。 guidir 中编译

我发现自己陷入的陷阱

  • 当使用 Winim 调用 winapi 并尝试传递空值时,请确保将

    NULL
    值(在 Winim 库中定义)作为假定的 Nim 内置
    nil
    值传递。(啊)

  • open()
    在 Windows 上调用后获取已创建文件的操作系统句柄,你需要调用
    f.getOsFileHandle()
    not
    f.getFileHandle()
    cause reason。

  • Nim 编译器确实接受形式

    -a=value
    --arg=value
    什至 tho中的参数,如果你查看它的用法,它仅将参数传递为
    -a:value
    or
    --arg:value
    。(对于 Makefile 很重要)

  • 定义字节数组时,还需要至少在第一个值中指明它是字节数组,有点奇怪但还可以(https://forum.nim-lang.org/t/4322

C#中的字节数组:

byte[] buf = new byte[5] {0xfc,0x48,0x81,0xe4,0xf0,0xff}

Nim 中的字节数组:

var buf: array[5, byte] = [byte 0xfc,0x48,0x81,0xe4,0xf0,0xff]

有趣的 Nim 库

Nim 用于植入开发链接

贡献者