繁体   English   中英

使用CreateProcess执行rundll32.exe

[英]Executing rundll32.exe with CreateProcess

我创建了一个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的效果(当前以命令写入文件的方式进行存根处理)。

如果我用诸如C:\\\\Windows\\\\system32\\\\notepad.exe东西替换应用程序,则该程序将成功运行。

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

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

有什么原因不能将RunProcess32与CreateProcess一起使用? 在阅读此内容时,我发现了一些有关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并在cmd中包含rundll32.exe似乎可行。

相关文件:
CreateProcess的
RUNDLL32.EXE

根据CreateProcess()文档:

如果lpApplicationNamelpCommandLine均为非NULL,则lpApplicationName指向的以Null终止的字符串指定要执行的模块,而lpCommandLine指向的以Null终止的字符串lpCommandLine指定命令行。 新进程可以使用GetCommandLine检索整个命令行。 用C编写的控制台进程可以使用argcargv参数来解析命令行。 由于argv[0]是模块名称,因此C程序员通常将模块名称作为命令行中的第一个标记重复

您没有将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 [输入,输出,可选]
...
此函数的Unicode版本CreateProcessW可以修改此字符串的内容。 因此,该参数不能是指向只读存储器的指针 (例如const变量或文字字符串)。 如果此参数是常量字符串,则该函数可能会导致访问冲突。

您可能仍然考虑将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:

lpApplicationName参数可以为NULL。 在这种情况下,模块名称必须是lpCommandLine字符串中第一个由空格分隔的标记。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM