|
Nell' articolo articolo41.htm abbiamo
visto come eseguire un programma con l' utenza SYSTEM. Abbiamo utilizzato
una dll che esporta una procedura la cui implementazione consiste appunto nell'
esecuzione dell' api CreateProcess. Tale dll viene caricata nello spazio
di memoria di winlogon.exe tramite una procedura che viene copiata
(assieme all' argomento in input) nello spazio di memoria di winlogon.exe
e, una volta lanciata tramite l' api CreateRemoteThread, carica la dll ed
invoca la procedura esportata dalla medesima passandogli come argomento il
programma (o più in generale la linea di comando) che vogliamo eseguire con l'
utenza SYSTEM. Bene .... con quell' esempio abbiamo visto come lanciare
un programma con l' utenza SYSTEM ed al tempo stesso abbiamo anche visto
come far eseguire ad un processo remoto una funzione esportata da una dll. Ora
però bisogna sottolineare che lo stesso obiettivo (lanciare un programma come SYSTEM)
può essere raggiunto anche senza bisogno di una dll esterna: eseguiremo il CreateProcess
direttamente nella procedura che verrà copiata e poi eseguita nel contesto del
processo remoto. Tale soluzione ci farà anche risparmiare abbastanza codice.
Una rassettata veloce del codice originale e si perviene al seguente listato in
cui viene ridefinita l' implementazione della procedura SystemProcess che
(analogamente all' articolo41.htm)
prende in input il nome di un programma (o anche una linea di comando) e lo
esegue nel contesto dell' utenza SYSTEM:
unit ProcessUtilities;
interface
uses
Windows, Sysutils, TlHelp32;
procedure SystemProcess(NomeProg: pChar);
implementation
type
TRemoteData = record
pCreateProcess: function (lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD;
lpEnvironment: Pointer; lpCurrentDirectory: PAnsiChar;
const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
pDesktop: pchar;
pProgName: pchar;
end;
PRemoteData = ^TRemoteData;
procedure ModificaPrivilegio(szPrivilege: pChar; fEnable: Boolean);
var
NewState: TTokenPrivileges;
luid: TLargeInteger;
hToken: THandle;
ReturnLength: DWord;
begin
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
hToken);
LookupPrivilegeValue(nil,
szPrivilege,
luid);
NewState.PrivilegeCount := 1;
NewState.Privileges[0].Luid := luid;
if fEnable then
NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
NewState.Privileges[0].Attributes := 0;
AdjustTokenPrivileges(
hToken,
FALSE,
NewState,
sizeof(NewState),
nil,
ReturnLength);
CloseHandle(hToken);
end;
function PidProcesso(NomeProcesso: string): LongWord;
var
pe: TProcessEntry32;
hSnap: THandle;
begin
hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe.dwSize := sizeof(TProcessEntry32);
//Prelevo informazioni sul primo processo nello snapshot di sistema
Process32First(hSnap, pe);
repeat //loop sui processi
Result := pe.th32ProcessID;
if (LowerCase(pe.szExeFile) = LowerCase(NomeProcesso)) then
begin
break;
end;
until (not (Process32Next(hSnap, pe)) ) ;
CloseHandle(hSnap);
end;
function InjectString(Process: LongWord; Text: pchar): pchar;
var
BytesWritten: dword;
begin
Result := VirtualAllocEx(Process,
nil,
Length(Text) + 1,
MEM_COMMIT or MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
WriteProcessMemory(Process, Result, Text, Length(Text) + 1, BytesWritten);
end;
function InjectDati(Process: LongWord; Dati: Pointer; Dimensione: dword): pointer;
var
BytesWritten: dword;
begin
Result := VirtualAllocEx(Process,
nil,
Dimensione,
MEM_COMMIT or MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
WriteProcessMemory(Process, Result, Dati, Dimensione, BytesWritten);
end;
procedure RemoteThread(RemoteData: PRemoteData); stdcall;
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
with RemoteData^ do
begin
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.lpReserved := nil;
StartupInfo.lpDesktop := pDesktop;
StartupInfo.lpTitle := nil;
StartupInfo.dwX := 0;
StartupInfo.dwY := 0;
StartupInfo.dwXSize := 0;
StartupInfo.dwYSize := 0;
StartupInfo.dwXCountChars := 0;
StartupInfo.dwYCountChars := 0;
StartupInfo.dwFillAttribute := 0;
StartupInfo.dwFlags := 1;
StartupInfo.wShowWindow := 5;
StartupInfo.cbReserved2 := 0;
StartupInfo.lpReserved2 := nil;
StartupInfo.hStdInput := 0;
StartupInfo.hStdOutput := 0;
StartupInfo.hStdError := 0;
pCreateProcess(nil,
pProgName,
nil,
nil,
False,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
nil,
nil,
StartupInfo,
ProcessInfo);
end;
end;
procedure EndRemoteThread(); stdcall;
begin
end;
procedure SystemProcess(NomeProg: pChar);
var
PID: dword;
RemoteData: TRemoteData;
process, thread: THandle;
ptrInput, ptrProc: Pointer;
ThreadId: DWORD;
begin
ModificaPrivilegio('SeDebugPrivilege', TRUE);
PID := PidProcesso('winlogon.exe');
Process := OpenProcess(PROCESS_CREATE_THREAD +
PROCESS_QUERY_INFORMATION +
PROCESS_VM_OPERATION +
PROCESS_VM_WRITE +
PROCESS_VM_READ,
False,
PID
);
RemoteData.pProgName := InjectString(Process, NomeProg);
RemoteData.pDesktop := InjectString(Process, 'winsta0\default');
RemoteData.pCreateProcess := GetProcAddress(GetModuleHandle('kernel32'), 'CreateProcessA');
ptrInput := InjectDati(Process, @RemoteData, SizeOf(RemoteData));
ptrProc := InjectDati(Process, @RemoteThread, dword(@EndRemoteThread) - dword(@RemoteThread));
Thread := CreateRemoteThread(Process, nil, 0, ptrProc, ptrInput, 0, ThreadId);
VirtualFreeEx(Process, ptrInput, SizeOf(RemoteData), MEM_RELEASE);
VirtualFreeEx(Process, ptrProc, dword(@EndRemoteThread) - dword(@RemoteThread), MEM_RELEASE);
WaitForSingleObject(Thread, INFINITE);
CloseHandle(Thread);
end;
end.
sorgenti
|