2016-09-27 2 views
2

Я пытаюсь установить исполняемый файл для запуска как локального пользователя с низким уровнем привилегий (отличного от текущего зарегистрированного пользователя) по умолчанию. Эта команда Windows «runas/savecred/user: username appname.exe» может сделать это, но она требует, чтобы текущий зарегистрированный пользователь вручную вводил пароль другого пользователя в первый раз. В идеале я хочу, чтобы установщик программы установил учетные данные, поэтому для текущего входа в систему не требуется никакого взаимодействия. (Я не хочу, чтобы программа была как служба Windows по другим причинам.)C++: Как программно создать учетные данные локального пользователя в Windows Credential Manager, чтобы «runas/savecred» мог его использовать?

Когда я запустил команду «runas», я заметил, что новый новый «интерактивный вход в систему» ​​Windows Credential был создан в диспетчере учетных данных , где «Интернет или сетевой адрес» был установлен как «$ computer_name \ $ username (Interactive Logon)», «User name» был установлен как «$ computer_name \ $ username», «password» был отображен как «***** *** "и" Persistence "был установлен как« Предприятие ».

Основываясь на этом наблюдении, я нашел API Win32, CredWrite, но у меня возникли проблемы с его работой. Я получил код ошибки 87 (ERROR_INVALID_PARAMETER - параметр неверный.), Когда был вызван CredWrite.

#include <windows.h> 
#include <wincred.h> 
#include <tchar.h> 

void main() 
{ 
    char* password = "randompassword"; 
    DWORD blobsize= 1 + strlen(password); 

    CREDENTIAL cred = {0}; 
    cred.Flags = CRED_FLAGS_USERNAME_TARGET; 
    cred.Type = CRED_TYPE_DOMAIN_PASSWORD; 
    cred.TargetName = L"computername\\username"; 
    cred.CredentialBlobSize = blobsize; 
    cred.CredentialBlob = (LPBYTE) password; 
    cred.Persist = CRED_PERSIST_LOCAL_MACHINE; 
    cred.UserName = L"computername\\username"; 

    if (!CredWrite(&cred, 0)) 
    { 
     std::cerr << GetLastError() << std::endl; 
    } 
} 

Ссылки, которые я смотрел, перечислены внизу. Мне удалось создать учетную запись типа CRED_TYPE_GENERIC, но она не была распознана RUNAS. Я действительно озадачен тем, как устанавливать поля типа TargetName и Type, чтобы программно создавать учетные данные интерактивного входа в систему, как это делает RUNAS. Официальная документация MSDN не ясна и примеров нет.

CredWrite: https://msdn.microsoft.com/en-us/library/windows/desktop/aa375187(v=vs.85).aspx CREDENTIAL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx Пример кода для создания CRED_TYPE_GENERIC типа учетных данных: How do I store and retrieve credentials from the Windows Vault credential manager?

+0

см этот адрес http://stackoverflow.com/questions/3729406/create-local-user-account – Proxytype

+0

Спасибо за ответ, Proxytype.I не было проблем, чтобы создать локальную низкоприоритетную учетную запись в NetUserAdd. – Batistuta

+0

выглядит так: некоторые поля не могут быть изменены в существующих учетных данных. Эта ошибка возвращается, если поле не соответствует значению в защищенном поле существующих учетных данных. - вы не можете изменить параметр после создания пользователя, это значит, что вам нужно установить его при создании пользователя. https://msdn.microsoft.com/en-us/library/windows/desktop/aa375187(v= vs.85) .aspx – Proxytype

ответ

0

Ошибка ERROR_INVALID_PARAMETER (код ошибки 87) была вызвана неправильным значением CredentialBlobSize. «Если членом типа является CRED_TYPE_DOMAIN_PASSWORD, этот член содержит пароль Unicode открытого текста для UserName. Члены CredentialBlob и CredentialBlobSize не включают в себя конечный нулевой символ». (ПОЛНОМОЧИЙ: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx)

