Wrzuta downloader

Posted in C++, Newsy on Lipiec 23rd, 2010 by Grzonu

Bardzo lubie sciagnac zasłyszana piosenke do siebie jako mp3 (oczywiscie na 24h ;) )
Czesto uzywam do tego z wrzuty i serwisow ktore umozliwiaja pobranie utworu z tego serwisu.
Niestety ostatnio wrzuta zmienila sposob pobierania plikow upodobnila go do sposobu megavideo ktory dosc mocno utrudnia pobieranie(do pobrania trzeba otworzyc plik XML a w nim jest link ale skozystac z niego mozna tylko z tego IP z ktorego zostal pobrany XML)

Czesc serwisow ktore umozliwiaja pobierania przestała dzialac a czesc wprowadzila skrypt Java ktory pobierze nam utwor. Jako ze Javy nie mam zainstalowanej i nie zamierzam instalowac tak wiec napisalem sobie programik w C++ ktory pobierze utwor z wrzuty.
Programik pisalem dla siebie no ale postanowilem udostepnic go szerszemu gronu. Wiec jakby komuś się przydał to zapraszam do sciagania ;)

DOWNLOAD

Tags: , , ,

Kolejna metoda detekcji debuggera

Posted in C++ on Lipiec 6th, 2010 by Grzonu

Ostatnimi czasy wrocilem do badania metod wykrywania debuggerow i wymyslilem metode oparta o funkcje NtQuerySystemInformation mozliwe ze ktos wpadł juz na to wczesniej lecz nie moglem nic znalesc na ten temat.

Metoda jest bardzo prosta za pomoca funkcji NtQuerySystemInformation z parametrem SystemHandleInformation
pobieramy uchwyty otwarte przez wszystkie aplikacje. Poszukujemy uchwytow do procesow ktore sa uchwytami do naszego procesu i sprawdzamy czy wsrod uchwytow tego procesu nie znajduje sie uchwyt o typie 0xb czyli DebugObject jesli znajduje sie to moze byc znak ze jestesmy debuggowani(choc nie ma 100% pewnosci)

Czas na troche kodu :)

potrzebne nam zmienne i funkcja:

1
2
3
4
5
6
7
8
9
NTSTATUS                        ntStatus;
DWORD                           dwParentPID =   0xffffffff;
HANDLE							h_proc,h;
ULONG                           need;	
BOOL							isDebug=0;
 
 
HMODULE ntdll = GetModuleHandle("ntdll");
NTQSI NtQuerySystemInformation = (NTQSI)GetProcAddress(ntdll, "NtQuerySystemInformation");

Wywolajmy teraz funkcje NtQuerySystemInformation

1
2
3
4
5
6
7
8
9
10
11
ULONG size = 0x1000;
SYSTEM_HANDLE_INFORMATION *handles = (SYSTEM_HANDLE_INFORMATION*)malloc(size);
 
ntStatus = NtQuerySystemInformation(SystemHandleInformation, handles, size, &need);
if(ntStatus!=0)//jesli za maly bufor alokujemy wiekszy
					   {
                        free(handles);
                        size =need;
                        handles = (SYSTEM_HANDLE_INFORMATION*)malloc(size);
		NtQuerySystemInformation(SystemHandleInformation, handles, size, &need);
						}

w tym momecie w w strukturze handles mamy wszystkie uchwyty dostepne w systemie.
Musimy przeszukac czy wsrod nich nie ma uchwytow o typie 0×7 czyli proces.
Jesli taki znajdziemy to musimy otworzyc ten proces z prawami PROCESS_DUP_HANDLE
i zduplikowac ten uchwyt ale w naszym procesie. Nastepnie sprawdzic czy jest to uchwyt do naszego procesu a jesli tak to sprawdzic czy wsrod uchwytow tego procesu nie ma uchwytow typu DebugObject

