-
Notifications
You must be signed in to change notification settings - Fork 78
/
RunAsTI.au3
355 lines (323 loc) · 14.9 KB
/
RunAsTI.au3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=C:\Program Files (x86)\AutoIt3\Icons\au3.ico
#AutoIt3Wrapper_Outfile=RunAsTI32.exe
#AutoIt3Wrapper_Outfile_x64=RunAsTI64.exe
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Comment=Start program with same privileges as TrustedInstaller
#AutoIt3Wrapper_Res_Description=Start program with same privileges as TrustedInstaller
#AutoIt3Wrapper_Res_Fileversion=1.0.0.1
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#AutoIt3Wrapper_Res_File_Add=RunFromToken32.exe, 10, EXE32
#AutoIt3Wrapper_Res_File_Add=RunFromToken64.exe, 10, EXE64
#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 5
#AutoIt3Wrapper_Run_Au3Stripper=y
#Au3Stripper_Parameters=/sf /sv /rm /pe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
; Much of the code is taken from wraithdu's examples
; Modified by Joakim
#include <WinAPI.au3>
#Include <WinAPIEx.au3>
CONST $ERROR_INVALID_SID = 1337
Global Const $tagSTARTUPINFO1 = "dword cb;ptr lpReserved;ptr lpDesktop;ptr lpTitle;dword dwX;dword dwY;dword dwXSize;dword dwYSize;" & _
"dword dwXCountChars;dword dwYCountChars;dword dwFillAttribute;dword dwFlags;ushort wShowWindow;" & _
"ushort cbReserved2;ptr lpReserved2;ptr hStdInput;ptr hStdOutput;ptr hStdError"
Global Const $tagPROCESSINFO1 = "ptr hProcess;ptr hThread;dword dwProcessId;dword dwThreadId"
Global Const $RPC_X_BAD_STUB_DATA = 1783
Global $ghADVAPI32 = DllOpen("advapi32.dll")
If StringInStr(@OSVersion,"XP") Or StringInStr(@OSVersion,"2003") Then
ConsoleWrite("Error: This program is meaningless in XP/2003" & @CRLF)
Exit
EndIf
$Privs = "SeDebugPrivilege,SeAssignPrimaryTokenPrivilege,SeIncreaseQuotaPrivilege,SeImpersonateName"
$PrivsArray = StringSplit($Privs,",")
For $i = 1 To $PrivsArray[0]
;ConsoleWrite("Now setting privilege: " & $PrivsArray[$i] & @CRLF)
_SetPrivilege($PrivsArray[$i])
Next
If $cmdline[0] = 0 Then
$sCmdLine = "cmd.exe"
Else
$sCmdLine = $cmdline[1]
EndIf
$sProcessAsUser = "winlogon.exe"
$dwSessionId = DllCall("kernel32.dll", "dword", "WTSGetActiveConsoleSessionId")
If @error Or $dwSessionId[0] = 0xFFFFFFFF Then
ConsoleWrite("WTSGetActiveConsoleSessionId: " & _WinAPI_GetLastErrorMessage() & @CRLF)
Exit
EndIf
$dwSessionId = $dwSessionId[0]
ConsoleWrite("Running in session: " & $dwSessionId & @CRLF)
Dim $aProcs = ProcessList($sProcessAsUser), $processPID = -1, $ret
For $i = 1 To $aProcs[0][0]
$ret = DllCall("kernel32.dll", "int", "ProcessIdToSessionId", "dword", $aProcs[$i][1], "dword*", 0)
If Not @error And $ret[0] And ($ret[2] = $dwSessionId) Then
$processPID = $aProcs[$i][1]
ExitLoop
EndIf
Next
;ConsoleWrite("Host PID: " & $processPID & @CRLF)
If $processPID = -1 Then
ConsoleWrite("Return 0 ; failed to get winlogon PID in current sessio")
Exit
EndIf
Local $hProc = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", 0x001F0FFF, "int", 0, "dword", $processPID)
If @error Or Not $hProc[0] Then
ConsoleWrite("OpenProcess: " & _WinAPI_GetLastErrorMessage() & @CRLF)
Exit
EndIf
$hProc = $hProc[0]
$hToken = DllCall($ghADVAPI32, "int", "OpenProcessToken", "ptr", $hProc, "dword", 0x2, "ptr*", 0)
If @error Or Not $hToken[0] Then
ConsoleWrite("OpenProcessToken: " & _WinAPI_GetLastErrorMessage() & @CRLF)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc)
Exit
EndIf
$hToken = $hToken[3]
$hDupToken = DllCall($ghADVAPI32, "int", "DuplicateTokenEx", "ptr", $hToken, "dword", 0x1F0FFF, "ptr", 0, "int", 1, "int", 1, "ptr*", 0)
If @error Or Not $hDupToken[0] Then
ConsoleWrite("DuplicateTokenEx: " & _WinAPI_GetLastErrorMessage() & @CRLF)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hToken)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc)
Exit
EndIf
;Identify correct module
If @OSArch = "X86" Then
$sModuleName = @TempDir&"\RunFromToken32.exe"
$TargetRCDataName = "EXE32"
Else
$sModuleName = @TempDir&"\RunFromToken64.exe"
$TargetRCDataName = "EXE64"
EndIf
;Get module from resource
_WriteFileFromResource($sModuleName,$TargetRCDataName)
If @error Or FileExists($sModuleName)=0 Then
ConsoleWrite("Error finding module" & @CRLF)
FileDelete($sModuleName)
Exit
EndIf
;Set command line
$sCmdLine = $sModuleName & " trustedinstaller.exe " & $dwSessionId & " " & $sCmdLine
;Start service
run("cmd.exe /c sc start trustedinstaller", "", @SW_HIDE, 0x10000)
$hDupToken = $hDupToken[6]
$pEnvBlock = _GetEnvironmentBlock($sProcessAsUser, $dwSessionId) ; target process
$dwCreationFlags = BitOR($NORMAL_PRIORITY_CLASS, $CREATE_NEW_CONSOLE)
If $pEnvBlock Then $dwCreationFlags = BitOR($dwCreationFlags, $CREATE_UNICODE_ENVIRONMENT)
$SI = DllStructCreate($tagSTARTUPINFO1)
DllStructSetData($SI, "cb", DllStructGetSize($SI))
$PI = DllStructCreate($tagPROCESSINFO1)
$sDesktop = "winsta0\default"
$lpDesktop = DllStructCreate("wchar[" & StringLen($sDesktop) + 1 & "]")
DllStructSetData($lpDesktop, 1, $sDesktop)
DllStructSetData($SI, "lpDesktop", DllStructGetPtr($lpDesktop))
_WinAPI_SetLastError(0)
$ret = DllCall($ghADVAPI32, "bool", "CreateProcessWithTokenW", "handle", $hDupToken, "dword", 0, "ptr", 0, "wstr", $sCmdLine, "dword", $dwCreationFlags, "ptr", $pEnvBlock, "wstr", @WindowsDir, "ptr", DllStructGetPtr($SI), "ptr", DllStructGetPtr($PI))
;If @error or Not $ret[0] Then
If Not $ret[0] and _WinAPI_GetLastError() = $RPC_X_BAD_STUB_DATA Then
ConsoleWrite("Error in CreateProcessWithTokenW: " & _WinAPI_GetLastErrorMessage() & @CRLF)
If $pEnvBlock Then DllCall("userenv.dll", "int", "DestroyEnvironmentBlock", "ptr", $pEnvBlock)
$pEnvBlock = 0
$ret = DllCall($ghADVAPI32, "bool", "CreateProcessWithTokenW", "handle", $hDupToken, "dword", 1, "ptr", 0, "wstr", $sCmdLine, "dword", $dwCreationFlags, "ptr", $pEnvBlock, "wstr", @WindowsDir, "ptr", DllStructGetPtr($SI), "ptr", DllStructGetPtr($PI))
ConsoleWrite("CreateProcessWithTokenW=" & $ret[0] & " error=" & @error & " LastError=" & _WinAPI_GetLastError() & @CRLF)
If @error or Not $ret[0] Then
$ret = DllCall($ghADVAPI32, "int", "CreateProcessAsUserW", "handle", $hDupToken, "ptr", 0, "wstr", $sCmdLine, "ptr", 0, "ptr", 0, "int", 0, "dword", $dwCreationFlags, "ptr", $pEnvBlock, "ptr", 0, "ptr", DllStructGetPtr($SI), "ptr", DllStructGetPtr($PI))
If Not @error And $ret[0] Then
ConsoleWrite("Success CreateProcessAsUserW created new process: " & DllStructGetData($PI, "dwProcessId") & @CRLF)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", DllStructGetData($PI, "hThread"))
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", DllStructGetData($PI, "hProcess"))
Else
ConsoleWrite("Error in CreateProcessAsUserW: " & _WinAPI_GetLastErrorMessage() & @CRLF)
EndIf
EndIf
Else
ConsoleWrite("Success CreateProcessWithTokenW created new process: " & DllStructGetData($PI, "dwProcessId") & @CRLF)
EndIf
If $pEnvBlock Then DllCall("userenv.dll", "int", "DestroyEnvironmentBlock", "ptr", $pEnvBlock)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hDupToken)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hToken)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc)
FileDelete($sModuleName)
Exit
Func _GetEnvironmentBlock($sProcess, $dwSession)
Local Const $dwAccess = BitOR(0x2, 0x8) ; TOKEN_DUPLICATE | TOKEN_QUERY
; get PID of process in current session
Local $aProcs = ProcessList($sProcess), $processPID = -1, $ret = 0
For $i = 1 To $aProcs[0][0]
$ret = DllCall("kernel32.dll", "int", "ProcessIdToSessionId", "dword", $aProcs[$i][1], "dword*", 0)
If Not @error And $ret[0] And ($ret[2] = $dwSession) Then
$processPID = $aProcs[$i][1]
ExitLoop
EndIf
Next
If $processPID = -1 Then Return 0 ; failed to get PID
; open process
Local $hProc = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", 0x02000000, "int", 0, "dword", $processPID)
If @error Or Not $hProc[0] Then Return 0
$hProc = $hProc[0]
; open process token
$hToken = DllCall($ghADVAPI32, "int", "OpenProcessToken", "ptr", $hProc, "dword", $dwAccess, "ptr*", 0)
If @error Or Not $hToken[0] Then
ConsoleWrite("OpenProcessToken: " & _WinAPI_GetLastErrorMessage() & @CRLF)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc)
Return 0
EndIf
$hToken = $hToken[3]
; create a new environment block
Local $pEnvBlock = DllCall("userenv.dll", "int", "CreateEnvironmentBlock", "ptr*", 0, "ptr", $hToken, "int", 1)
If Not @error And $pEnvBlock[0] Then $ret = $pEnvBlock[1]
; close handles
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hToken)
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc)
Return $ret
EndFunc
Func _SetPrivilege($Privilege)
Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes"
Local $count = 1
Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & $count * 12 & "]" ; count of LUID structs * sizeof LUID struct
Local $SE_PRIVILEGE_ENABLED = 0x2
Local $curProc = DllCall("kernel32.dll", "ptr", "GetCurrentProcess")
Local $call = DllCall("advapi32.dll", "int", "OpenProcessToken", "ptr", $curProc[0], "dword", $TOKEN_ALL_ACCESS, "ptr*", "")
If Not $call[0] Then Return False
Local $hToken = $call[3]
$call = DllCall("advapi32.dll", "int", "LookupPrivilegeValue", "str", "", "str", $Privilege, "int64*", "")
Local $iLuid = $call[3]
Local $TP = DllStructCreate($tagTOKENPRIVILEGES)
Local $TPout = DllStructCreate($tagTOKENPRIVILEGES)
Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB"))
DllStructSetData($TP, "PrivilegeCount", $count)
DllStructSetData($LUID, "Luid", $iLuid)
DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED)
$call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", DllStructGetSize($TPout), "ptr", DllStructGetPtr($TPout), "dword*", 0)
$lasterror = _WinAPI_GetLastError()
If $lasterror <> 0 Then
ConsoleWrite("AdjustTokenPrivileges for "&$Privilege&": " & _WinAPI_GetLastErrorMessage() & @CRLF)
If $lasterror = 1300 Then
_LsaAddAccountRights(@UserName, $Privilege)
If not @error then
ConsoleWrite("Reboot required for changes to take effect" & @CRLF)
Else
ConsoleWrite("Warning: The right was probably not added correctly to your account" & @CRLF)
Return SetError(1,0,0)
EndIf
EndIf
EndIf
DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hToken)
Return ($call[0] <> 0) ; $call[0] <> 0 is success
EndFunc
Func _LsaAddAccountRights($sName, $sRight)
Local $hPolicy, $tSid, $pSid, $iLength, $iSysError
Local $tUnicode, $pUnicode, $iResult, $tRight, $pRight
$tSid = _LookupAccountName($sName)
$pSid = DllStructGetPtr($tSid)
If Not _IsValidSid($pSid) Then Return SetError(@error, 0, 0)
$hPolicy = _LsaOpenPolicy(0x811)
$iLength = StringLen($sRight) * 2
$tRight = DllStructCreate("wchar[" & $iLength & "]")
$pRight = DllStructGetPtr($tRight)
DllStructSetData($tRight, 1, $sRight)
$tUnicode = DllStructCreate("ushort Length;ushort MemSize;ptr wBuffer")
$pUnicode = DllStructGetPtr($tUnicode)
DllStructSetData($tUnicode, "Length", $iLength)
DllStructSetData($tUnicode, "MemSize", $iLength + 2)
DllStructSetData($tUnicode, "wBuffer", $pRight)
$iResult = DllCall("advapi32.dll", "dword", "LsaAddAccountRights", _
"hWnd", $hPolicy, "ptr", $pSid, _
"ptr", $pUnicode, "ulong", 1)
; ConsoleWrite("LsaAddAccountRights Dec " & _LsaNtStatusToWinError($iResult[0]) & @CRLF)
ConsoleWrite("LsaAddAccountRights 0x" & Hex(_LsaNtStatusToWinError($iResult[0]),8) & @CRLF)
$tSid = 0
_LsaClose($hPolicy)
$iSysError = _LsaNtStatusToWinError($iResult[0])
Return SetError($iSysError, 0, $iSysError = 0)
EndFunc
Func _LsaOpenPolicy($iAccess)
Local $hPolicy, $tLsaAttr, $pLsaAttr
$tLsaAttr = DllStructCreate("ulong;hWnd;ptr;ulong;ptr[2]")
$pLsaAttr = DllStructGetPtr($tLsaAttr)
$hPolicy = DllCall("advapi32.dll", "ulong", "LsaOpenPolicy", _
"ptr", 0, "ptr", $pLsaAttr, "int", $iAccess, "hWnd*", 0)
Return SetError(_LsaNtStatusToWinError($hPolicy[0]), 0, $hPolicy[4])
EndFunc
Func _LsaClose($hPolicy)
Local $iResult
$iResult = DllCall("advapi32.dll", "ulong", "LsaClose", "hWnd", $hPolicy)
Return SetError(_LsaNtStatusToWinError($iResult[0]), 0, $iResult[0] = 0)
EndFunc
Func _LookupAccountName($sName, $sSystem = "")
Local $iResult, $tSid, $pSid, $tDomain, $pDomain
$iResult = DllCall("advapi32.dll", "int", "LookupAccountName", _
"str", $sSystem, "str", $sName, _
"ptr", 0, "int*", 0, "ptr", 0, "int*", 0, "int*", 0)
If $iResult[4] = 0 Then Return SetError($ERROR_INVALID_SID, 0, 0)
$tSid = DllStructCreate("ubyte[" & $iResult[4] & "]")
$tDomain = DllStructCreate("ubyte[" & $iResult[6] & "]")
$pSid = DllStructGetPtr($tSid)
$pDomain = DllStructGetPtr($tDomain)
$iResult = DllCall("advapi32.dll", "int", "LookupAccountName", _
"str", $sSystem ,"str", $sName, _
"ptr", $pSid, "int*", $iResult[4], _
"ptr", $pDomain, "int*", $iResult[6], "int*", 0)
Return SetError(Not $iResult[0], $iResult[7], $tSid)
EndFunc
Func _IsValidSid($pSid)
Local $iResult
$iResult = DllCall("advapi32.dll", "int", "IsValidSid", "ptr", $pSid)
If $iResult[0] Then Return SetError(0, 0, True)
Return SetError($ERROR_INVALID_SID, 0, 0)
EndFunc
Func _LsaNtStatusToWinError($iNtStatus)
Local $iSysError
$iSysError = DllCall("Advapi32.dll", "ulong", "LsaNtStatusToWinError", "dword", $iNtStatus)
Return $iSysError[0]
EndFunc
Func NT_SUCCESS($status)
If 0 <= $status And $status <= 0x7FFFFFFF Then
Return True
Else
Return False
EndIf
EndFunc
Func _WriteFileFromResource($OutPutName,$ResName)
If FileExists($OutPutName) Then FileDelete($OutPutName)
If Not FileExists($OutPutName) Then
; Local $hResource = _WinAPI_FindResource(0, 10, '#'&$RCDataNumber)
Local $hResource = _WinAPI_FindResource(0, 10, $ResName)
If @error Or $hResource = 0 Then
ConsoleWrite("Error: Resource not found" & @CRLF)
Return SetError(1, 0, 0)
EndIf
Local $iSize = _WinAPI_SizeOfResource(0, $hResource)
If @error Or $iSize = 0 Then
ConsoleWrite("Error: Resource size not retrieved" & @CRLF)
Return SetError(1, 0, 0)
EndIf
Local $hData = _WinAPI_LoadResource(0, $hResource)
If @error Or $hData = 0 Then
ConsoleWrite("Error: Resource could not be loaded" & @CRLF)
Return SetError(1, 0, 0)
EndIf
Local $pData = _WinAPI_LockResource($hData)
If @error Or $pData = 0 Then
ConsoleWrite("Error: Resource not locked" & @CRLF)
Return SetError(1, 0, 0)
EndIf
Local $tBuffer=DllStructCreate('align 1;byte STUB['&$iSize&']', $pData)
Local $DriverData = DllStructGetData($tBuffer,'STUB')
If @error or $DriverData = "" Then
ConsoleWrite("Error: Could not put driver data into buffer" & @CRLF)
Return SetError(1, 0, 0)
EndIf
Local $hFile = FileOpen($OutPutName,2)
If Not FileWrite($hFile,$DriverData) Then
ConsoleWrite("Error: Could not write driver file" & @CRLF)
Return SetError(1, 0, 0)
EndIf
FileClose($hFile)
Return 1
Else
Return 1
EndIf
EndFunc