什么情况下可以使用rundll32调用DLL中的函数?

Ben*_*n N 6 windows rundll32.exe

我想从命令行调用各种 Windows DLL 中的功能。看起来该rundll32实用程序将执行我需要的操作 - 它需要一个 DLL 名称和一个函数名称,并使用参数运行该函数。

我当然希望这不会有任何问题。我可以使用哪些功能rundll32

Ben*_*n N 6

几乎肯定会出现问题。

我可以使用哪些功能rundll32

好吧,最理想的是,您根本不会使用它——它已被弃用

Rundll32 是 Windows 95 的遗留物,至少自 Windows Vista 以来它已被弃用,因为它违反了许多现代工程指南。如果您通过 Rundll32 运行某些东西,那么您将失去为正在运行的东西定制执行环境的能力。

rundll32仅设计用于调用非常特定类型的函数,特别是创建窗口和处理窗口消息的函数。界面上的这份 Microsoft 文档rundll32解释了您正在调用的函数必须采用HWND、 a HINSTANCE、 aLPSTR和 an int(按该顺序),并且必须使用_stdcall/CALLBACK调用约定。

请查阅有关您要调用的函数的 MSDN 文档,以查看它是否具有该签名。例如,ExitWindowsEx不适合。事实上,我找不到具有该签名的单个函数。

如果您不确定所有这些意味着什么,您可以跳过下一部分并继续最后一部分。

如果我在其他功能上使用它会出现什么问题?

还记得整个函数签名吗?rundll32假设您尝试调用的函数具有正确的签名,无论实际情况是否如此。如果它的假设是错误的,那么与堆栈相关的非常奇怪的东西就会继续发生。(堆栈是存储函数之间传递的参数的内存位置。)

不匹配的函数签名将导致提供的数据rundll32被解释为不同的东西,因为函数期望其参数在堆栈中的位置。第一个数据rundll32提供的是一个窗口句柄,它以不确定的方式分配。因此,如果您误用rundll32您实际上是在将随机数据作为第一个参数传递。进一步阅读:当调用约定不匹配时会出现什么问题?

其余的参数并没有变得更好。即使您通过 向函数提供命令行rundll32,它也不会被解析为适合该函数的数据类型。相反,rundll32只需获取整个“额外”文本,将其塞入一个字符串变量中,然后将指向该数据的指针作为后面的参数传递给函数。由函数来解析文本。因此,永远不可能使用用户提供的参数调用任意函数rundll32

如果目标函数不需要参数,这并不是一场彻底的灾难,但您仍然在搞乱堆栈。有代码rundll32可以解决这个问题,但这并不能给你一个继续滥用它的借口。

如果您正在使用rundll32旨在以这种方式使用的第三方 DLL 中调用兼容函数,您仍然可能会遇到问题。rundll32始终选择使用所有新的 Windows 功能(例如数据执行保护),这可能会引入第三方代码不适合的更改;这就是行为是选择加入的原因。

幸运的是,有一种更好的方法可以做你想做的事。

我可以做什么?

试图锁定工作站 ( user32.dll,LockWorkStation)?就跑tsdiscon

试图关闭系统 ( user32.dll,ExitWindowsEx)?使用shutdown带有适当标志的实用程序 - 请参阅shutdown /?以获取帮助。

您是应用程序开发人员,并试图在不编写新 EXE 的情况下调用您的 DLL 函数吗?写那个 EXE,可能是用 C++。

尝试运行其他东西?我的开源实用程序SprintDLL支持用户指定的参数列表、多个调用约定和脚本以处理多个函数及其输出。如果您更喜欢仅使用 Windows 包含的工具,则可以使用 PowerShell执行P/Invoke


这个问题和答案是作为参考而编写的,可用于纠正建议rundll32以可疑方式使用的材料。如果您看到有人滥用rundll32,请给他们一个指向此页面的链接!