A teraz praktyka:

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
int i=0;
int j=0;
for (i=0; i<handles->HandleCount; i++)
{
	if(handles->Handles[i].ObjectType==7)//Process
	{
		h=OpenProcess(PROCESS_DUP_HANDLE, FALSE,handles->Handles[i].OwnerPid);
		if(h!=0)
		{
			if (DuplicateHandle(h, (HANDLE)handles->Handles[i].HandleValue, GetCurrentProcess(),&h_proc, 0, FALSE, DUPLICATE_SAME_ACCESS))
			{
				if(GetProcessId(h_proc)==GetCurrentProcessId())
				{
					j=0;
					while(j<handles->HandleCount)
					{
						if(handles->Handles[i].OwnerPid==handles->Handles[j].OwnerPid && handles->Handles[j].ObjectType==0xb)
						{
						isDebug=1;
						}
					j++;
					}
				}
			}
		}
	}
}

Na koniec printfujemy wyniki przeszukiwania i zwalniamy bufor

1
2
3
4
5
6
7
8
9
if(isDebug==1)
{
printf("Debugger wykryty\n");
}
else
{
printf("Nie wykryto debuggera\n");
}
	if (handles) free(handles);

Caly kod programu mozna sciagnac TU

PS.
Czysty olly jest ta metoda bez problemu wykrywany ale np. Olly z pluginem StrongOD juz nie.
Plugin ten m.in powoduje ze lista uchwytow dla tego procesu jest pusta. Jest to tez dosc charakterystyczne bo kazdy program ma jakies uchwyty. Dodatkowo mozemy sprawdzac nasz proces rodzica jakie uchwyty posiada(albo nie posiada wcale)

Tags: , ,

Wykrywanie IAT hookingu

Posted in C++, Security on Czerwiec 25th, 2010 by Grzonu

Jak obiecalem tak zrobilem. Dzis chciałbym omowic IAT hooking i sposoby ich wykrywania.
Za jakis czas postaram sie napisac cos o hookach EAT i modyfikacjach kodu.

No wiec zaczynamy.
Najpierw kilka słow czym jest sam IAT hooking – jest to technika hookowania funkcji poprzez zamiane adresu funkcji umieszczonego w IAT na adres
funkcji umieszczonej w innej bibliotece dll albo poprostu gdzies w pamieci. O samym zakładaniu hookow pisal nie bede sa do tego dziesiatki gotowych
bibliotek, setki przykładowych kodów wiec mysle ze ci ktorzy jeszcze tego nie opanowali powinni jak najszybciej uzupełnic braki kozystajac z google.

Teraz cos na temat wykrywania tych hookow – Opisze w punktach co musimy zrobic:
1. Znajdujemy plik exe procesu w ktorym chcemy hookow poszukac.
2. Znajdujemy w tym pliku tablice IAT i sprawdzamy wszystkie funkcje znajdujace sie w IAT
3. Sprawdzamy w jakim module wg. IAT powinna znajdowac sie dana funkcja.
4. Sprawdzamy ImageBase i Size tego modułu i sprawdzamy czy adres w IAT miesci sie w przedziale
Jesli tak to wszystko OK jesli nie to sprawdzamy na jaki moduł wskazuje dany adres

To tyle teori.
Czas na praktyke.

Potrzebne naglowki:

1
2
3
4
5
6
7
8
9
#include <windows.h>
#include <stdio.h>
#include <string>
#include <Tlhelp32.h>
#include <vector>
#include <Psapi.h>
#include <fstream>
#include "PE_class.h" //moja klasa do obslugi plikow PE(udostepnie razem z reszta kodu)
#pragma comment (lib,"psapi.lib");

Zmienne globalne:

1
2
3
HANDLE hProc;//uchwyt procesu
DWORD pid;//ProcessID
DWORD MainImageBase;//ImageBase procesu

Main:

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
int main(int argc, CHAR* argv[])
{
printf("\n\nIAT Hook detector v. 1.0 by Grzonu\n\n");
 
if(argc!=2)//sprawdzamy czy podano parametr jesli nie to wychodzimy
{
	printf("usage: %s <pid>\n\n",argv[0]);
	return 0;
}
pid=atoi(argv[1]);//pobieramy PID
DWORD IB=0;
DWORD ImgSize=0;
FindImageBase(pid,&IB,&ImgSize);//Znajdujemy ImageBase i Size procesu
printf("ImageBase: 0x%.8x\nImageSize: 0x%.8x\n\n",IB,ImgSize);
 
hProc=OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,pid);//otwieramy go
if(hProc==0)//jesli sie nie udalo to wychodzimy
{
printf("can`t open process\n");
return 0;
}
char* buf=LoadMod(IB);//ladujemy plik
MainImageBase=IB;
PE_file PE((HMODULE)buf);
IAT(&PE);//szukamy hookow
free(buf);//zwalniamy bufor zaalokowany w funkcji LoadMod
 
 
	return 0;
}

