Home | Chi sono | Contattami
 

Progr. lineare

Delphi
 
Componenti
  Database
 
Miei articoli

Windows

Miei articoli 

 

Eseguire un processo con l' utenza System
 

Nell' articolo articolo40.htm abbiamo visto come copiare una funzione ed il suo input nello spazio di memoria di una altro processo e quindi eseguire la funzione come thread del processo remoto grazie alla CreateRemoteThread. Bene ... la procedura che vado a copiare può ad esempio caricare una dll e richiamare una delle funzioni esportate da tale dll. Ok ... supponiamo ora che la dll che viene caricata esporti una procedura che esegue l' api CreateProcess: se la procedura copiata nello spazio di memoria del processo remoto carica la dll e poi chiama la procedura in questione (ossia la procedura esportata dalla dll e la cui implementazione consiste nella chiamata all' api CreateProcess) il processo creato dalla CreateProcess sarà un processo figlio del processo remoto. Dunnnqueeeee ... se il processo remoto fosse ad esempio winlogon.exe??? Behh allora il processo generato dalla CreateProcess sarà figlio di winlogon.exe e quindi verrà eseguito con l' utenza System. Bene abbiamo quindi trovato un modo per eseguire un processo come System.

Vediamo ora come implementare il tutto:

prima di tutto creiamoci la dll con la procedura esportata la cui implementazione consiste nell' esecuzione di una CreateProcess

 

library HookDll; uses Windows, SysUtils, Classes; procedure AttivaApplicazione(FileName: string; Visibility: Integer); var zAppName: array[0..512] of Char; zCurDir: array[0..255] of Char; WorkDir: string; StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; begin StrPCopy(zAppName, FileName); GetDir(0, WorkDir); StrPCopy(zCurDir, WorkDir); FillChar(StartupInfo, SizeOf(StartupInfo), #0); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.lpDesktop := pChar('winsta0\default'); StartupInfo.dwFlags := STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := Visibility; CreateProcess(nil, zAppName, nil, nil, False, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo); end; {AttivaApplicazione} procedure MyCreateProcess(str: pChar); stdcall; begin AttivaApplicazione(str, SW_SHOW); end; exports MyCreateProcess; {$R *.RES} procedure EntryPointProc(reason: integer); begin case reason of DLL_PROCESS_ATTACH: begin end; DLL_THREAD_ATTACH: begin end; DLL_PROCESS_DETACH: begin end; DLL_THREAD_DETACH: begin end; end; end; begin DllProc := @EntryPointProc; EntryPointProc(DLL_PROCESS_ATTACH); end.


E' da notare la riga

StartupInfo.lpDesktop := pChar('winsta0\Desktop');

StartupInfo specifica le caratteristiche principali del processo che viene creato dalla CreateProcess ed il campo lpDesktop indica il Desktop con cui deve interagire il processo. Per maggiori informazioni sul concetto di WindowStation e Desktop si può far riferimento all' articolo

http://www.microsoft.com/msj/1298/terminalserver/terminalserver.aspx

che, pur essendo datato, contiene appunto un paragrafo di nome "Windowstations and Desktops" in cui si parla dei suddetti concetti. In breve se non viene specificato il valore di lpDesktop, il processo generato dalla CreateProcess andrà in esecuzione ndella WindowStation dell' utenza System e quindi non sarà visibile graficamente (pur essendo visibilissimo dal Task Manager).

Bene, ora dobbiamo creare una procedura che dovrà essere copiata ed eseguita nello spazio di memoria di winlogon.exe e che appunto faccia le seguenti cose: carichi nello spazio di memoria di winlogon.exe la dll sopra (di nome HookDll.dll),e chiami la procedura esportata dalla medesima (MyCreateProcess), esegua il FreeLibrary della dll precedentemente caricata. Assieme ad essa dobbiamo definire un record che contenga tutte le informazioni di cui la procedura stessa avrà bisogno per eseguire il suo operato una volta copiata nello spazio di memoria di winlogon.exe. Un puntatore a tale record sarà appunto l' argomento di input della procedura stessa. Tenendo conto di tutte le considerazioni fatte negli articoli precedenti si perviene a:

unit ProcessUtilities; interface uses Windows, Sysutils, TlHelp32; procedure SystemProcess(NomeProg: pChar); implementation type TRemoteData = record pMyCreateProcess: procedure(str: pChar); stdcall; pGetModuleHandle: function(lpModuleName: PChar): HMODULE; stdcall; pLoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall; pGetProcAddress: function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall; pFreeLibrary: function(hLibModule: HMODULE): BOOL; stdcall; pExitProcess: procedure(uExitCode: UINT); stdcall; pDllName: pchar; pFunctionName: 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 InjectDll(PID: dword; DLL: pChar); var BytesWritten, Process, Thread, ThreadId: dword; Paramaters: pointer; begin ModificaPrivilegio('SeDebugPrivilege', TRUE); Process := OpenProcess(PROCESS_CREATE_THREAD + PROCESS_QUERY_INFORMATION + PROCESS_VM_OPERATION + PROCESS_VM_WRITE + PROCESS_VM_READ, False, PID ); Paramaters := VirtualAllocEx( Process, nil, Length(DLL), MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(Process, Paramaters, Pointer(DLL), Length(DLL), BytesWritten); Thread := CreateRemoteThread(Process, nil, 0, GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'LoadLibraryA'), Paramaters, 0, ThreadId); WaitForSingleObject(Thread, INFINITE); VirtualFreeEx(Process, Paramaters, 0, MEM_RELEASE); CloseHandle(Thread); CloseHandle(Process); end; procedure RemoteThread(RemoteData: PRemoteData); stdcall; var Dll_handle:LongWord; begin with RemoteData^ do begin Dll_Handle := pGetModuleHandle(pDllName); if Dll_handle = 0 then Dll_Handle := pLoadLibrary(pDllName); pMyCreateProcess := pGetProcAddress(Dll_Handle, pFunctionName); pMyCreateProcess(pProgName); pFreeLibrary(Dll_handle); 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.pDllName := InjectString(Process, pChar(GetCurrentDir + '\HookDll.dll')); RemoteData.pFunctionName := InjectString(Process, 'MyCreateProcess'); RemoteData.pProgName := InjectString(Process, NomeProg); RemoteData.pGetModuleHandle := GetProcAddress(GetModuleHandle('kernel32'), 'GetModuleHandleA'); RemoteData.pLoadLibrary := GetProcAddress(GetModuleHandle('kernel32'), 'LoadLibraryA'); RemoteData.pGetProcAddress := GetProcAddress(GetModuleHandle('kernel32'), 'GetProcAddress'); RemoteData.pExitProcess := GetProcAddress(GetModuleHandle('kernel32'), 'ExitProcess'); RemoteData.pFreeLibrary := GetProcAddress(GetModuleHandle('kernel32'), 'FreeLibrary'); ptrInput := InjectDati(Process, @RemoteData, SizeOf(RemoteData)); ptrProc := InjectDati(Process, @RemoteThread, dword(@EndRemoteThread) - dword(@RemoteThread)); Thread := CreateRemoteThread(Process, nil, 0, ptrProc, ptrInput, 0, ThreadId); WaitForSingleObject(Thread, INFINITE); CloseHandle(Thread); end; end.

La procedura chiave della unit ProcessUtilites è SystemProcess che prende in input il nome di un programma e lo esegue nel contesto dell' utenza System. Il gioco è quindi fatto. Per verificare che il programma lanciato gira effettivamente come System basta aprire il Task Manager, andare nell' elenco dei processi e vedere che appunto il nome utente associato al programma è SYSTEM. Utilizzando "Process explorer" si può verificare che effettivamente il processo generato è figlio di Winlogon.exe. Poi si può verificare che si ha un livello di accesso superiore alla norma: se lanciamo regedit.exe possiamo ad esempio navigare nella chiave HKLM\SAM. Se poi eseguiamo cmd.exe si può entrare tranquillamente nella cartella "System Volume Information" della partizione di sistema, etc...

sorgenti

 

 

 
 
Your Ad Here