我意识到这有点晚了大约 6 个月,但我正在尝试同样的事情并有一些额外的注意事项:
- 您可以取得所有权并
ole32.dll
从中删除HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
。这使您可以绕过 Windows 已锁定这些键的事实。
- 创建一个
SafeDllSearch
值为0
inHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager
的键应该会改变搜索路径。
应用了这两种技术并重新启动后,挂钩仍然不起作用。我更进一步,使用我们的一张救援 CD(基于 Windows PE 的环境)启动了一个 VM,并覆盖了system32
. 结果 Windows 无法启动 - 没有符号错误,但我从来没有达到LogonUI.exe
. 我的钩子函数可能被破坏了,所以这可能是原因。
无论如何,这产生了一种实际的、有形的钩子效果——尽管它尖叫着“坏掉了”!。不幸的是,它似乎很难调试,我可能会求助于另一种挂钩方法——即IAT 补丁。
编辑我执行的另一个实验是将 Dll 自己显式加载到目标进程的地址空间中。执行此操作的代码片段如下所示:
wchar_t* TargetPath = argv[1];
wchar_t DllPath[] = L"N:\\experiments\\ole32.dll";
STARTUPINFOW si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(STARTUPINFOW));
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
// create process suspended
BOOL bResult = CreateProcess(NULL, TargetPath, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi);
// write DLL name to remote process
void* RemoteAddr = VirtualAllocEx(pi.hProcess, NULL, sizeof(DllPath)+1,
MEM_RESERVE | MEM_COMMIT, PAGE_READONLY);
WriteProcessMemory(pi.hProcess, RemoteAddr, DllPath, sizeof(DllPath), &BytesWritten);
// get handle to LoadLibraryW
PTHREAD_START_ROUTINE pfLoadLibrary = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
// create remote thread calling LoadLibraryW
HANDLE hThread = CreateRemoteThread(pi.hProcess, NULL,
0, pfLoadLibrary, RemoteAddr, 0, NULL);
// start remote process
ResumeThread(pi.hThread);
为简洁起见,删除了错误处理。
ole32.dll
基本上,目标是在它有机会ole32.dll
从 system32加载之前强制将 my 加载到目标的地址空间中。就我而言,ole32.dll
稍后会在应用程序的加载例程中加载,所以理论上这应该有效。在实践中,它没有。我不确定为什么。
更新我的原始代码失败,因为 DLL 在运行时有未解析的符号警告。这种技术确实有效所以显然,它ole32.dll
从 system32 加载了我的和那个。为了确保库加载成功,我添加了LoadLibrary(DllPath)
对上面代码的调用。