Teraz postaram sie omowic kazda z funkcji na poczatek FindImageBase() czyli funkcja szukajaca ImageBase i Size procesu

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
DWORD FindImageBase(DWORD pid,DWORD* IB,DWORD* ImgSize)//funkcja przyjmuje processID, wskazniki na bufory na dane
{
PROCESSENTRY32 lppe32;
char buf[260];
	memset(buf,0,260);
    HANDLE hSnapshot;
   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//robimy snapshot listy procesow
    lppe32.dwSize = sizeof(PROCESSENTRY32);
 
    Process32First(hSnapshot, &lppe32);
	    do
        {
		if(lppe32.th32ProcessID==pid)//szukamy naszego procesu
		{
		strcpy(buf,lppe32.szExeFile);
		break;
		}
 
		}
        while(Process32Next(hSnapshot, &lppe32));
        CloseHandle(hSnapshot);
if(buf[0]==0)//jesli nie udalo sie znalesc zwracamy 0;
{
return 0;
}
 
MODULEENTRY32 mod32;
std::string x;
 
   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);//robimy snapshot listy modolow znalezionego procesu
   mod32.dwSize = sizeof(MODULEENTRY32);
 
    Module32First(hSnapshot, &mod32);
	     do
        {
		x=mod32.szExePath;
		if(x.find(buf)!=0xFFFFFFFF)//sprawdzamy czy to główna czesc programu
		{//jesli tak to wypelniamy odpowiednie zmienne
			*IB=(DWORD)mod32.modBaseAddr;
			*ImgSize=mod32.modBaseSize;
		}
 
 
		}
        while(Module32Next(hSnapshot, &mod32));
        CloseHandle(hSnapshot);
return 1;
}

Mamy wiec juz potrzebne ImageBase i ImageSize procesu. Teraz zajmiemy sie funkcja ladujaca kod modulu z pliku na ktory wskazuje ImageBase.
Dotyczyc to bedzie nie tylko glownego kodu programu ale i wszystkich bibliotek. Musimy pobrac ImageSize z pliku poniewaz ImageSize modulu
w pamieci bardzo latwo zmienic tak aby wygladalo ze kod jednej biblioteki pokrywa sie z druga poprzez zmiane ImageSize modulu w pamieci.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char* LoadMod(DWORD IB)
{
char ProcName[260];
GetModuleFileNameEx(hProc,(HMODULE)IB,ProcName,260);//pobieramy pelna sciezke do binarki modulu
std::ifstream f(ProcName,std::ios::binary);//otwieramy plik
char* buf;
f.seekg(0,std::ios::end);
int size=f.tellg();
f.seekg(0,std::ios::beg);
buf=(char*)malloc(size);//alokujemy bufor(pamietajmy go pozniej zwolnic)
memset(buf,0,size);
int i=0;
char ch;
while(i<size)
{
f.get(ch);//wczytujemy
buf[i]=ch;
i++;
}
f.close();
return buf;//zwracamy bufor
}

