跟踪了一下函数逻辑,发现不同的UserInfo都有不同的处理方法,通常我们会传入一个USERINFO1结构体,这里会把有效信息传入到一个 USER_ALL_INFORMATION 结构体里面,这个结构体的实现和Startupinfo有点像,需要同时设置值和使用标签位,阅读发现,有一个结构体单处理密码。
#include "ApiAddUser.h"
int wmain(int argc, wchar_t* argv[])
{
UNICODE_STRING UserName;
UNICODE_STRING PassWord;
HANDLE ServerHandle = NULL;
HANDLE DomainHandle = NULL;
HANDLE UserHandle = NULL;
ULONG GrantedAccess;
ULONG RelativeId;
NTSTATUS Status = NULL;
HMODULE hSamlib = NULL;
HMODULE hNtdll = NULL;
HMODULE hNetapi32 = NULL;
LSA_HANDLE hPolicy = NULL;
LSA_OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
USER_ALL_INFORMATION uai = { 0 };
hSamlib = LoadLibraryA("samlib.dll");
hNtdll = LoadLibraryA("ntdll");
pSamConnect SamConnect = (pSamConnect)GetProcAddress(hSamlib, "SamConnect");
pSamOpenDomain SamOpenDomain = (pSamOpenDomain)GetProcAddress(hSamlib, "SamOpenDomain");
pSamCreateUser2InDomain SamCreateUser2InDomain = (pSamCreateUser2InDomain)GetProcAddress(hSamlib, "SamCreateUser2InDomain");
pSamSetInformationUser SamSetInformationUser = (pSamSetInformationUser)GetProcAddress(hSamlib, "SamSetInformationUser");
pSamQuerySecurityObject SamQuerySecurityObject = (pSamQuerySecurityObject)GetProcAddress(hSamlib, "SamQuerySecurityObject");
pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
RtlInitUnicodeString(&UserName, L"Admin");
RtlInitUnicodeString(&PassWord, L"Admin");
Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL);;
Status = LsaOpenPolicy(NULL,&ObjectAttributes,POLICY_VIEW_LOCAL_INFORMATION,&hPolicy);
Status = LsaQueryInformationPolicy(hPolicy, PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
Status = SamOpenDomain(ServerHandle,
DOMAIN_CREATE_USER | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
DomainInfo->DomainSid,
&DomainHandle);
Status = SamCreateUser2InDomain(DomainHandle,
&UserName,
USER_NORMAL_ACCOUNT,
USER_ALL_ACCESS | DELETE | WRITE_DAC,
&UserHandle,&GrantedAccess,&RelativeId);
RtlInitUnicodeString(&uai.NtPassword, PassWord.Buffer);
uai.NtPasswordPresent = TRUE;
uai.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
Status = SamSetInformationUser(UserHandle,
UserAllInformation,
&uai);
return 0;
}