[C++] Api Hooking Hakkında Soru
-
merhaba beyler,
kısa ve basit bir sorum var, ben explorer.exe nin görüntülediği/listelediği dosyaları kancalamak istiyorum hangi apiyi hook etmem gerekli, bilen var mı?
-
kimse mi bilmez :D
-
Yetkili müşteri temsilcimizi yönlendirdim
Şimdi sizinle ilgileniyor efendim.
Tahmini geri dönüş süresi, eleman buradan cıkacak eve gidecek olydebugdan bakıp cevap verecek
-
Öncelikle şunu belirteyim, tam olarak hazır bir program vermeyeceğim, bu konular genelde iyi amaçlar için kullanılmadığından, hazır fonksiyonu kodunda kullanamayacak, veya bu örnekte gereken dll injection kodunu yazamayacak kişilerin eline hazır program vermek istemiyorum.
Listelenen dosyaları elde etmenin yolları şunlardır (farklı yollar da vardır tabi ama api hook dediğin için)
1) FindFirstFile ve FindNextFile ı hook edersin, bu fonksiyonu hook fonksiyonundan çağırdıktan sonra dosya adını alırsın.
2) Bu fonksiyonların kendi içinde çağırdığı native api olan NtQueryDirectoryFile apisini hook edersin, ntdll.dll içindeki native apileri hook etmenin yolu tamamen farklıdır ve sakıncaları olabilir bazı durumlarda ama kernele çıkan tek yol olduğu için avantajı da var.
Bu iki yol user mode idi, bunları yapmak için her process'in kendi bellek alanına hook fonksiyonunu yazman lazım ve orda çalıştırman lazım (bkz korumalı mod) ayrıca her process' in kernel32 si normalde bellekte tek kopyadır ama sen editlersen editlediğin yerin sana özel bir kopyası çıkarılır, diğer processler yine editlenmemiş olanı kullanır (ntdll.dll içinde geçerli) (bkz copy on write) doğal olarak her process de hook u ayrıca yapman lazım. bunun da en basit yolu = dll injection. (senin durumunda tek hook edeceğin explorer.exe olacağı için sıkıntı yok)
Gelelim kernel mode da ne yapabiliriz.
3) Aygıt sürücü yazarsın, kernel modda NtQueryDirectoryFile ın kernel kodunu hook edersin, (bkz ssdt hook) kendi fonksiyonunu yazarsın oraya, tüm processleri ayrı ayrı hook etmekle uğraşmazsın, kernelde herşeyin tek kopyası vardır ve tüm kernel mod programlar ve kernel aynı bellek alanını kullanır. (bkz kernel space vs user space)
4) FileSystem Filter Driver yazarsın, her dizin listeleme isteği geldiğinde önce listelenmiş dosya isimlerini sen ele geçirirsin ve user mod programına yollarsın. Aslında kernel mode da gördüğün gibi herşey daha kolaydır ancak kernelde kod yazmak da ayrıca deneyim isteyen birşey.
Şimdi yukardaki adımları açıklıyorum.
1) Bir dll hazırlayacaksın, yüklenir yüklenmez FindFirstFile ve FindNextFile apilerini kernel32 den bulup oraya kendi fonksiyonunun adresini yazacaksın, kendi fonksiyonunda da yine bu apileri çağırıp sonuçlarını ele geçireceksin. Bunu yapan kendi fonksiyonum (j4x ile birlikte yazdık ancak şuan kullanmıyoruz)
BOOL SetApiHook (LPCSTR szDllName, LPCSTR szApiName, PHOOK PhkFunc, LPVOID lpHookFunc ) { HMODULE hHookDll = NULL; DWORD dwOldFlags = 0; LPVOID lpFunc = NULL; *((int*)(JmpCode + 1)) = (int)lpHookFunc; CopyMemory(PhkFunc->JmpCode, JmpCode, TRAMPOLINE_SIZE); hHookDll = GetModuleHandle(szDllName); if (hHookDll == NULL) { return FALSE; } lpFunc = GetProcAddress(hHookDll, szApiName); if (lpFunc == NULL) { return FALSE; } PhkFunc->FuncPtr = lpFunc; if (!VirtualProtect (lpFunc, TRAMPOLINE_SIZE, PAGE_EXECUTE_READWRITE, &dwOldFlags)) { return FALSE; } CopyMemory(PhkFunc->OrgBytes, lpFunc, TRAMPOLINE_SIZE); CopyMemory(lpFunc, JmpCode, TRAMPOLINE_SIZE); return TRUE; }
Fonksiyonu kullanman için gereken bilgiler şunlar;
jmpcode bir global değişken, bunun içinde
push senin_hook_fonksiyonun
ret
komutlarının hex kodları var, senin_hook_fonksiyonun yerine kendi adresini yazıyosun kodda. bu değer ney dersen
char JmpCode[TRAMPOLINE_SIZE] = {0x68, 0x00, 0x00, 0x00, 0x00 ,0xC3};
İkincisi HOOK yapısı, ziraa parametrelerden birisi PHOOK, o da şöyle
typedef struct _HOOK{ LPVOID FuncPtr; char OrgBytes[TRAMPOLINE_SIZE]; char JmpCode[TRAMPOLINE_SIZE]; } HOOK, *PHOOK;
#define TRAMPOLINE_SIZE 6
Bu bilgilerle bu fonksiyonu kendi kodunda çağırabilmen lazım.
2) Native Api hook biraz daha farklı, ntdll.dll içinde 15 baytlık kodlar vardır her fonksiyon için, bu kodlar sadece eax e uygun fonksiyon no koyar ve ordan sysenter ile kernel mode geçer. İşte biz bu 15 baytı çalıyoruz yerine kendi kodumuzu koyuyoruz, o kod ile hook fonksiyonuna atlıyor, iş bittikten sonra bu 15 baytı yine çalıştırıyoruz. bunu yapan fonksiyon;
BOOL SetNativeApiHook (LPCSTR szApiName, LPVOID lpCallStub, LPVOID lpHookFunc) { HMODULE hNtdll = NULL; DWORD dwOldFlags = 0; LPVOID lpFunc = NULL; *((int*)(JmpCode + 1)) = (int)lpHookFunc; hNtdll = GetModuleHandle("Ntdll.dll"); if (hNtdll == NULL) { return FALSE; } lpFunc = GetProcAddress(hNtdll, szApiName); if (lpFunc == NULL) { return FALSE; } if (!VirtualProtect (lpCallStub, NATIVE_CALL_STUB_SIZE, PAGE_EXECUTE_READWRITE, &dwOldFlags)) { return FALSE; } if (!VirtualProtect (lpFunc, NATIVE_CALL_STUB_SIZE, PAGE_EXECUTE_READWRITE, &dwOldFlags)) { return FALSE; } CopyMemory(lpCallStub, lpFunc, NATIVE_CALL_STUB_SIZE); CopyMemory(lpFunc, JmpCode, TRAMPOLINE_SIZE); return TRUE; }
Bu fonksiyonu çağırman için gereken yukardakiler dışında şu;
#define NATIVE_CALL_STUB_SIZE 16
char CallStubName[NATIVE_CALL_STUB_SIZE];
Artık bunu da kullanabilmen gerek. CallStubName her fonksiyon için ayrı olmalı, çünkü ntdll.dll den çaldığın baytlar burda, fonksiyon ismiyle ilişkili birşey yazman daha iyi.
3) SSDT Hook için yıllar önce Mark Russinovich'in filemon için yazdığı bir dizi hook makrosu vardır, ben dahil herkes bunları kullanır ancak mantığını anladıktan sonra kendin de yazarsın, bu konuyu uzun uzadıya açıklasam da büyük ihtimal kimse birşey anlamayacak, makroları veriyorum.
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \ _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook) #define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) \ InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook) #define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1) HOOK_SYSCALL( ZwQueryDirectoryFile, NewZwQueryDirectoryFile, OldZwQueryDirectoryFile ); şeklinde çağıracaksın
4) Filesystem filter driver ın aslında api hook ile pek ilgisi yok ama güzel bir yöntem olduğu için kısaca değineyim. önce bir filter driver yazıp ntfs.sys nin üstüne yerleştireceksin, böylece bu driver a giden tüm IRP paketleri önce sana uğrayacak. Gelen IRP nin major fonksiyonu IRP_MJ_DIRECTORY_CONTROL ise, minor fonksiyonu da IRP_MN_QUERY_DIRECTORY ise, demekki bu driver a gelen IRP paketinin amacı belli bir dizindeki dosyaları listelemek.
Biz hemen bir callback fonksiyon set ediyoruz IoSetCompletionRoutine fonksiyonuyla, listeleme işlemi bitince kernel tarafından bizim fonksiyonumuz çağırılıyor. bu fonksiyonda IRP->UserBuffer da dosya ve dizin isimleri var , alıp user mode programımıza yollayabiliriz.
Kernel mod olanlar büyük ihtimal işine yaramaz ancak user mode olan 2 hook yöntemi çok sağlamdır. Ayrıca inline hook dışında bir de import table hook var, ben pek sevmiyorum ama aynı işlemleri onunla da yaparsın user mode da.
-
tugberk,
öncelikle sen adamsın :D, uğraşıp detaylı bir anlatım yapmışsın çok teşekkürler ilginden dolayı, böyle bir açıklamaya karşın bende uzun birşeyler yazmak isterim, bari neden böyle birşey istediğimi yazayım : )
bizim okulda optik okuyuclarla yazılıları okuyorlar(lise 4 öğrencisiyim), ben de bir program yazdıydım sistemde arada bir arama yapıp okunan dosyalarda (heriflerin optik okuyucu yazılımlarının çıkardığı data dosyaları) adımı numaramı görünce cevap isminde kağıdı bulup zınk 70-100 arası bir cevap anahtarı yapışytırıyordu, ama arama işlemi hem sistmei kasıyor hemde hocalar işini seri hallederse yazılım birşey yapamıyordu bende dll enjekte yapayım dedim hem cpp ile uğraşayım az (zorda kalmadıkça kullanmam :D), önce yazılmın writefile apisini hook edeyim dedim sonra bu yazılımın nasıl tepki vereceğini bilmiyorum dedim, ayrıca yazılım ve optik okuyucu bende olmadığından direk deneyebilme imkanım da yok çalıştırıp bırakıcam yazılımı, işte dedim bunu bir şekilde herifler sisteme geçicekler o sırada explorer.exe bunu görüntülecek ben burdan dosyayı çekerim dedim, win apilerine de o kadar aşina biri değilim foruma sorayım dedim, eyv çok yardımcı oldunuz
tekrardan teşekkürler : )
-
sen programın tam olarak ne yapmasını istediğini pm ile açıkla (tam olarak) , boş bir zamanımda yazarım.
-
yok dayı est, ne haddime senin gibi bir insanı böyle birşeyle yorayım, ben programın büyük kısmını yazdım, sadece hook edicek apiyi arıyordum sende apileri söyledin(beraberinde bir çok ayrıntıyı anlattın çok teşekkürler) olay tamam, bu dönemden geçti bir dahaki dönem kuruyorm makineye yazılımı :D
-
nessaj bunu yazdı:
-----------------------------yok dayı est, ne haddime senin gibi bir insanı böyle birşeyle yorayım, ben programın büyük kısmını yazdım, sadece hook edicek apiyi arıyordum sende apileri söyledin(beraberinde bir çok ayrıntıyı anlattın çok teşekkürler) olay tamam, bu dönemden geçti bir dahaki dönem kuruyorm makineye yazılımı :D
-----------------------------ahah :) helal bu arada lise 4 e gidiyorsun bunları yazabiliyorsun.
-
Müşteri Memnuniyeti Anketi :
Efenim öncelikme müşteri memnuniyeti anketimize katıldığınız için teşekkür ederiz.
Müşteri temsilcimizi geliştirmemiz için lütfen aşağıdaki soruları cevaplayın
1 rezil 5 mükemmel
1. Temsilcinin Performansı ? :
2. Temsilcinin Hızı? :
3. Temsilcinin Efendiliği? :
4. Temsilcinin Bilgisi? :
Söleyin maaşını ona göre verelim...
-
Bu arada sorun lise 4 e gidip bunları yazması değil
lise 4 de gözünün bu derece acık olması.
Tebrik ediyorum hocam, üniversiteye gir bilgisayarı geliştir işe alalım seninde...
-
buyuk harf yasak ama yazicam : NESSAJ / TUGBERK DE TBT ye Yakisir Muridler.. :)