Teraz czas na glowna funkcje IAT() ktora ma za zadanie znalesc wszystkie funkcje importowane przez aplikacje i sprawdzic czy nie sa hookowane.
Funkcja ta kozysta z kilku innych funkcji ktore tez po drodze omowie.

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
void IAT(PE_file* PE)
{
HINSTANCE hInstance =(HINSTANCE)PE->buf;
PIMAGE_DOS_HEADER pdosheader = (PIMAGE_DOS_HEADER)hInstance;//pobieramy naglowki
PIMAGE_NT_HEADERS pntheaders = (PIMAGE_NT_HEADERS)((DWORD)hInstance + pdosheader->e_lfanew);//i dalej...
PIMAGE_SECTION_HEADER psectionheader = (PIMAGE_SECTION_HEADER)(pntheaders + 1);
PIMAGE_IMPORT_DESCRIPTOR pimportdescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hInstance + PE->RVA_to_RAW(pntheaders->OptionalHeader.DataDirectory[1].VirtualAddress));//znajdujemy adres IAT w naglowku PE ale jako ze szukamy w pliku a nie w procesie pamietamy o zamianie adresu z RVA na RAW
PIMAGE_THUNK_DATA pthunkdatain, pthunkdataout;
PIMAGE_IMPORT_BY_NAME pimportbyname;
DWORD dw;
PCHAR ptr;
DWORD IB;
char* buf;
DWORD ImgSize;
PIMAGE_OPTIONAL_HEADER32 opt;
DWORD address;
DWORD IAT_adr;
DWORD read;
 
int i=0;
while ( pimportdescriptor->TimeDateStamp != 0 ||pimportdescriptor->Name != 0)//pobieramy tak dlugo importy az sie skoncza :)
{
	ptr = (PCHAR)((DWORD)hInstance+ PE->RVA_to_RAW((DWORD)pimportdescriptor->Name));//Nazwa biblioteki Dll
	i=0;
	IB=FindModule(ptr);//Funkcja szukajaca ImageBase na podstawie nazwy biblioteki(omowie dalej)
	buf=LoadMod(IB);//opisana wczesniej funkcja ladujaca kod 
	PE_file PE2((HMODULE)buf);//ladujemy kod do klasy
	opt=PE2.GetOptionalHeader();//Pobieramy odpowiedni header
	ImgSize=opt->SizeOfImage;//pobieramy potrzebne nam pole z tego headera czyli ImageSize
	free(buf);//zwalniamy bufor
 
		pthunkdataout = (PIMAGE_THUNK_DATA)((DWORD)hInstance + PE->RVA_to_RAW((DWORD)pimportdescriptor->FirstThunk));//pobieramy adres gdzie zaczynaja sie adresy w IAT
		if (pimportdescriptor->Characteristics == 0)
		{
			pthunkdatain = pthunkdataout;//pobieramy adres struktury z ktorej pobierzemy nazwy funkcji
		}
		else 
		{
			pthunkdatain = (PIMAGE_THUNK_DATA)((DWORD)hInstance +PE->RVA_to_RAW((DWORD)pimportdescriptor->Characteristics));//to samo ;)
		}
 
		while ( pthunkdatain->u1.AddressOfData != NULL)//dopuki sa jeszcze jakies funkcje
		{
			if ((DWORD)pthunkdatain->u1.Ordinal & IMAGE_ORDINAL_FLAG)//jesli Ordinal
			{
				LPSTR x=MAKEINTRESOURCE(LOWORD(pthunkdatain->u1.Ordinal));//Ordinal
				address=MainImageBase+(pimportdescriptor->FirstThunk+(i*4));//adres bufora na adres funkcji
				ReadProcessMemory(hProc,(LPCVOID)address,&IAT_adr,4,&read);//Odczytujemy adres funkcji znajdujacej sie pod adresem pobranym wyzej
 
				if(IAT_adr<IB || IAT_adr>(IB+ImgSize))//sprawdzamy czy adres miesci sie w granicach swojego modułu
				{//jesli nie to sprawdzamy w jakim module znajduje sie funkcja
				DWORD HookBase=FindHookModule(IAT_adr);//pobieramy ImageBase modułu w ktorym znajduje sie ta funkcja.(Ta funkcje omowie pozniej)
				char modname[260];
				if(HookBase==0)//jesli nie ma takiego modulu oznacza ze jest to poprostu zaalokowana pamiec np. przez VirtualAllocEx
				{
				strcpy(modname,"Virtual Memory");
				}
				else//jesli jest to pobieramy sciezke do tego modułu
				{
				GetModuleFileNameEx(hProc,(HMODULE)HookBase,modname,260);
				}
printf("Ord: %x(%s) --- Hooked by %s(0x%.8x)\n",x,ptr,modname,IAT_adr);//printfujemy wynik :)
				}
 
 
			} else {
				pimportbyname = (PIMAGE_IMPORT_BY_NAME)(PE->RVA_to_RAW((DWORD)pthunkdatain->u1.AddressOfData) + (DWORD)hInstance);
					address=MainImageBase+(pimportdescriptor->FirstThunk+(i*4));//tutaj to samo co wyzej 
				ReadProcessMemory(hProc,(LPCVOID)address,&IAT_adr,4,&read);
 
				if(IAT_adr<IB || IAT_adr>(IB+ImgSize))
				{
				DWORD HookBase=FindHookModule(IAT_adr);
				char modname[260];
				if(HookBase==0)
				{
				strcpy(modname,"Virtual Memory");
				}
				else
				{
				GetModuleFileNameEx(hProc,(HMODULE)HookBase,modname,260);
				}
				printf("%s(%s) --- Hooked by %s(0x%.8x)\n",(char*)pimportbyname->Name,ptr,modname,IAT_adr);
				}
 
			}
 
        i++;//nastepna funkcja
			pthunkdatain++;
			pthunkdataout++;
		}
 
	pimportdescriptor++;//nastepna DLL`ka
 
}
}

To teraz 2 funkcje ktore mialem omowic

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
void str_tolower(char* str)//funkcja zamieniajaca string na male litery
{
int i=0;
int size=strlen(str);
 
while(i<size)
{
str[i]=tolower(str[i]);
i++;
}
}
 
DWORD FindModule(char* mod_name)
{
MODULEENTRY32 mod32;
std::string x;
   HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);//o tym juz mowilem
   mod32.dwSize = sizeof(MODULEENTRY32);
   str_tolower(mod_name);
 
    Module32First(hSnapshot, &mod32);
	     do
        {
		str_tolower(mod32.szExePath);
		x=mod32.szExePath;
 
		if(x.find(mod_name)!=0xFFFFFFFF)//jesli to szukany modul to zwracamy jego ImageBase
		{
			return (DWORD)mod32.modBaseAddr;
		}
 
 
		}
        while(Module32Next(hSnapshot, &mod32));
        CloseHandle(hSnapshot);
		return 0;
}
 
DWORD FindHookModule(DWORD Address)//funkcja szukajaca ImageBase modulu w ktorym znajduje sie funkcja
{
MODULEENTRY32 mod32;
   HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
   mod32.dwSize = sizeof(MODULEENTRY32);
 
    Module32First(hSnapshot, &mod32);
	     do
        {
		if(Address>=(DWORD)mod32.modBaseAddr && Address<=(DWORD)(mod32.modBaseAddr+mod32.modBaseSize))//jesli adres znajduje sie w przedziale <ImageBase ; ImageBase+ImageSize> to zwracamy jego ImageBase
		{
return (DWORD)mod32.modBaseAddr;
		}
 
		}
        while(Module32Next(hSnapshot, &mod32));
        CloseHandle(hSnapshot);
		return 0;
}

To chyba tyle na dzis.
Przedstawiona metoda jest prosta a jednak skuteczna(choc oczywiscie ja tez mozna ominac)
Jesli bym o czyms zapomnial to dopisze wkrotce ;)

Załączam kod pod VC++ i binarke ;)
Link

Tags: , ,

Zapobieganie Code Injection i Dll Injection

Posted in C++ on Grudzień 19th, 2009 by Grzonu

Dzisiaj zajmiemy się zapobieganiem Code Injection i Dll Injection.
Obie te techniki łączy wspólna rzecz – obie tworzą zdalny wątek w aplikacji. Po wywołaniu funkcji CreateRemoteThread która ma utworzyć wątek w drugiej aplikacji, wywołanie trafia do jądra, które w aplikacji w której wątek ma powstać tworzy wątek i startuje go w funkcji KiUserApcDispatcher ale jak powiedział mi j00ru nie jest bezpiecznie modyfikowac ta funkcje bo kozysta z niej bardzo wiele innych funkcji. Zamiast tego lepiej modyfikowac LdrInitializeThunk która jest później wywoływana. No wiec zalozymy sobie hooka na ta funkcje.
Pierwsze 5 bajtów nadpiszemy skokiem do naszej funkcji która zamknie nowo powstały wątek zanim kod zostanie wykonany.
Kod naszej funkcji:

