我将Nim武器化以进行植入物开发和一般进攻行动的实验。
mingw工具链并将单个标志传递给 nim 编译器。
文件 | 描述 |
---|---|
pop_bin.nim | 不使用 Winim 库调用MessageBoxWinApi |
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 | 使用MSScriptControlCOM 对象动态执行 VBScript 和 JScript |
excel_com_bin.nim | 使用 Excel COM 对象和宏注入 shellcode |
键盘记录器_bin.nim | 键盘记录器使用 SetWindowsHookEx |
memfd_python_interpreter_bin.nim | 使用memfd_createsyscall 将二进制文件加载到匿名文件中并使用 execvesyscall执行它。 |
uuid_exec_bin.nim | 将 UUID 数组中的 shellcode 植入堆空间并使用EnumSystemLocalesA回调来执行 shellcode。 |
文件 | 描述 |
---|---|
amsi_patch_2_bin.nim | 使用不同的方法从当前进程中修补 AMSI(WIP,感谢帮助) |
excel_4_com_bin.nim | 使用 Excel COM 对象和 Excel 4 宏 ( WIP )注入 shellcode |
这个存储库不提供二进制文件,你必须自己编译它们。
这个 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库,以及zippy和nimcrypto
nimble install winim zippy nimcrypto
然后 cd 进入此存储库的根目录并运行
make.
You should find the binaries and dlls in the
bin/directory
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
mingwtoolchain, usually a matter of just
brew install mingw-w64or
apt install mingw-w64.
You then just have to pass the
-d=mingwflag to the nim compiler.
E.g.
nim c -d=mingw --app=console --cpu=amd64 source.nim
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
MessageBoxexample
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!!!
DllMain
Big thanks to the person who posted this on the Nim forum.
The Nim compiler tries to create a
DllMainfunction 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
DllMainyou need to pass
--nomainand define a
DllMainfunction 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
对于最大的尺寸减少使用以下标志
-d:danger -d:strip --opt:size
此外,我发现你可以通过传递
--passc=-flto --passl=-flto给编译器来挤出更多字节。另请查看
Makefile此 repo 中的 。
这些标志显着减小了大小:当从 MacOSX 交叉编译时,shellcode 注入示例从 484.3 KB 变为 46.5 KB!
非常感谢@Shitsecure 解决了这个问题!
默认情况下,Nim 不会生成带有重定位表的 PE,这是大多数反射加载 EXE 的工具所需要的。
要生成带有重定位部分的 Nim 可执行文件,你需要向链接器传递一些额外的标志。
具体来说:
--passL:-Wl,--dynamicbase
完整示例命令:
nim c --passL:-Wl,--dynamicbase my_awesome_malwarez.nim
令人难以置信的是,尺寸差异几乎可以忽略不计。尤其是当你应用上述大小优化时。
这两个示例
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。绝对脱颖而出。
https://github.com/nim-lang/c2nim
用它翻译了一堆小的C代码片段,没试过什么大的。
Python 集成https://github.com/yglukhov/nimpy
Jave VM 集成:https : //github.com/yglukhov/jnim
将该
repr()函数与
echo,结合使用,支持几乎所有 (??) 数据类型,甚至结构体!
VSCode 有一个运行良好的 Nim 扩展。这似乎也是目前唯一的选择。
你可以按照以下步骤从 Visual Studio 中自动编译 Nim 代码:
Code Runner作为扩展添加到你的 Visual Studio 代码,你可以通过浏览到扩展选项卡并搜索代码运行器来执行此操作:
安装 Code Runner 后,你可以通过按 (
Ctrl+,在 Windows 或
Ctrl+Shift+pMac 上)在 Visual Studio 代码中配置它。你还可以浏览到设置菜单,如下所示:
进入设置窗口后,键入
code-runner.executor
从现在开始,你可以选择通过修改来改变NIM执行
executorMap或者你可以改变
execution by Glob。我个人建议修改 glob,一个例子如下:
此配置会将名称中包含 gui 的任何 nim 文件编译为 gui 应用程序,并将它们放在你的 nim 文件所在目录的已编译的 gui 文件夹中。 保存配置后,你现在可以按下播放按钮在 VSC 中,你的代码将自行编译:
当使用 Winim 调用 winapi 并尝试传递空值时,请确保将
NULL值(在 Winim 库中定义)作为假定的 Nim 内置
nil值传递。(啊)
要
open()在 Windows 上调用后获取已创建文件的操作系统句柄,你需要调用
f.getOsFileHandle()not
f.getFileHandle()cause reason。
Nim 编译器确实接受形式
-a=value或
--arg=value什至 tho中的参数,如果你查看它的用法,它仅将参数传递为
-a:valueor
--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]