C - 仅使用 ntdll 的堆栈分配

C - Stack allocation using only ntdll

是否有 API 调用或任何其他类似方式,仅使用 ntdll.dll 在堆栈上分配内存?

我知道 alloca() 会这样做,但我不能使用它,因为我只能使用 ntdll.dll 中的函数。

谢谢!

alloca 是部分内部函数,由编译器实现。但在内部它调用 _alloca_probe_16 (对于 x86)或 __chkstk(x64) 将保护页面向下移动到堆栈上。此函数的实现存在于 alloca16.objchkstk.obj 中,它们可以在 VC 子文件夹中找到(其中完全依赖于 VC 版本) - 您可以为 [=55 添加此对象=]处理甚至先将其转换为lib。同样在最新的 WDK 库中 - 存在 ntdllp.lib(不要与 ntdll.lib 混淆) - 它也包含所有实现需求(ntdll.dll 导出 _chkstk(对于 x86)和 __chkstk(对于 x64))


再次详细介绍:

当你在 src 代码中写入时

alloca(cb) CL x86 编译器生成

mov eax,cb
call _alloca_probe_16 ; do actual stack allocation and probe

在 x64 版本中

mov         ecx,eax 
add         rcx,0Fh 
cmp         rcx,rax 
ja          @@0
mov         rcx,0FFFFFFFFFFFFFF0h 
@@0:
and         rcx,0FFFFFFFFFFFFFFF0h 
mov         rax,rcx 
call        __chkstk ; probe only
sub         rsp,rax ; actual stack allocation

所以 _alloca_probe_16 and/or __chkstk 必须在某处实现,否则你会遇到 link 错误 - 无法解析的外部符号。

在最新的 WDK 版本中存在包含此实现的 ntdllp.lib(注意 p - 而不是 ntdll.lib)。在这种情况下,您的 PE 将从 ntdll.dll 导入 __chkstk_alloca_probe(此函数从 XP 导出的最小值 - 这两个函数指向相同的代码,只是别名)

另一个解决方案 - 在 VC 文件夹中可以找到 alloca16.objchkstk.obj - 你可以使用这个对象作为 link 输入(或合并 alloca16.obj + chkstk.obj 在单个 lib 文件中)。在这种情况下,您的 PE 将毫无意义。

您不需要依赖架构的东西,因为堆栈上的分配(通常)是独立于架构的。

如果你使用的是 C99,你有一个标准的方法,使用可变长度数组:https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

你会很简单地写这样的东西:

char mybuffer[my_size];

并且会分配到栈上

因为 alloca 操作堆栈指针,所以它不是 "real" 函数,而是 "compiler intrinsic"。如果将使用 alloca 的函数编译为汇编语言,您 应该 看到它被直接翻译成 sub esp, NNN 而不是 call alloca。 (除了 和 sub esp, NNN 之外,可能还调用了一个函数 。在这种情况下,您需要找出该函数的作用,它通常在哪里定义,并安排你的应用程序提供了一个替代品。你已经跳过了各种不寻常的箍,只使用 NTDLL,这只是一个。)

如果你看到call alloca而没有sub esp, NNN,这很可能意味着你的编译器只有[=10的假实现=] 那是 不是 给你从堆栈分配的内存,你根本不应该使用它。