[英]Executing rundll32.exe with CreateProcess
I've created a DLL and would like to execute one of the functions using the rundll32.exe command on windows. 我创建了一个DLL,并希望在Windows上使用rundll32.exe命令执行其中一个功能。
Using rundll32.exe, it runs correctly from the command line; 使用rundll32.exe,它可以从命令行正确运行; however, I'd like to call it (rundll32.exe) from a separate program.
但是,我想从一个单独的程序中调用它(rundll32.exe)。 I cannot directly call the function from my code due to 32/64 bit compatibility issues in the underlying libraries I'm using (Easyhook).
由于我正在使用的基础库(Easyhook)中存在32/64位兼容性问题,因此我无法直接从代码中调用该函数。
Below is what I'm using in an attempt to run the dll function: 下面是我在尝试运行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);
The output to my console is always DLL Launched
; 我的控制台的输出始终是
DLL Launched
; however, I do not see the effects of my DLL actually being called (currently stubbed out in such a way that the command writes to a file). 但是,我看不到实际调用DLL的效果(当前以命令写入文件的方式进行存根处理)。
If I swap out the application with something such as C:\\\\Windows\\\\system32\\\\notepad.exe
, the program successfully runs. 如果我用诸如
C:\\\\Windows\\\\system32\\\\notepad.exe
东西替换应用程序,则该程序将成功运行。
For completion, here's the body of MyFunc
: 为了完成,这是
MyFunc
的主体:
ofstream file;
file.open("C:\\Projects\\Test\\test.txt");
file << "I wrote to a file!";
file.close();
Is there any reason CreateProcess cannot be used with rundll32? 有什么原因不能将RunProcess32与CreateProcess一起使用? While reading over this I found several warnings about
LoadLibrary()
and DLLMain
but it doesn't seem like they're relevant to this. 在阅读此内容时,我发现了一些有关
LoadLibrary()
和DLLMain
警告,但似乎它们与此无关。
More Clarification: 更多说明:
This is currently a 32-bit application (allegedly) launching the 32-bit rundll32.exe
(Logic will be added later to call the 32 or 64 bit version). 当前,这是一个32位应用程序(据说)正在启动32位
rundll32.exe
(稍后将添加逻辑以调用32或64位版本)。
My dll is as follows: 我的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) { ... }
Which also has a .def
file with: 其中也有一个
.def
文件,其中包含:
EXPORTS
MyFunc
Running 运行
C:\Windows\system32\rundll32.exe C:\Projects\Test\mydll.dll,MyFunc
produces the expected results. 产生预期的结果。
Update 更新
Setting application
to NULL
and including the rundll32.exe
in cmd as mentioned in the comments seems to work. 如注释中所述,将
application
设置为NULL
并在cmd中包含rundll32.exe
似乎可行。
Relevant Docs: 相关文件:
CreateProcess CreateProcess的
RunDll32.exe RUNDLL32.EXE
Per the CreateProcess()
documentation: 根据
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.如果
lpApplicationName
和lpCommandLine
均为非NULL,则lpApplicationName
指向的以Null终止的字符串指定要执行的模块,而lpCommandLine
指向的以Null终止的字符串lpCommandLine
指定命令行。 The new process can useGetCommandLine
to retrieve the entire command line.新进程可以使用
GetCommandLine
检索整个命令行。 Console processes written in C can use theargc
andargv
arguments to parse the command line.用C编写的控制台进程可以使用
argc
和argv
参数来解析命令行。 Becauseargv[0]
is the module name, C programmers generally repeat the module name as the first token in the command line .由于
argv[0]
是模块名称,因此C程序员通常将模块名称作为命令行中的第一个标记重复 。
You are not repeating rundll32.exe
as the first command-line token. 您没有将
rundll32.exe
作为第一个命令行标记重复。
So, if you continue using the lpApplicationName
parameter, then change this: 因此,如果继续使用
lpApplicationName
参数,请更改此参数:
LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";
To this instead: 为此:
LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");
LPTSTR cmd = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
Note that you are currently compiling for ANSI/MBCS (by virtue of the fact that you are passing narrow strings to CreateProcess()
). 请注意,您当前正在针对ANSI / MBCS进行编译(因为您正在将狭窄的字符串传递给
CreateProcess()
)。 If you ever update the project to compile for Unicode, use this instead: 如果您曾经更新过项目以针对Unicode进行编译,请改用以下代码:
TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
This is because the documentation states: 这是因为文档指出:
lpCommandLine [in, out, optional]
lpCommandLine [输入,输出,可选]
......
The Unicode version of this function,CreateProcessW
, can modify the contents of this string.此函数的Unicode版本
CreateProcessW
可以修改此字符串的内容。 Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string).因此,该参数不能是指向只读存储器的指针 (例如const变量或文字字符串)。 If this parameter is a constant string, the function may cause an access violation.
如果此参数是常量字符串,则该函数可能会导致访问冲突。
You might consider changing cmd
into a TCHAR[]
array anyway, even in ANSI/MBCS, so you can do something like this: 您可能仍然考虑将
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"));
Either way, by passing the module filename as the first token in the lpCommandLine
parameter, you can then set the lpApplicationName
parameter to NULL: 无论哪种方式,都可以通过将模块文件名作为第一个令牌传递给
lpCommandLine
参数,然后将lpApplicationName
参数设置为NULL:
The
lpApplicationName
parameter can be NULL.lpApplicationName
参数可以为NULL。 In that case, the module name must be the first white space–delimited token in thelpCommandLine
string.在这种情况下,模块名称必须是
lpCommandLine
字符串中第一个由空格分隔的标记。
Let CreateProcess()
setup the correct command-line to pass to rundll32.exe
for you: 让
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.