使用 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
之类的东西替换应用程序,程序会成功 运行s。
为了完成,这里是 MyFunc
的正文:
ofstream file;
file.open("C:\Projects\Test\test.txt");
file << "I wrote to a file!";
file.close();
CreateProcess 不能与 运行dll32 一起使用有什么原因吗?在阅读这篇文章时,我发现了一些关于 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()
文档:
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, ...);
我已经创建了一个 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
之类的东西替换应用程序,程序会成功 运行s。
为了完成,这里是 MyFunc
的正文:
ofstream file;
file.open("C:\Projects\Test\test.txt");
file << "I wrote to a file!";
file.close();
CreateProcess 不能与 运行dll32 一起使用有什么原因吗?在阅读这篇文章时,我发现了一些关于 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()
文档:
If both
lpApplicationName
andlpCommandLine
are non-NULL, the null-terminated string pointed to bylpApplicationName
specifies the module to execute, and the null-terminated string pointed to bylpCommandLine
specifies the command line. The new process can useGetCommandLine
to retrieve the entire command line. Console processes written in C can use theargc
andargv
arguments to parse the command line. Becauseargv[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 thelpCommandLine
string.
让 CreateProcess()
为您设置正确的命令行以传递给 rundll32.exe
:
TCHAR cmd[] = TEXT("C:\Windows\system32\rundll32.exe C:\Projects\Test\mydll.dll,MyFunc");
BOOL cpRes = CreateProcess(NULL, cmd, ...);