使用CreateProcess执行rundll32.exe

时间:2017-09-26 19:45:28

标签: 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实际被调用的效果(当前以命令写入文件的方式存根)。

如果我用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并在cmd中包含rundll32.exe似乎可行。

相关文件:
CreateProcess
RunDll32.exe

1 个答案:

答案 0 :(得分:1)

根据CreateProcess()文档:

  

如果lpApplicationNamelpCommandLine都是非NULL,则lpApplicationName指向的以null结尾的字符串指定要执行的模块,以及由{指向的以null结尾的字符串{1}}指定命令行。新进程可以使用lpCommandLine来检索整个命令行。用C编写的控制台进程可以使用GetCommandLineargc参数来解析命令行。 因为argv是模块名称,C程序员通常会重复模块名称作为命令行中的第一个标记

您不是要重复argv[0]作为第一个命令行令牌。

因此,如果您继续使用rundll32.exe参数,请更改此项:

lpApplicationName

改为:

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

请注意,您当前正在编译ANSI / MBCS(因为您将窄字符串传递给LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe"); LPTSTR cmd = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc"); )。如果您更新项目以编译Unicode,请改为使用:

CreateProcess()

这是因为文档声明:

  

lpCommandLine [in,out,optional]
  ...
  此函数的Unicode版本TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc"); 可以修改此字符串的内容。 因此,此参数不能是指向只读内存的指针(例如const变量或文字字符串)。如果此参数是常量字符串,则该函数可能会导致访问冲突。

您可以考虑将CreateProcessW更改为cmd数组,即使在ANSI / MBCS中,也可以这样做:

TCHAR[]

无论哪种方式,通过将模块文件名作为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参数设置为NULL:

  

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

lpCommandLine设置正确的命令行,为您传递给CreateProcess()

rundll32.exe