С этим исправлением учетные данные Windows (не общие или сертификатные сертификаты) могут быть созданы без ошибок.

#include <windows.h> 
#include <wincred.h> 
#include <tchar.h> 

void main() 
{ 
    char* password = "randompassword"; 
    DWORD blobsize= strlen(password); // Do NOT add 1 here. 

    CREDENTIAL cred = {0}; 
    cred.Flags = CRED_FLAGS_USERNAME_TARGET; 
    cred.Type = CRED_TYPE_DOMAIN_PASSWORD; 
    cred.TargetName = L"computername\\username"; 
    cred.CredentialBlobSize = blobsize; 
    cred.CredentialBlob = (LPBYTE) password; 
    cred.Persist = CRED_PERSIST_LOCAL_MACHINE; 
    cred.UserName = L"computername\\username"; 

    if (!CredWrite(&cred, 0)) 
    { 
     std::cerr << GetLastError() << std::endl; 
    } 
} 

Однако, есть еще тонкое различие. «Интернет или сетевой адрес» того, что я создал, «$ computer_name \ $ username (« Идентификатор Windows »), который не может быть распознан RUNAS. Созданный RUNAS был «$ computer_name \ $ username (Интерактивный вход в систему)». Как этот бит устанавливается?

Я могу использовать CredRead для чтения учетных данных, которые я создал, но не могу сделать это для созданного RUNAS.

CREDENTIAL cred = { 0 }; 
PCREDENTIAL pcred = &cred; 
// Works for Windows Identity. TargetName is case-insensitive. 
CredRead(L"$computer_name\$username", CRED_TYPE_DOMAIN_PASSWORD, 0, &pcred); 
// Fails for Interactive Logon with error code 87 or 1168. I tried all possible CRED_TYPE_*. 
CredRead(L"$computer_name\$username", CRED_TYPE_*, 0, &pcred); 

Похожие темы: 1. Runas команд, байпас Полномочия (https://community.spiceworks.com/topic/485852-runas-command-bypass-credentials) 2 .runas/savecred ... не принимаю cmdkey/добавить (учетные данные) (runas /savecred... don't accept cmdkey /add (credentials)) 3. RunAs с savecred переключателем/не принимает учетные данные, хранящиеся в команде cmdkey (https://social.technet.microsoft.com/Forums/windowsserver/en-US/c0e398cc-224f-4390-bc69-0ee544f9b5cb/runas-with-the-savecred-switch-does-not-accept-a-credential-stored-by-the-cmdkey-command?forum=winserversecurity)

Команда CMDKEY позволила мне создать учетную запись, ближайшую к той, которая была создана RUNAS.Оба выглядят одинаково в результате, возвращаемом «cmdkey/list». Однако, созданный CMDKEY, не соблюдается RUNAS.

cmdkey /add:Domain:interactive=$computer_name\$username1 /user:$computer_name\$username1 /pass:$password 

cmdkey /list 

# created by CMDKEY 
Target: Domain:interactive=$computer_name\$username1 
Type: Domain Password 
User: $computer_name\$username1 

# created by RUNAS 
Target: Domain:interactive=$computer_name\$username2 
Type: Domain Password 
User: $computer_name\$username2 
1

Существует недокументированный флаг CREDENTIAL структуры, которые вы передаете CredWrite.

При вызове API с флагом = 8196, вы получите результат вы хотите

char* password1 = "randompassword"; 
DWORD blobsize = strlen(password1); // Do NOT add 1 here. 

CREDENTIAL cred = { 0 }; 
cred.Flags = 8196; 
cred.Type = 2; 
cred.TargetName = L"computername\\username"; 
cred.CredentialBlobSize = blobsize; 
cred.CredentialBlob = (LPBYTE)password1; 
cred.Persist = 3; 
cred.UserName = L"computername\\username"; 

if (!CredWrite(&cred, 0)) 
{ 
    std::cerr << GetLastError() << std::endl; 
} 
Смежные вопросы