2017-02-11 3 views
-1

Я создал Credential Manager DLL, чтобы воспользоваться событием NPLogonNotify. Я тестирую это на полностью исправленном экземпляре Windows 7 Ultimate.Учетная запись диспетчера учетных записей вызывает зависание входа в систему при форсировании смены пароля

Когда пользователь регистрируется в моей реализации 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; 
} 

ПРИМЕЧАНИЕ: данная функция не влияет на систему час я попытался полностью отказаться от экспорта, и я все равно получаю тот же результат.

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 отлично подходит для входа пользователя в систему, но полностью зависает системой, когда пользователь вынужден менять свой пароль при входе в систему?

+0

висит в 'WaitForInputIdle' или в' WaitForSingleObject (pi.hProcess, INFINITE); 'Я прокомментировал только это и тест. если вешать действительно здесь (не висели, когда вы не ждете) - задача в ваших отдельных процессах. Я запускаю отладчик раньше (на текущем рабочем столе winlogon) и просматриваю под ним – RbMm

+0

@RbMm Хорошая мысль, я возьму их и посмотрю. Я предполагал, что он даже не дошел до этого момента, поскольку на экране ничего не отображалось, но оно могло отображаться, но являлось чем-то другим или не отображалось нормально, что заставило бы его замерзнуть. Я обновлю вопрос с результатами – vane

+0

Вы пробовали ... отладки? – conio

ответ

1

Я все еще не понимаю, почему моя программа не отображается при смене пароля пользователя, но мне удалось выяснить, как ее исправить. Мне нужно было выяснить способ определения разницы между вызовом NPLogonNotify при входе в систему и вызовом его при изменении пароля.

Проблема с подвеской была связана с тем, что я вызывал WaitForSingleObject, чтобы дождаться завершения моей программы, прежде чем продолжить, чтобы программа работала, она была просто скрыта и не была неразрешимой по какой-либо причине во время смены пароля.

Там нет документации, что я мог бы найти, что четко не описывает разницу между вызовом при смене пароля и вызова при входе в систему, так что я был в состоянии проверить на код ниже:

if (lpPreviousAuthentInfoType != NULL || lpPreviousAuthentInfo != NULL || lstrcmpi(lpStationName, L"Winsta0") != 0) 
    return WN_SUCCESS; 

Это может быть чрезмерным и, вероятно, не соответствующим образом, но я не мог найти на нем никакой документации.В принципе, при изменении пароля lpPreviousAuthentInfoType будет заполняться строкой (в зависимости от типа аутентификации) и пустой строкой, если выполняется обычная логина. lpPreviousAuthentInfo будет содержать указатель на учетные данные предыдущего пользователя и NULL, если обычный вход в систему. Наконец, lpStationName будет Winsta0 на обычном входе и SvcCtl (если я правильно помню, я не записывал его) при смене пароля.

Смежные вопросы