Skip to content

Instantly share code, notes, and snippets.

@rbmm
Created August 3, 2024 00:08
Show Gist options
  • Save rbmm/4115931d728b23aa8c6adaf1b76863b3 to your computer and use it in GitHub Desktop.
Save rbmm/4115931d728b23aa8c6adaf1b76863b3 to your computer and use it in GitHub Desktop.
HRESULT GetLastErrorEx(ULONG dwError = GetLastError())
{
NTSTATUS status = RtlGetLastNtStatus();
return dwError == RtlNtStatusToDosErrorNoTeb(status) ? HRESULT_FROM_NT(status) : HRESULT_FROM_WIN32(dwError);
}
NTSTATUS GetLogonSid(_In_ ULONG SessionId, _Out_ PSID_AND_ATTRIBUTES LogonSid)
{
HANDLE hToken;
if (WTSQueryUserToken(SessionId, &hToken))
{
NTSTATUS status;
union {
PVOID buf;
PTOKEN_GROUPS ptg;
};
PVOID stack = alloca(guz);
ULONG cb = 0, rcb = 0x100;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
status = NtQueryInformationToken(hToken, TokenGroups, buf, cb, &rcb);
} while (STATUS_BUFFER_TOO_SMALL == status);
NtClose(hToken);
if (0 > status)
{
return status;
}
if (ULONG GroupCount = ptg->GroupCount)
{
PSID_AND_ATTRIBUTES Groups = ptg->Groups;
do
{
if (Groups->Attributes & SE_GROUP_LOGON_ID)
{
PSID Sid = Groups->Sid;
if (SECURITY_LOGON_IDS_RID_COUNT == *RtlSubAuthorityCountSid(Sid) &&
SECURITY_LOGON_IDS_RID == *RtlSubAuthoritySid(Sid, 0))
{
LogonSid->Attributes = Groups->Attributes;
return RtlCopySid(SECURITY_SID_SIZE(SECURITY_LOGON_IDS_RID_COUNT), LogonSid->Sid, Sid);
}
}
} while (Groups++,--GroupCount);
}
return STATUS_NO_SUCH_GROUP;
}
return GetLastErrorEx();
}
NTSTATUS GetUserToken(_Out_ HANDLE* phToken, _In_ PCWSTR LogonDomainName, _In_ PCWSTR UserName, _In_ PCWSTR Password)
{
LONG SessionId = WTSGetActiveConsoleSessionId();
if (0 >= SessionId)
{
return STATUS_NO_SUCH_LOGON_SESSION;
}
NTSTATUS status;
UCHAR Sid[SECURITY_SID_SIZE(SECURITY_LOGON_IDS_RID_COUNT)];
TOKEN_GROUPS LocalGroups = { 1, { Sid } };
if (0 <= (status = GetLogonSid(SessionId, LocalGroups.Groups)))
{
LSA_STRING PackageName;
HANDLE LsaHandle;
if (0 <= (status = LsaConnectUntrusted(&LsaHandle)))
{
ULONG AuthenticationInformationLength = 0;
PKERB_INTERACTIVE_LOGON pkil = 0;
union {
PWSTR buf = 0;
PVOID pv;
PBYTE pb;
};
int len = 0;
status = STATUS_INTERNAL_ERROR;
while (0 < (len = _snwprintf(buf, len, L"%s%c%s%c%s", LogonDomainName, 0, UserName, 0, Password)))
{
if (buf)
{
pkil->MessageType = KerbInteractiveLogon;
RtlInitUnicodeString(&pkil->LogonDomainName, buf);
pb += pkil->LogonDomainName.Length + sizeof(WCHAR);
RtlInitUnicodeString(&pkil->UserName, buf);
pb += pkil->UserName.Length + sizeof(WCHAR);
RtlInitUnicodeString(&pkil->Password, buf);
pb += pkil->Password.Length + sizeof(WCHAR);
(ULONG_PTR&)pkil->LogonDomainName.Buffer -= (ULONG_PTR)pkil;
(ULONG_PTR&)pkil->UserName.Buffer -= (ULONG_PTR)pkil;
(ULONG_PTR&)pkil->Password.Buffer -= (ULONG_PTR)pkil;
status = STATUS_SUCCESS;
break;
}
pkil = (PKERB_INTERACTIVE_LOGON)alloca(
AuthenticationInformationLength = sizeof(KERB_INTERACTIVE_LOGON) + ++len * sizeof(WCHAR));
pv = pkil + 1;
}
ULONG AuthenticationPackage;
RtlInitString(&PackageName, NEGOSSP_NAME_A);
if (0 <= status &&
0 <= (status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage)))
{
RtlInitString(&PackageName, "OriginName");
TOKEN_SOURCE ts = {"1234567", {0x12345678, 0x90abcdef }};
void* ProfileBuffer;
ULONG ProfileBufferLength;
LUID LogonId;
QUOTA_LIMITS ql;
NTSTATUS subStatus;
HANDLE hToken;
if (0 <= (status = LsaLogonUser(LsaHandle, &PackageName, Interactive, AuthenticationPackage,
pkil, AuthenticationInformationLength, &LocalGroups, &ts,
&ProfileBuffer, &ProfileBufferLength, &LogonId, &hToken, &ql, &subStatus)))
{
LsaFreeReturnBuffer(ProfileBuffer);
TOKEN_LINKED_TOKEN hLinkToken;
switch (status = NtQueryInformationToken(hToken, TokenLinkedToken, &hLinkToken, sizeof(hLinkToken), &ProfileBufferLength))
{
case STATUS_SUCCESS:
NtClose(hToken);
hToken = hLinkToken.LinkedToken;
case STATUS_NO_SUCH_LOGON_SESSION:
status = NtSetInformationToken(hToken, TokenSessionId, &SessionId, sizeof(SessionId));
break;
}
if (0 > status)
{
NtClose(hToken);
}
else
{
*phToken = hToken;
}
}
else
{
if (0 > subStatus)
{
status = subStatus;
}
}
}
LsaDeregisterLogonProcess(LsaHandle);
}
}
return status;
}
NTSTATUS StartProcessAsUser(_In_ PCWSTR LogonDomainName,
_In_ PCWSTR UserName,
_In_ PCWSTR Password,
_In_ PCWSTR lpApplicationName,
_Inout_opt_ PWSTR lpCommandLine = 0)
{
HANDLE hToken;
NTSTATUS status = GetUserToken(&hToken, LogonDomainName, UserName, Password);
if (0 <= status)
{
PROCESS_INFORMATION pi;
STARTUPINFOW si = { sizeof(si) };
si.lpDesktop = const_cast<PWSTR>(L"Winsta0\\Default");
if (CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, 0, 0, 0, 0, 0, 0, &si, &pi))
{
NtClose(pi.hThread);
NtClose(pi.hProcess);
}
NtClose(hToken);
return GetLastErrorEx();
}
return status;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment