c++ - 使用 CreateProcess 执行 rundll32.exe

标签 c++ windows dll createprocess rundll32

我已经创建了一个 DLL,并想在 Windows 上使用 rundll32.exe 命令执行其中一个功能。

使用rundll32.exe,从命令行正确运行;但是,我想从一个单独的程序中调用它 (rundll32.exe)。由于我正在使用的底层库 (Easyhook) 中存在 32/64 位兼容性问题,我无法直接从我的代码中调用该函数。

下面是我在尝试运行 dll 函数时使用的内容:

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi));

LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";

BOOL cpRes = CreateProcess(application,
  cmd,
  NULL,
  NULL,
  FALSE,
  0,
  NULL,
  NULL,
  &si,
  &pi);

if(cpRes == 0) {
  cout << "ERROR\n";
  cout << GetLastError() << endl;
} else {
  cout << "DLL Launched!" << endl;
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

我控制台的输出总是DLL Launched;但是,我没有看到实际调用我的 DLL 的效果(当前以命令写入文件的方式 stub )。

如果我用诸如 C:\\Windows\\system32\\notepad.exe 之类的东西替换应用程序,程序会成功运行。

为了完成,这里是 MyFunc 的主体:

ofstream file;
file.open("C:\\Projects\\Test\\test.txt");
file << "I wrote to a file!";
file.close();

有什么理由不能将 CreateProcess 与 rundll32 一起使用?在阅读本文时,我发现了一些关于 LoadLibrary()DLLMain 的警告,但它们似乎与此无关。


更多说明:
目前这是一个 32 位应用程序(据称)启动 32 位 rundll32.exe(稍后将添加调用 32 位或 64 位版本的逻辑)。

我的dll如下:

extern "C" __declspec(dllexport) void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { ... }

它还有一个 .def 文件:

EXPORTS
  MyFunc

运行

C:\Windows\system32\rundll32.exe C:\Projects\Test\mydll.dll,MyFunc 

产生预期的结果。


更新
application 设置为 NULL 并将 rundll32.exe 包含在评论中提到的 cmd 中似乎有效。

相关文档:
CreateProcess
RunDll32.exe

最佳答案

根据 CreateProcess()文档:

If both lpApplicationName and lpCommandLine are non-NULL, the null-terminated string pointed to by lpApplicationName specifies the module to execute, and the null-terminated string pointed to by lpCommandLine specifies the command line. The new process can use GetCommandLine to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.

您没有将 rundll32.exe 重复为第一个命令行标记。

因此,如果您继续使用 lpApplicationName 参数,则更改为:

LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";

改为:

LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");
LPTSTR cmd = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");

请注意,您目前正在为 ANSI/MBCS 进行编译(由于您将窄字符串传递给 CreateProcess())。如果您曾经更新项目以针对 Unicode 进行编译,请改用它:

TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");

这是因为文档指出:

lpCommandLine [in, out, optional]
...
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.

无论如何,您可能会考虑将 cmd 更改为 TCHAR[] 数组,即使在 ANSI/MBCS 中也是如此,因此您可以这样做:

LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");

TCHAR cmd[(MAX_PATH*2)+10];
wsprintf(cmd, TEXT("%s %s,%s"), application, TEXT("C:\\Projects\\Test\\mydll.dll"), TEXT("MyFunc"));

无论哪种方式,通过将模块文件名作为第一个标记传递到 lpCommandLine 参数中,然后您可以将 lpApplicationName 参数设置为 NULL:

The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space–delimited token in the lpCommandLine string.

CreateProcess() 为您设置正确的命令行以传递给 rundll32.exe:

TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");

BOOL cpRes = CreateProcess(NULL, cmd, ...);

关于c++ - 使用 CreateProcess 执行 rundll32.exe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46434605/

相关文章:

c# - C# 运行时导入失败中的 C++ 非托管 DLL

c# - 为什么.net项目有时会使用旧版本的dll?

c++ - 防止连接到插槽 ("Really"专用插槽)

c++ - 尝试打印时堆损坏

c++ - 如何将 ""替换为 "_"?

c++ - 安装 VS 2019 后 CMake 找不到 VS 2017 C++ 编译器

windows - QueryUnbiasedInterruptTime 是单调的吗?

c++ - boost 日志 1.62 : filter condition must be in parentheses?

java - 没有 java 就无法运行 izpack 安装程序

c# - 无法访问放置在 wpf 应用程序中另一个程序集中的资源(图像)