-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from DartVanya/main
Add user friendly GUI installer on AutoHotkey
- Loading branch information
Showing
9 changed files
with
445 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
Inject(PID, dll) | ||
{ | ||
static PROCESS_ALL_ACCESS := 0x1F0FFF, MEM_COMMIT := 0x1000, MEM_RELEASE := 0x8000, PAGE_EXECUTE_READWRITE := 64 | ||
,hKernel32 := DllCall("LoadLibrary", "Str", "kernel32.dll", "PTR") | ||
,LoadLibraryW := DllCall("GetProcAddress", "PTR", hKernel32, "AStr", "LoadLibraryW", "PTR") | ||
|
||
hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int", 0, "UInt", PID, "PTR") | ||
If !hProc | ||
throw Exception("Could not open process for PID: " PID ". LastError: " A_LastError, -1) | ||
|
||
nDirLength := VarSetCapacity(nDir, (StrLen(dll)+1) << 1, 0) | ||
,StrPut(dll, &nDir, "UTF-16") | ||
|
||
If !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr") { | ||
DllCall("CloseHandle", "PTR", hProc) | ||
throw Exception("Could not reseve memory for process: " A_LastError, -1) | ||
} | ||
|
||
DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0) | ||
|
||
hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", LoadLibraryW, "PTR", pBufferRemote, "UInt", 0, "PTR", 0, "PTR") | ||
lasterr := A_LastError | ||
|
||
if (hThread) { | ||
; waits until the specified object is in the signaled state or the time-out interval elapses | ||
WaitResult := DllCall("WaitForSingleObject", "ptr", hThread, "uint", 0xFFFFFFFF) | ||
} | ||
|
||
DllCall("VirtualFreeEx","PTR", hProc, "PTR", pBufferRemote, "PTR", nDirLength, "Uint", MEM_RELEASE) | ||
DllCall("CloseHandle", "PTR", hProc) | ||
If !hThread | ||
throw Exception("Could not load " dll " in remote process: " lasterr, -1) | ||
return hThread | ||
} | ||
|
||
; https://www.autohotkey.com/boards/viewtopic.php?t=68716 | ||
DllUnInject(ProcessID, ModuleName) | ||
{ | ||
static TH32CS_SNAPMODULE := 0x00000008 | ||
, STANDARD_RIGHTS_REQUIRED := 0x000F0000 | ||
, SYNCHRONIZE := 0x00100000 | ||
, PROCESS_ALL_ACCESS := (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF) | ||
, INFINITE := 0xFFFFFFFF | ||
, WAIT_FAILED := 0xFFFFFFFF | ||
, WAIT_OBJECT_0 := 0x00000000 | ||
|
||
try | ||
{ | ||
; take a snapshot of all modules in the specified process | ||
if !(hSnapshot := DllCall("CreateToolhelp32Snapshot", "uint", TH32CS_SNAPMODULE, "uint", ProcessID, "ptr")) | ||
throw Exception("CreateToolhelp32Snapshot failed: " A_LastError, -1) | ||
|
||
; set the size of the structure before using it. | ||
NumPut(VarSetCapacity(MODULEENTRY32, (A_PtrSize = 8 ? 568 : 548), 0), MODULEENTRY32, "uint") | ||
; retrieve information about the first module and exit if unsuccessful | ||
if !(DllCall("Module32First", "ptr", hSnapshot, "ptr", &MODULEENTRY32)) | ||
throw Exception("Module32First failed: " A_LastError, -1) | ||
|
||
; walk the module list of the process and gets the base address of the module | ||
while (DllCall("Module32Next", "ptr", hSnapshot, "ptr", &MODULEENTRY32)) | ||
if (ModuleName = StrGet(&MODULEENTRY32+ (A_PtrSize = 8 ? 48 : 32), 256, "cp0")) { | ||
modBaseAddr := NumGet(MODULEENTRY32, (A_PtrSize = 8 ? 24 : 20), "uptr") | ||
break | ||
} | ||
|
||
; exit if module is not found | ||
if !(modBaseAddr) | ||
throw Exception("Module not found", -1) | ||
|
||
; opens an existing local process object | ||
if !(hProcess := DllCall("OpenProcess", "uint", PROCESS_ALL_ACCESS, "int", 0, "uint", ProcessID, "ptr")) | ||
throw Exception("OpenProcess failed: " A_LastError, -1) | ||
|
||
; retrieves a module handle for the specified module | ||
if !(hModule := DllCall("GetModuleHandle", "str", "kernel32.dll", "ptr")) | ||
throw Exception("GetModuleHandle failed: " A_LastError, -1) | ||
|
||
; retrieves the address of an exported function or variable from the specified dynamic-link library (DLL) | ||
if !(pThreadProc := DllCall("GetProcAddress", "ptr", hModule, "astr", "FreeLibrary", "ptr")) | ||
throw Exception("GetProcAddress failed with: " A_LastError, -1) | ||
|
||
; creates a thread that runs in the virtual address space of another process | ||
if !(hThread := DllCall("CreateRemoteThread", "ptr", hProcess, "ptr", 0, "uptr", 0, "ptr", pThreadProc, "ptr", modBaseAddr, "uint", 0, "uint*", 0)) | ||
throw Exception("CreateRemoteThread failed with: " A_LastError, -1) | ||
|
||
; waits until the specified object is in the signaled state or the time-out interval elapses | ||
if ((WaitResult := DllCall("WaitForSingleObject", "ptr", hThread, "uint", INFINITE)) = WAIT_FAILED) | ||
throw Exception("WaitForSingleObject failed with: " A_LastError, -1) | ||
|
||
; if the state of the specified object is signaled (thread has terminated) | ||
if (WaitResult = WAIT_OBJECT_0) { | ||
; retrieves the termination status of the specified thread | ||
if !(DllCall("GetExitCodeThread", "ptr", hThread, "uint*", ExitCode)) | ||
throw Exception("GetExitCodeThread failed with: " A_LastError, -1) | ||
} | ||
} | ||
catch exception | ||
{ | ||
; represents errors that occur during application execution | ||
throw Exception | ||
} | ||
finally | ||
{ | ||
; cleaning up resources | ||
if (hThread) | ||
DllCall("CloseHandle", "ptr", hThread) | ||
if (hProcess) | ||
DllCall("CloseHandle", "ptr", hProcess) | ||
if (hSnapshot) | ||
DllCall("CloseHandle", "ptr", hSnapshot) | ||
} | ||
|
||
return ExitCode | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
ImpersonateTrustedInstaller() { | ||
return ImpersonateProcess(GetTrustedInstallerPid()) | ||
} | ||
|
||
RevertToSelf() { | ||
return DllCall("Advapi32.dll\RevertToSelf") | ||
} | ||
|
||
; https://github.com/winsiderss/systeminformer/blob/master/SystemInformer/runas.c#L2123; | ||
RunAsTrustedInstaller(cmd_line, work_dir := "") { | ||
static PROCESS_CREATE_PROCESS := 0x80, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS := 0x20000 | ||
, CREATE_NEW_CONSOLE := 0x10, EXTENDED_STARTUPINFO_PRESENT := 0x80000, CREATE_DEFAULT_ERROR_MODE := 0x4000000 | ||
|
||
if not (PID_TI := GetTrustedInstallerPid()) | ||
return false | ||
|
||
if !EnablePrivilege() ; need SeDebugPrivilege to open with PROCESS_CREATE_PROCESS | ||
return false | ||
hProcTi := DllCall("OpenProcess", "UInt",PROCESS_CREATE_PROCESS, "Int",false, "UInt",PID_TI, "Ptr") | ||
if (!hProcTi) | ||
return false | ||
|
||
VarSetCapacity(PROCESS_INFORMATION, A_PtrSize*2 + 8, 0) | ||
size := VarSetCapacity(STARTUPINFOEX, A_PtrSize*10 + 32, 0) | ||
NumPut(size, &STARTUPINFOEX + 0, "UInt") | ||
|
||
DllCall("InitializeProcThreadAttributeList", "Ptr",0, "UInt",1, "UInt",0, "UPtrP",size) | ||
size := VarSetCapacity(PROC_THREAD_ATTRIBUTE_LIST, size, 0) | ||
DllCall("InitializeProcThreadAttributeList", "Ptr",&PROC_THREAD_ATTRIBUTE_LIST, "UInt",1, "UInt",0, "UPtrP",size) | ||
|
||
DllCall("UpdateProcThreadAttribute", "Ptr",&PROC_THREAD_ATTRIBUTE_LIST, "UInt",0 | ||
, "UPtr",PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, "PtrP",hProcTi, "UPtr",A_PtrSize, "Ptr",0, "Ptr",0) | ||
NumPut(&PROC_THREAD_ATTRIBUTE_LIST, &STARTUPINFOEX + A_PtrSize*9 + 32) | ||
|
||
pwork_dir := (work_dir ? &work_dir : 0) ; doesn't work on one line, v1 bug? | ||
res := DllCall("CreateProcess", "ptr", 0 | ||
, "str", cmd_line | ||
, "ptr", 0, "ptr", 0 | ||
, "int", false | ||
, "uint", CREATE_NEW_CONSOLE|EXTENDED_STARTUPINFO_PRESENT|CREATE_DEFAULT_ERROR_MODE | ||
, "ptr", 0, "ptr", pwork_dir | ||
, "ptr", &STARTUPINFOEX, "ptr", &PROCESS_INFORMATION) | ||
last_err := A_LastError | ||
|
||
if (res) { | ||
DllCall("CloseHandle", "Ptr",NumGet(&PROCESS_INFORMATION + 0)) | ||
DllCall("CloseHandle", "Ptr",NumGet(&PROCESS_INFORMATION + A_PtrSize)) | ||
} | ||
DllCall("DeleteProcThreadAttributeList", "Ptr",&PROC_THREAD_ATTRIBUTE_LIST) | ||
DllCall("CloseHandle", "Ptr",hProcTi) | ||
|
||
return res | ||
} | ||
|
||
GetTrustedInstallerPid() { | ||
static SC_MANAGER_CONNECT := 0x1, SC_MANAGER_ENUMERATE_SERVICE := 0x4 | ||
, SERVICE_QUERY_STATUS := 0x4, SERVICE_START := 0x10, SERVICE_RUNNING := 0x4 | ||
, SC_STATUS_PROCESS_INFO := 0 | ||
|
||
hSC := DllCall("Advapi32.dll\OpenSCManager", "Ptr",0, "Ptr",0, "UInt",SC_MANAGER_ENUMERATE_SERVICE, "Ptr") | ||
if (hSC) { | ||
|
||
hTI := DllCall("Advapi32.dll\OpenService", "Ptr",hSC, "Str","TrustedInstaller", "UInt",SERVICE_QUERY_STATUS|SERVICE_START, "Ptr") | ||
if (hTI) { | ||
size := VarSetCapacity(SERVICE_STATUS_PROCESS, 36, 0) | ||
DllCall("Advapi32.dll\QueryServiceStatusEx", "Ptr",hTI, "UInt",SC_STATUS_PROCESS_INFO, "Ptr",&SERVICE_STATUS_PROCESS, "UInt",size, "UIntP",returnLength:=0) | ||
|
||
if (NumGet(&SERVICE_STATUS_PROCESS + 4, "UInt") != SERVICE_RUNNING) { | ||
DllCall("Advapi32.dll\StartService", "Ptr",hTI, "Ptr",0, "Ptr",0) | ||
Loop { | ||
DllCall("Advapi32.dll\QueryServiceStatusEx", "Ptr",hTI, "UInt",SC_STATUS_PROCESS_INFO, "Ptr",&SERVICE_STATUS_PROCESS, "UInt",size, "UIntP",returnLength:=0) | ||
if (NumGet(&SERVICE_STATUS_PROCESS + 4, "UInt") = SERVICE_RUNNING) | ||
break | ||
Sleep 500 | ||
if (A_Index = 10) | ||
return false | ||
} | ||
} | ||
} | ||
DllCall("Advapi32.dll\CloseServiceHandle", "Ptr",hTI) | ||
} | ||
DllCall("Advapi32.dll\CloseServiceHandle", "Ptr",hSC) | ||
|
||
return hTI ? NumGet(&SERVICE_STATUS_PROCESS + 28, "UInt") : false | ||
} | ||
|
||
ImpersonateProcess(ProcessID) { | ||
static THREAD_DIRECT_IMPERSONATION := 0x0200, SecurityImpersonation := 2 | ||
|
||
if (!ProcessID || !EnablePrivilege()) | ||
return false | ||
|
||
tid := GetProcessThreads(ProcessID, true) | ||
if (!tid) | ||
return false | ||
hThread := DllCall("OpenThread", "UInt",THREAD_DIRECT_IMPERSONATION, "Int",false, "UInt",tid, "Ptr") | ||
if (!hThread) | ||
return false | ||
|
||
size := VarSetCapacity(SECURITY_QUALITY_OF_SERVICE, 12, 0) | ||
NumPut(size, &SECURITY_QUALITY_OF_SERVICE+0, "UInt") | ||
NumPut(SecurityImpersonation, &SECURITY_QUALITY_OF_SERVICE + 4, "Int") | ||
status := DllCall("ntdll.dll\NtImpersonateThread", "Ptr",DllCall("GetCurrentThread", "Ptr"), "Ptr",hThread, "Ptr",&SECURITY_QUALITY_OF_SERVICE) | ||
DllCall("CloseHandle", "Ptr",hThread) | ||
return status = 0 | ||
} | ||
|
||
GetProcessThreads(ProcessID, bFirstOnly := false) { | ||
if !(hSnapshot := DllCall("CreateToolhelp32Snapshot", "uint", 0x4, "uint", ProcessID)) | ||
return false | ||
|
||
NumPut(VarSetCapacity(THREADENTRY32, 28, 0), THREADENTRY32, "uint") | ||
if !(DllCall("Thread32First", "ptr", hSnapshot, "ptr", &THREADENTRY32)) | ||
return false, DllCall("CloseHandle", "ptr", hSnapshot) | ||
|
||
Threads := [] | ||
while (DllCall("Thread32Next", "ptr", hSnapshot, "ptr", &THREADENTRY32)) { | ||
if (NumGet(THREADENTRY32, 12, "uint") = ProcessID) { | ||
if (bFirstOnly) | ||
return NumGet(THREADENTRY32, 8, "uint"), DllCall("CloseHandle", "ptr", hSnapshot) | ||
Threads.Push(NumGet(THREADENTRY32, 8, "uint")) | ||
} | ||
} | ||
return Threads.Count() ? Threads : false, DllCall("CloseHandle", "ptr", hSnapshot) | ||
} | ||
|
||
EnablePrivilege(Name := "SeDebugPrivilege") { | ||
hProc := DllCall("GetCurrentProcess", "UPtr") | ||
If DllCall("Advapi32.dll\LookupPrivilegeValue", "Ptr", 0, "Str", Name, "Int64P", LUID := 0, "UInt") | ||
&& DllCall("Advapi32.dll\OpenProcessToken", "Ptr", hProc, "UInt", 32, "PtrP", hToken := 0, "UInt") { ; TOKEN_ADJUST_PRIVILEGES = 32 | ||
VarSetCapacity(TP, 16, 0) ; TOKEN_PRIVILEGES | ||
, NumPut(1, &TP + 0, "UInt") | ||
, NumPut(LUID, &TP + 4, "Int64") | ||
, NumPut(2, &TP + 12, "UInt") ; SE_PRIVILEGE_ENABLED = 2 | ||
, DllCall("Advapi32.dll\AdjustTokenPrivileges", "Ptr", hToken, "UInt", 0, "Ptr", &TP, "UInt", 0, "Ptr", 0, "Ptr", 0, "UInt") | ||
} | ||
LastError := A_LastError | ||
If (hToken) | ||
DllCall("CloseHandle", "Ptr", hToken) | ||
Return !(ErrorLevel := LastError) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# GUI installer on AutoHotkey | ||
Also open source, written on AHK v1.1 | ||
## Installation / Removal | ||
Download compiled standalone installer for your OS: [64-bit](https://github.com/DartVanya/uwd-oss/raw/main/Installer%20GUI/Compiled/UWD-OSS.exe) / [32-bit](https://github.com/DartVanya/uwd-oss/raw/main/Installer%20GUI/Compiled/UWD-OSS_x86.exe). EXE packed with UPX. | ||
### Installation | ||
Run (accept UAC prompt if needed), click Install. Watermark should gone. | ||
|
||
### Removal | ||
Run (accept UAC prompt if needed), click Uninstall. | ||
|
||
***** | ||
## Features | ||
- No need to restart Explorer or logoff. | ||
- changes are applied immediately by inject/uninject dll into/from Explorer process and force redraw of the desktop | ||
- Script acquire TrustedInstaller privileges when making changes to the registry | ||
- Support both x64 and x86 (note: compiled x86 version cannot run on 64-bit OS) | ||
***** | ||
![installer_window](installer_window.png) | ||
|
||
# Compability | ||
Tested on Windows 11 23H2, removes Test Mode and Safe Mode watermarks.\ | ||
To run installer script from source, clone repo and run UWD-OSS.ahk from admin IDE or from "Run with UI Access" menu (AutoHotkey v1.1 should be installed). |
Oops, something went wrong.