1
2
3
4
5
6
void __declspec(naked)wrap(void)
{
printf("Killing thread: %d\n",GetCurrentThreadId());
TerminateThread(GetCurrentThread(),0); //zamykamy wątek
__asm ret
}

No to nadpiszmy kod funkcji.

1
2
3
4
5
6
7
8
x=GetProcAddress(GetModuleHandle("NTDLL"),"LdrInitializeThunk"); //pobieramy adres funkcji
DWORD old;
VirtualProtect(x,5,PAGE_EXECUTE_READWRITE,&old); // ustawiamy prawa do zapisu
memcpy(x,"\xE9",1); //nadpisujemy pierwszy bajt(0xE9 to jmp)
DWORD addr=(DWORD)wrap-(DWORD)x-5;//obliczamy przesuniecie naszej funkcji wzgledem orginału
//aby wykonac skok zgodnie ze wzorem offset=punkt_docelowy-miejsce_do_nadpisania-5
memcpy((char*)((char*)x+1),&addr,4);//kopiujemy tam nasz offset
VirtualProtect(x,5,old,&old);//ustawiamy spowrotem prawa

Teraz mozemy sprobowac utworzyc zdalny wątek w naszej aplikacji. Wątek utworzy się lecz zostanie odrazu zabity.
Jeśli chcemy w naszej aplikacji używać wątków powinnismy napisać funkcje która najpierw przywróci orginalne bajty następnie wywoła CreateThread po czym od nowa nadpisze skokiem. To juz pozostawiam chętnym.

Po tym zabiegu Olly także nie bedzie potrafił się attachnąć do naszego procesu.
To chyba tyle na dziś ;)

przykładowa aplikacja

//EDIT
Właśnie hxv poinformował mnie że można attachnac sie Ollym ale z uzyciem OllyAdvance :)

//EDIT2
Przygotowałem dll`ke która będzie chroniła nasza aplikację odrazu po wczytaniu jej do programu(LoadLibrary)
DLL`ka

A tak dodatkowo chciałbym podziękować Gynvaelowi Coldwindowi bo prawdopodobnie bez jego pomocy ten i kilka innych postow zakonczyloby sie po 3 wyrazach ;)

Tags: , , , ,

Anti Keylogger

Posted in C++, Security on Listopad 17th, 2009 by Grzonu

Dzisiejszego dnia na strone dodałem Anti Keylogger program który będzie chronił komputer przed wszelkimi programami monitorujacymi stan klawiatury.

Zapraszam do testów.

//EDIT 20.11.09 aktualnilem program

Tags: , ,

GrzonuShell

Posted in C++ on Listopad 4th, 2009 by Grzonu

Dziś do dzialu projekty dodany został program GrzonuShell ktory jest narzedziem do zdalnej administracji własnym komputerem.

Zapraszam do testów.
Będe wdzięczny za wszelkie komentarze.

Tags: , ,

Niekonwencjonalna metoda zabijania procesu ;)

Posted in C++, assembler on Październik 7th, 2009 by Grzonu

Dziś 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)

Tags: , , , , , ,

Nowy keylogger

Posted in C++ on Wrzesień 12th, 2009 by Grzonu

Na stronie pojawil sie nowy keylogger
posiada wiele ciekawych funkcji

Zapraszam do testow :)
Bede wdzieczny za wszelkie komentarze

Tags: , ,

AntiDebug Library

Posted in C++, assembler on Sierpień 28th, 2009 by Grzonu

Do źródeł dodany zostal kod klasy chroniacej przed Debuggerami, VM,  Sandboxami, AV

Tags: , , , , ,

Nowy artykuł

Posted in C++, assembler on Lipiec 31st, 2009 by Grzonu

Na stronie pojawił się nowy artykuł na temat pisania PE loadera czy „jak to sie dzieje ze program się włącza”.

Jest jeszcze jedno ogłoszenie.
BlackSun Team poszukuje zdolnych koderów,grafików,testerów. Szczegóły na http://bl4cksun.org

Tags: ,