Executing rundll32.exe with CreateProcess

Executing rundll32.exe with CreateProcess

本文关键字:CreateProcess with exe rundll32 Executing      更新时间:2023-10-16

我已经创建了一个DLL,并且想使用Windows上的rundll32.exe命令执行其中一个函数。

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

以下是我在尝试运行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 << "ERRORn";
  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();

是否有任何理由与rundll32一起使用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:Windowssystem32rundll32.exe C:ProjectsTestmydll.dll,MyFunc 

产生预期的结果。


更新
application设置为NULL,并在评论中提到的CMD中包括rundll32.exe

相关文档:
CreateProcess
rundll32.exe

根据CreateProcess()文档:

如果lpApplicationNamelpCommandLine都是非空的,则lpApplicationName指向的null终止字符串指定要执行的模块,并且 lpCommandLine指向的null终止字符串指定命令行。新过程可以使用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 [IN,OUT,可选]
...
此功能的Unicode版本CreateProcessW可以修改此字符串的内容。因此,此参数不能是读取仅内存的指针(例如const变量或文字字符串)。如果此参数是恒定字符串,则该功能可能会导致访问违规。

即使在ANSI/MBC中,您也可以考虑将cmd更改为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参数中的第一个令牌,然后可以将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, ...);