Custom Authentication Package - Winlogon.exe exception after successful logon
Hi,
I am developing credential provider with custom authentication package.
I have implemented LsaApLogonUserEx() as per msdn.
My AP function LsaApLogonUserEx() gets called during logon. CreateLogonsession() is successful but immediately winlogon crashes with below stack trace.
same question was asked in msdn forum before but solution is not mentioned. Below is the link https://social.msdn.microsoft.com/Forums/en-US/c66f24bf-deaa-4196-a97e-d8b7c64f3319/custom-authentication-package-winlogonexe-exception-after-successfull-logon?forum=windowsgeneraldevelopmentissues I am trying to find out what is causing this issue. Please let me know if you know the solution. Thanks, Hari
Windows API - Win32
C++
-
Viorel 114.7K Reputation points
2023-04-05T18:36:40.19+00:00 Maybe there are some issues or bad data in your code.
-
Jeanine Zhang-MSFT 9,431 Reputation points • Microsoft Vendor
2023-04-06T02:23:02.3266667+00:00 Could you please provide a sample code to help us reproduce the issue?
-
Hari 0 Reputation points
2023-04-07T11:55:46.04+00:00 @Viorel @Jeanine Zhang-MSFT I have placed LsaApLogonuserEx() code here. Please check where the code is wrong. I have hard coded usersid (sidhari) for testing purpose.
PUNICODE_STRING unialloc(PWCHAR src, USHORT len) { PUNICODE_STRING tgt; if (!(tgt = (PUNICODE_STRING)funcs->AllocateLsaHeap(sizeof(UNICODE_STRING)))) return NULL; tgt->Length = len * sizeof(WCHAR); tgt->MaximumLength = tgt->Length + sizeof(WCHAR); if (!(tgt->Buffer = (PWSTR)funcs->AllocateLsaHeap(tgt->MaximumLength))) { funcs->FreeLsaHeap(tgt); return NULL; } wcscpy(tgt->Buffer, src); return tgt; } NTSTATUS NTAPI LsaApLogonUserEx(PLSA_CLIENT_REQUEST request, SECURITY_LOGON_TYPE logon_type, PVOID auth, PVOID client_auth_base, ULONG auth_len, PVOID* profileBuffer, PULONG pbuf_len, PLUID logon_id, PNTSTATUS sub_stat, PLSA_TOKEN_INFORMATION_TYPE tok_type, PVOID* tok, PUNICODE_STRING* account, PUNICODE_STRING* authority, PUNICODE_STRING* machine) { DWORD checksum, i; PDWORD csp, csp_end; NTSTATUS stat; SECPKG_CLIENT_INFO clinf; /* Check if the caller has the SeTcbPrivilege, otherwise refuse service. */ stat = funcs->GetClientInfo(&clinf); if (stat != STATUS_SUCCESS) { writelog("getclientinfo failed"); return stat; } if (!clinf.HasTcbPrivilege) { writelog("notcbprivilege"); return STATUS_ACCESS_DENIED; } wchar_t uname[256] = L"hari"; if (account && !(*account = unialloc(uname, wcslen(uname)))) { return STATUS_NO_MEMORY; } wchar_t dname[256] = L"DESKTOP"; if (authority && !(*authority = unialloc(dname, wcslen(dname)))) { return STATUS_NO_MEMORY; } if (machine) { WCHAR mach[MAX_COMPUTERNAME_LENGTH + 1]; DWORD msize = MAX_COMPUTERNAME_LENGTH + 1; if (!GetComputerNameW(mach, &msize)) wcscpy(mach, L"UNKNOWN"); if (!(*machine = unialloc(mach, wcslen(mach)))) { return STATUS_NO_MEMORY; } } KERB_INTERACTIVE_PROFILE kip; kip.MessageType = KerbInteractiveProfile; kip.LogonCount = 0; kip.BadPasswordCount = 0; //last logon time kip.LogonTime.LowPart = u1.LowPart; kip.LogonTime.HighPart = u1.HighPart; kip.LogonScript.Length = 0; kip.LogonScript.Buffer = NULL; wchar_t homedir[256] = L"C:\\Users\\hari"; kip.HomeDirectory.Length = wcslen(homedir) * sizeof(WCHAR); kip.HomeDirectory.MaximumLength = kip.HomeDirectory.Length + sizeof(WCHAR); funcs->AllocateClientBuffer(request, kip.HomeDirectory.MaximumLength, (PVOID*)&(kip.HomeDirectory.Buffer)); funcs->CopyToClientBuffer(request, kip.HomeDirectory.Length, kip.HomeDirectory.Buffer, homedir); wchar_t username[256] = L"Hari"; kip.FullName.Length = wcslen(username) * sizeof(WCHAR); kip.FullName.MaximumLength = kip.FullName.Length + sizeof(WCHAR); funcs->AllocateClientBuffer(request, kip.FullName.MaximumLength, (PVOID*)&(kip.FullName.Buffer)); funcs->CopyToClientBuffer(request, kip.FullName.Length, kip.FullName.Buffer, username); kip.ProfilePath.Length = 0; kip.ProfilePath.Buffer = NULL; wchar_t drive[256] = L"C:"; kip.HomeDirectoryDrive.Length = wcslen(drive) * sizeof(WCHAR); kip.HomeDirectoryDrive.MaximumLength = kip.HomeDirectoryDrive.Length + sizeof(WCHAR); funcs->AllocateClientBuffer(request, kip.HomeDirectoryDrive.MaximumLength, (PVOID*)&(kip.HomeDirectoryDrive.Buffer)); funcs->CopyToClientBuffer(request, kip.HomeDirectoryDrive.Length, kip.HomeDirectoryDrive.Buffer, drive); wchar_t server[256] = L"DESKTOP"; kip.LogonServer.Length = wcslen(server) * sizeof(WCHAR); kip.LogonServer.MaximumLength = kip.LogonServer.Length + sizeof(WCHAR); funcs->AllocateClientBuffer(request, kip.LogonServer.MaximumLength, (PVOID*)&(kip.LogonServer.Buffer)); auto status = funcs->CopyToClientBuffer(request, kip.LogonServer.Length, kip.LogonServer.Buffer, server); kip.UserFlags = LOGON_RESOURCE_GROUPS; if (profileBuffer) { stat = funcs->AllocateClientBuffer(request, sizeof(KERB_INTERACTIVE_PROFILE), profileBuffer); if (!LSA_SUCCESS(stat)) { return stat; } } if (pbuf_len) *pbuf_len = sizeof(KERB_INTERACTIVE_PROFILE1); auto status2 = funcs->CopyToClientBuffer(request, sizeof(KERB_INTERACTIVE_PROFILE), *profileBuffer, (PVOID)&kip); char sidlocal[256] = "S-1-2-0"; PSID psidlocal; auto res = ConvertStringSidToSidA(sidlocal, &psidlocal); if (res); writelog("converted sidlocal"); auto sizelocalsid = GetLengthSid(psidlocal); char sidhari[256] = "S-1-5-21-3318738305-2660226224-2916278809-1004"; PSID psidhari; auto res1 = ConvertStringSidToSidA(sidhari, &psidhari); if (res1); writelog("converted sidlocal"); auto sizeharisid = GetLengthSid(psidhari); //S-1-5-32-544 administrator group char sidadmin[256] = "S-1-5-32-544"; PSID psidadmin; auto res2 = ConvertStringSidToSidA(sidadmin, &psidadmin); auto sizeadminsid = GetLengthSid(psidadmin); PLSA_TOKEN_INFORMATION_V2 tokinf; if (!(tokinf = (PLSA_TOKEN_INFORMATION_V2)funcs->AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V2) + sizelocalsid + sizeof(TOKEN_GROUPS) + /*sizeof(SID_AND_ATTRIBUTES) * (GroupCount - 1) */ +sizeadminsid + sizeharisid))) { return STATUS_NO_MEMORY; } PTOKEN_GROUPS grps; PBYTE tptr; tptr = (PBYTE)(tokinf + 1); //Expiration time SYSTEMTIME st; FILETIME ft; double seconds = 3600; GetLocalTime(&st); SystemTimeToFileTime(&st, &ft); ((ULARGE_INTEGER*)&ft)->QuadPart += (seconds * 10000000LLU); LARGE_INTEGER u; memcpy(&u, &ft, sizeof(u)); tokinf->ExpirationTime.LowPart = u.LowPart; tokinf->ExpirationTime.HighPart = u.HighPart; CopySid(sizelocalsid, (PSID)tptr, psidlocal); tokinf->User.User.Sid = (PSID)tptr; tptr += sizelocalsid; tokinf->User.User.Attributes = SE_GROUP_LOGON_ID; grps = (PTOKEN_GROUPS)tptr; tokinf->Groups = grps; grps->GroupCount = 1; tokinf->Groups->Groups[0].Attributes = SE_GROUP_LOGON_ID; tptr += sizeof(TOKEN_GROUPS); CopySid(sizeadminsid, (PSID)tptr, psidadmin); tokinf->Groups->Groups[0].Sid = (PSID)tptr; tptr += sizeadminsid; /////* Group SIDs */ ////for (i = 0; i < src_grps->GroupCount; ++i) ////{ //// src_sid = (PSID)(base + src_grps->Groups[i].Sid); //// size = GetLengthSid(src_sid); //// CopySid(size, (PSID)tptr, src_sid); //// tokinf->Groups->Groups[i].Sid = (PSID)tptr; //// tptr += size; //// tokinf->Groups->Groups[i].Attributes = src_grps->Groups[i].Attributes; ////} CopySid(sizeharisid, (PSID)tptr, psidhari); tokinf->PrimaryGroup.PrimaryGroup = (PSID)tptr; tptr += sizeharisid; tokinf->Privileges = NULL; tokinf->Owner.Owner = NULL; tokinf->DefaultDacl.DefaultDacl = NULL; *tok = (PVOID)tokinf; *tok_type = LsaTokenInformationV2; stat = funcs->CreateLogonSession(logon_id); if (stat != STATUS_SUCCESS) { funcs->FreeLsaHeap(*tok); *tok = NULL; return stat; } LocalFree(psidlocal); LocalFree(psidhari); LocalFree(psidadmin); return STATUS_SUCCESS; }
-
Jeanine Zhang-MSFT 9,431 Reputation points • Microsoft Vendor
2023-04-11T07:32:23.4933333+00:00 The authentication package is responsible for allocating the ProfileBuffer buffer within the client process by calling the AllocateClientBuffer function. The contents of this buffer are determined by the authentication package. As far as I'm concerned, you just need call
AllocateClientBuffer
andCopyToClientBuffer
only once time.
Sign in to comment