Win32 DLL 注入 - 需要帮助理解为什么注入的 LoadLibraryA 有时会失败并显示“访问被拒绝”。
为了我自己的教育,我一直在尝试编写一个进行 DLL 注入的 Windows 程序。我的程序是一个在 Windows 11 上运行的 x64 Visual C++ 应用程序。它通过使用 CreateRemoteThread 执行一小段 shell 代码,然后执行 LoadLibraryA 函数,将 DLL 注入到受害者中。我以这种方式执行此操作,因此如果 LoadLibraryA 函数失败,我可以使用 GetLastError 检索失败的原因。下面是该 shell 代码的 C++ 版本:
struct DllLoaderThreadParam
{
LoadLibraryA_t LoadLibraryA;
GetLastError_t GetLastError;
LPCSTR injectedDllPath;
HMODULE injectedDllH;
DWORD lastError;
};
DWORD DllLoaderThread(PVOID pParam)
{
DllLoaderThreadParam* p = (DllLoaderThreadParam*)pParam;
p->injectedDllH = p->LoadLibraryA(p->injectedDllPath);
if (!p->injectedDllH)
{
p->lastError = p->GetLastError();
}
return 0;
}
我的注入器在目标进程中为 DllLoaderThreadParam、DLL 路径名和 shell 代码分配内存;将必要的信息写入这些存储位置;然后调用CreateRemoteThread执行shell代码。这在大多数情况下都可以正常工作。但是,某些进程由于“访问被拒绝”失败而无法加载 DLL。考虑以下调试输出:
PID 31876 redirected output to C:\Temp\31876_stdout.txt
PID 31876 is attaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
PID 31876 set injection complete event
PID 31876 successfully attached DLL
Loaded injection DLL C:/Users/miked/Source/repos/InjectedDll/x64/Debug/InjectedDll.dll
Opened process 21180 for injection
Target Process Machine: 0, Host Process Machine: 0
Target Native Machine: 8664, Host Native Machine: 8664
Remote DLL loader thread 45620 created successfully!
Remote thread remote DLL loader thread terminated with exit code (0)
Remote ThreadMain thread 33604 created successfully!
Remote thread ThreadMain terminated with exit code (0)
PID 31876 is detaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
InjectDLL rtn: 0
Selected file: C:/Users/miked/Source/repos/InjectedDll/x64/Debug/InjectedDll.dll
PID 31876 is redirecting output to file C:\Temp\31876
PID 31876 redirected output to C:\Temp\31876_stdout.txt
PID 31876 is attaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
PID 31876 set injection complete event
PID 31876 successfully attached DLL
Loaded injection DLL C:/Users/miked/Source/repos/InjectedDll/x64/Debug/InjectedDll.dll
Opened process 25208 for injection
Target Process Machine: 0, Host Process Machine: 0
Target Native Machine: 8664, Host Native Machine: 8664
Remote DLL loader thread 49796 created successfully!
Remote thread remote DLL loader thread terminated with exit code (0)
**Remote DLL loader thread failed to load DLL, error: (5) - Access is denied.
PID 31876 is detaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
InjectDLL rtn: 1
这两个注入都是针对运行 msedge.exe 可执行文件的进程进行的。第一次注入进程 ID 21180 工作完美。我的注入器 shell 成功加载了 DLL,并且我的注入器程序随后也能够使用 CreateRemoteThread 从注入的 DLL 运行程序。
但是,我尝试注入另一个运行相同 msedge.exe 可执行文件的进程,但如您所见,我的 shell 加载程序在 LoadLibraryA 调用中失败,并出现错误 5 - 访问被拒绝。请注意,我提供了完全限定的 DLL 路径。我还确保(我相信)每个人都应该可以访问该组。我还使用 IsWow64Process2 确保目标进程运行与我的注入器进程相同的 64 位架构,您也可以在调试输出中看到其结果。
仅供参考,我最初使用经典的 DLL 注入方法,仅直接执行目标中的 LoadLibraryA 函数,但是因为我使用该方法看到了同样的问题,但不知道失败的原因是什么(因为返回来自线程的代码只是 LoadLibraryA 调用的结果)我决定执行额外的步骤,使用 shell 检索错误代码。
所以这让我难住了。我对 Windows 安全/权限主题不太熟悉,我进行了大量搜索以发现是否存在任何可能阻止 DLL 访问/加载的权限,但结果是空的。因此,我希望能得到任何关于为什么会发生这种情况的线索。谢谢!
I have been playing around with writing a windows program that does DLL injection for my own education. My program is an x64 Visual C++ application I am running on windows 11. It injects the DLL into its victim by using CreateRemoteThread to execute a small piece of shell code that then executes the LoadLibraryA function. I did this in this fashion so if the LoadLibraryA function fails, I can retrieve the reason for the failure by using GetLastError. Here is the C++ version of that shell code:
struct DllLoaderThreadParam
{
LoadLibraryA_t LoadLibraryA;
GetLastError_t GetLastError;
LPCSTR injectedDllPath;
HMODULE injectedDllH;
DWORD lastError;
};
DWORD DllLoaderThread(PVOID pParam)
{
DllLoaderThreadParam* p = (DllLoaderThreadParam*)pParam;
p->injectedDllH = p->LoadLibraryA(p->injectedDllPath);
if (!p->injectedDllH)
{
p->lastError = p->GetLastError();
}
return 0;
}
My injector allocates memory in the target process for the DllLoaderThreadParam, the DLL path name, and shell code; writes the necessary information to those memory locations; and then calls CreateRemoteThread to execute the shell code. This works fine for the most part. However, certain processes are unable to load the DLL for some unknown reason due to an "Access is denied" failure. Consider the following debug output:
PID 31876 redirected output to C:\Temp\31876_stdout.txt
PID 31876 is attaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
PID 31876 set injection complete event
PID 31876 successfully attached DLL
Loaded injection DLL C:/Users/miked/Source/repos/InjectedDll/x64/Debug/InjectedDll.dll
Opened process 21180 for injection
Target Process Machine: 0, Host Process Machine: 0
Target Native Machine: 8664, Host Native Machine: 8664
Remote DLL loader thread 45620 created successfully!
Remote thread remote DLL loader thread terminated with exit code (0)
Remote ThreadMain thread 33604 created successfully!
Remote thread ThreadMain terminated with exit code (0)
PID 31876 is detaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
InjectDLL rtn: 0
Selected file: C:/Users/miked/Source/repos/InjectedDll/x64/Debug/InjectedDll.dll
PID 31876 is redirecting output to file C:\Temp\31876
PID 31876 redirected output to C:\Temp\31876_stdout.txt
PID 31876 is attaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
PID 31876 set injection complete event
PID 31876 successfully attached DLL
Loaded injection DLL C:/Users/miked/Source/repos/InjectedDll/x64/Debug/InjectedDll.dll
Opened process 25208 for injection
Target Process Machine: 0, Host Process Machine: 0
Target Native Machine: 8664, Host Native Machine: 8664
Remote DLL loader thread 49796 created successfully!
Remote thread remote DLL loader thread terminated with exit code (0)
**Remote DLL loader thread failed to load DLL, error: (5) - Access is denied.
PID 31876 is detaching DLL C:\Users\miked\Source\repos\InjectedDll\x64\Debug\InjectedDll.dll
InjectDLL rtn: 1
Both of these injections were made to processes running the msedge.exe executable. the first injection into process id 21180 worked flawlessly. My injector shell successfully loaded the DLL, and my injector program was subsequently able to run a program from that injected DLL also using CreateRemoteThread.
However, I tried to inject into another process running the same msedge.exe executable, but as you can see, my shell loader failed at the LoadLibraryA call with error 5 - Access is denied. Notice that I provide a fully qualified DLL path. I have also ensured (I believe) that the group Everyone should have access to it. I also use IsWow64Process2 to ensure the target process is running the same 64 bit architecture as my injector process, the results of which you can also see in the debug output.
FYI, I originally was using the classic DLL injection approach by directly executing only the LoadLibraryA function in the target, but because I was seeing this same issue using that approach, but couldn't know what the reason for the failure was (since the return code from the thread was the result of the LoadLibraryA call only) I decided to go the extra step of using the shell to retrieve the error code.
So this has me stumped. I am only marginally familiar with Windows security/privilege topics, and I did a ton of searching to discover if any privileges might prevent DLL access/loading exist, but came up empty. So I'd appreciate any clues as to why this might be happening. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
众所周知,Edge 以沙盒模式运行,以保护您的电脑免受网站侵害。看来沙箱保护是双向的。
您提到“组每个人”,但这只是基于角色的访问控制。沙箱旨在保护您的文件免受浏览器的侵害;用户帐户在那里并不重要。
Edge is known to run in a sandbox mode, to protect your PC from websites. It appears the sandbox protection works both ways.
You mention "group Everyone", but that's just Role-Based Access Control. Sandboxing is intended to protect your files from your browser; user accounts do not matter there.