我创建了Credential Manager
DLL以利用NPLogonNotify
事件。我正在对Windows 7 Ultimate
进行完全修补的实例进行测试。凭证管理器DLL在强制更改密码时导致登录挂起
当用户登录我的NPLogonNotify
实现时,会产生一些使用CreateProcess
的进程。这些进程是Windows应用程序,一切正常。
当我强制用户在下次登录时更改密码时,他们更改密码,系统挂起“更改密码”。当用户更改密码时,在NPLoponNotify
内部创建新进程的某些操作不会很好。
我已验证它是NPLogonNotify
代码,通过注释该导出中的所有代码并测试强制密码更改。如果我将所有代码注释掉了,那么密码更改就完美了,代码会无限期地挂起。
下面是凭据管理器导出的函数
NPGetCaps
DWORD APIENTRY NPGetCaps(DWORD nIndex)
{
DWORD ret = 0;
switch (nIndex)
{
case WNNC_NET_TYPE:
ret = WNNC_CRED_MANAGER; // credential manager
break;
case WNNC_SPEC_VERSION:
// We are using version 5.1 of the spec.
ret = WNNC_SPEC_VERSION51;
break;
case WNNC_DRIVER_VERSION:
ret = 1; // This driver is version 1.
break;
case WNNC_START:
ret = 1; // We are already "started"
break;
}
return ret;
}
NPPasswordChangeNotify
DWORD APIENTRY NPPasswordChangeNotify(LPCWSTR lpAuthentInfoType, LPVOID lpAuthentInfo, LPCWSTR lpPreviousAuthentInfoType, LPVOID lpPreviousAuthentInfo, LPWSTR lpStationName, LPVOID StationHandle, DWORD dwChangeInfo)
{
return WN_SUCCESS;
}
注:以上功能对系统无影响H老化,我已经尝试完全没有出口,我仍然得到相同的结果。
NPLogonNotify
DWORD APIENTRY NPLogonNotify(PLUID lpLogon, LPCWSTR lpAuthentInfoType, LPVOID lpAuthentInfo, LPCWSTR lpPreviousAuthentInfoType, LPVOID lpPreviousAuthentInfo, LPWSTR lpStationName, LPVOID StationHandle, LPWSTR *lpLogonScript)
{
lpLogonScript = nullptr;
//auth type can help here to know what we're doing
if (lstrcmpi(lpAuthentInfoType, L"MSV1_0:Interactive") != 0 && lstrcmpiW(lpAuthentInfoType, L"Kerberos:Interactive"))
return WN_SUCCESS;
WCHAR filename[MAX_PATH];
GetModuleFileName(g_Module, filename, MAX_PATH);
wcsrchr(filename, L'\\')[0] = L'\0';
WCHAR exe1Filename[MAX_PATH];
wsprintf(exe1Filename, L"%lS\\exe1.exe", filename);
STARTUPINFOW si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(STARTUPINFO);
if (CreateProcess((LPWSTR)exe1Filename, nullptr, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi))
{
WaitForInputIdle(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
MSV1_0_INTERACTIVE_LOGON *authInfo = (MSV1_0_INTERACTIVE_LOGON *)lpAuthentInfo;
si = { 0 };
pi = { 0 };
si.cb = sizeof(STARTUPINFO);
((PWSTR)(&((char *)authInfo->UserName.Buffer)[authInfo->UserName.Length]))[0] = L'\0';
WCHAR args[(UNLEN + 14) * 2];
wsprintf(args, L"exe2.exe %lS", authInfo->UserName.Buffer);
WCHAR exe2Path[MAX_PATH];
wsprintf(exe2Path, L"%lS\\exe2.exe", filename);
if (CreateProcess((LPWSTR)exe2Path, (LPWSTR)args, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
return WN_SUCCESS;
}
我知道,上面的代码是非常糟糕的,没有错误检查,也不安全。我正在做这个测试和学习练习来了解更多关于Credential Managers的信息。
有谁知道为什么NPLogonNotify
内的代码在用户登录时可以完美工作,但是当用户在登录时被迫更改密码时会完全挂起系统?
挂在'WaitForInputIdle'或'WaitForSingleObject(pi.hProcess,INFINITE);'我只能评论这个和测试。如果真的挂在这里(当你不等待时不挂机) - 在你单独的进程中执行任务。我在之前(在当前winlogon桌面上)启动调试器并在其下查看 – RbMm
@RbMm好点,我将把它们拿出来看看。我认为它甚至没有达到这一点,因为屏幕上没有显示任何内容,但它可能正在显示,但是显示为其他内容或者没有正常显示,这会导致它出现冻结。我会用结果更新问题 – vane
您是否尝试过...调试? – conio