txm888 发表于 2016-5-23 09:28:49

P版,你好,关于CreateSystemProcess函数创建进程的问题(已解决)

本帖最后由 txm888 于 2016-5-23 16:53 编辑

不好意思,内存占用是自己的obj对象未释放造成,P版代码无任何问题,我脸快扫地了。


P版,你好,近期在使用你写的个以指定身份创建进程的函数,发现在2008 64位下执行,创建完子进程后,子进程退出了,但内存即一直占用中。
循环使用,内存会越来越大,而在win7 64位中没这现象,请帮看下,谢谢!Func _RunSystemFile($File = "")
        If $File = "" Then Return 0

        Local $tProcessInfo = _SeCreateHighSystemProcess($File)
        Local $iError = @error
        Local $iExtended = @extended

        If IsDllStruct($tProcessInfo) Then
                ;MsgBox(48, "OK", "Done", 2)

                Local $hProcess = DllStructGetData($tProcessInfo, "hProcess")                ; 进程句柄。
                Local $hThread = DllStructGetData($tProcessInfo, "hThread")                ; 主线程句柄。
                Local $iProcessID = DllStructGetData($tProcessInfo, "ProcessID")        ; 进程ID。
                Local $iThreadID = DllStructGetData($tProcessInfo, "ThreadID")                ; 主线程ID。

                ;TODO: do something...

                ;关闭进、线程句柄。
                DllCall("Kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
                DllCall("Kernel32.dll", "bool", "CloseHandle", "handle", $hThread)

                Return $iProcessID
                Else
                ;MsgBox(16, "Error", StringFormat("error=%d, extended=%d\n", $iError, $iExtended))
                Return 0
        EndIf
EndFunc

Func _SeImpersonateHighSystemContext($iImpersonationLevel, $iDesiredAccess)
        Local $iResult

        ; get system id.
        ; =========================================================================================================================

        $iResult = DllCall("Ntdll.dll", "ulong", "CsrGetProcessId")

        Local $iProcessID = $iResult
        If $iProcessID == 0 Then Return SetError(1359, 1, 0) ; 1359=ERROR_INTERNAL_ERROR

        $iResult = DllCall("Ntdll.dll", "long", "NtQuerySystemInformation", "ulong", 5, "ptr", 0, "ulong", 0, "ulong*", 0)
        If $iResult == 0 Then Return SetError($iResult, 2, 0)

        Local $tBuffer = DllStructCreate("ubyte Data[" & $iResult & "]")
        Local $pBuffer = DllStructGetPtr($tBuffer)

        $iResult = DllCall("Ntdll.dll", "long", "NtQuerySystemInformation", "ulong", 5, "ptr", $pBuffer, "ulong", $iResult, "ulong*", 0)
        If $iResult < 0 Then Return SetError($iResult, 3, 0)

        Local $iOffset, $tProcessInfo, $iSystemID

        Local Const $tagVM_COUNTERS = "ULONG_PTR PeakVirtualSize;ULONG_PTR VirtualSize;DWORD PageFaultCount;ULONG_PTR PeakWorkingSetSize;ULONG_PTR WorkingSetSize;ULONG_PTR QuotaPeakPagedPoolUsage;ULONG_PTR QuotaPagedPoolUsage;ULONG_PTR QuotaPeakNonPagedPoolUsage;ULONG_PTR QuotaNonPagedUsage;ULONG_PTR PagefileUsage;ULONG_PTR PeakPagefileUsage;"
       
        Local Const $tagIO_COUNTERS = "INT64 ReadOperationCount;INT64 WriteOperationCount;INT64 OtherOperationCount;INT64 ReadTransferCount;INT64 WriteTransferCount;INT64 OtherTransferCount;"

        If @AutoItX64 Then
                Local $tagSYSTEM_THREAD = "INT64 KernelTime;INT64 UserTime;INT64 CreateTime;ULONG WaitTime;ULONG_PTR Reserved3;PTR StartAddress;ULONG_PTR UniqueProcessId;ULONG_PTR UniqueThreadId;ULONG Priority;ULONG BasePriority;ULONG ContextSwitchCount;ULONG State;ULONG WaitReason;"
        Else
                Local $tagSYSTEM_THREAD = "INT64 KernelTime;INT64 UserTime;INT64 CreateTime;ULONG WaitTime;PTR StartAddress;ULONG_PTR UniqueProcessId;ULONG_PTR UniqueThreadId;ULONG Priority;ULONG BasePriority;ULONG ContextSwitchCount;ULONG State;ULONG WaitReason;"
        EndIf

        Local Const $tagSYSTEM_PROCESS_INFORMATION = "ULONG NextEntryOffset;ULONG NumberOfThreads;INT64 Reserved;INT64 CreateTime;INT64 UserTime;INT64 KernelTime;WORD Length;WORD MaximumLength;PTR ImageName;ULONG BasePriority;ULONG_PTR ProcessId;ULONG_PTR InheritedFromProcessId;ULONG HandleCount;ULONG Reserved;ULONG PrivatePageCount;" & $tagVM_COUNTERS & $tagIO_COUNTERS & $tagSYSTEM_THREAD

        While 1
                $tProcessInfo = DllStructCreate($tagSYSTEM_PROCESS_INFORMATION, $pBuffer)
                $iOffset = DllStructGetData($tProcessInfo, "NextEntryOffset")

                If DllStructGetData($tProcessInfo, "ProcessId") == $iProcessID Then
                        $iSystemID = DllStructGetData($tProcessInfo, "UniqueThreadId")

                        ExitLoop
                Else
                        If $iOffset Then
                                $pBuffer += $iOffset
                        Else
                                ExitLoop
                        EndIf
                EndIf
        WEnd
        If $iSystemID = 0 Then Return SetError(1359, 4, 0)
        ; =========================================================================================================================

        ; enable Debug privilege.
        ; =========================================================================================================================
        $iResult = DllCall("Advapi32.dll", "bool", "OpenProcessToken", "handle", -1, "dword", 0x0020, "handle*", 0)

        Local $hToken = $iResult
        If $hToken = 0 Then Return SetError(_s2er(0), 5, 0)

        Local $tTokenPrivileges = DllStructCreate("DWORD PrivilegeCount;DWORD LowPart;LONG HighPart;DWORD Attributes")
        Local $pTokenPrivileges = DllStructGetPtr($tTokenPrivileges)

        DllStructSetData($tTokenPrivileges, "PrivilegeCount", 1)
        DllStructSetData($tTokenPrivileges, "Attributes", 2) ; 2=SE_PRIVILEGE_ENABLED

        $iResult = DllCall("Advapi32.dll", "bool", "LookupPrivilegeValueW", "ptr", 0, "wstr", "SeDebugPrivilege", "ptr", DllStructGetPtr($tTokenPrivileges, "LowPart"))

        If Not $iResult Then
                ; handle error
        EndIf

        DllCall("Kernel32.dll", "none", "SetLastError", "dword", 0)
        DllCall("Advapi32.dll", "bool", "AdjustTokenPrivileges", "handle", $hToken, "bool", 0, "ptr", $pTokenPrivileges, "dword", 0, "ptr", 0, "ptr", 0)

        $iResult = DllCall("Kernel32.dll", "dword", "GetLastError")

        If $iResult = 1300 Then ; 1300=ERROR_NOT_ALL_ASSIGNED
                ; not all privileges are assigned.
        EndIf
        DllCall("Kernel32.dll", "bool", "CloseHandle", "handle", $hToken)
        ; =========================================================================================================================

        ; impersonate security context.
        ; =========================================================================================================================
        $iResult = DllCall("Kernel32.dll", "handle", "OpenThread", "dword", 0x0200, "bool", 0, "dword", $iSystemID)

        Local $hThread = $iResult
        If $hThread = 0 Then Return SetError(_s2er(0), 6, 0)

        Local $tSecurityQos = DllStructCreate("DWORD Length;DWORD ImpersonationLevel;BOOLEAN ContextTrackingMode;BOOLEAN EffectiveOnly")
        Local $pSecurityQos = DllStructGetPtr($tSecurityQos)

        DllStructSetData($tSecurityQos, "Length", DllStructGetSize($tSecurityQos))
        DllStructSetData($tSecurityQos, "ImpersonationLevel", $iImpersonationLevel)
        DllStructSetData($tSecurityQos, "ContextTrackingMode", 0)
        DllStructSetData($tSecurityQos, "EffectiveOnly", 0)

        $iResult = DllCall("Ntdll.dll", "long", "NtImpersonateThread", "handle", -2, "handle", $hThread, "ptr", $pSecurityQos)

        DllCall("Kernel32.dll", "bool", "CloseHandle", "handle", $hThread)

        If $iResult < 0 Then Return SetError($iResult, 7, 0)
        ; =========================================================================================================================

        ; open impersonation token.
        $iResult = DllCall("Advapi32.dll", "bool", "OpenThreadToken", "handle", -2, "dword", $iDesiredAccess, "boolean", 0, "handle*", 0)

        If $iResult Then
                Return $iResult
        Else
                Return SetError(_s2er(0), 8, 0)
        EndIf
EndFunc        ;==>_SeImpersonateSystemContext

Func _SeCreateHighSystemProcess($sCommandLine, $sWorkingDir = @WorkingDir, $iShowCmd = @SW_SHOWNORMAL) ;与Service.au3的函数重名,改名处理
        Local $hImpersonationToken = _SeImpersonateHighSystemContext(2, 0x0F01FF)
        If $hImpersonationToken = 0 Then Return SetError(@error, @extended, 0)

        Local $iResult

        ; enable privileges
        ; =========================================================================================================================
        Local $tTokenPrivileges = DllStructCreate("DWORD;DWORD;LONG;DWORD;DWORD;LONG;DWORD")
        Local $pTokenPrivileges = DllStructGetPtr($tTokenPrivileges)

        DllStructSetData($tTokenPrivileges, 1, 1)
        DllStructSetData($tTokenPrivileges, 4, 2) ; 2=SE_PRIVILEGE_ENABLED
        DllStructSetData($tTokenPrivileges, 7, 2) ; 2=SE_PRIVILEGE_ENABLED

        $iResult = DllCall("Advapi32.dll", "bool", "LookupPrivilegeValueW", "ptr", 0, "wstr", "SeAssignPrimaryTokenPrivilege", "ptr", DllStructGetPtr($tTokenPrivileges, 2))
        $iResult = DllCall("Advapi32.dll", "bool", "LookupPrivilegeValueW", "ptr", 0, "wstr", "SeTcbPrivilege", "ptr", DllStructGetPtr($tTokenPrivileges, 5))

        If Not $iResult Then
                ; handle error
        EndIf

        DllCall("Kernel32.dll", "none", "SetLastError", "dword", 0)
        DllCall("Advapi32.dll", "bool", "AdjustTokenPrivileges", "handle", $hImpersonationToken, "bool", 0, "ptr", $pTokenPrivileges, "dword", 0, "ptr", 0, "ptr", 0)

        $iResult = DllCall("Kernel32.dll", "dword", "GetLastError")

        If $iResult = 1300 Then ; 1300=ERROR_NOT_ALL_ASSIGNED
                ; not all privileges are assigned.
        EndIf
        ; =========================================================================================================================

        ; adjust session ID
        ; =========================================================================================================================
        $iResult = DllCall("Kernel32.dll", "dword", "WTSGetActiveConsoleSessionId")
        $iResult = DllCall("Advapi32.dll", "bool", "SetTokenInformation", "handle", $hImpersonationToken, "ulong", 12, "dword*", $iResult, "dword", 4)
        If Not $iResult Then
                ; handle error
        EndIf
        ; =========================================================================================================================

        $iResult = DllCall("Advapi32.dll", "bool", "GetTokenInformation", "handle", $hImpersonationToken, "ulong", 9, "dword*", 0, "dword", 4, "dword*", 0)
        If $iResult <> 2 Then ; 2=SecurityImpersonation
                ; handle error
        EndIf

        $iResult = DllCall("Advapi32.dll", "bool", "DuplicateTokenEx", "handle", $hImpersonationToken, "dword", 0x0F01FF, "ptr", 0, "dword", 0, "dword", 1, "handle*", 0)

        Local $hPrimaryToken = $iResult
        If $hPrimaryToken = 0 Then Return SetError(_s2er(0), 9, 0)

        If $sWorkingDir == "" Then $sWorkingDir = @WorkingDir

        Local Const $tagPROCESS_INFORMATION = "HANDLE hProcess;HANDLE hThread;DWORD ProcessID;DWORD ThreadID"
        Local Const $tagSTARTUPINFO = "DWORD Length;PTR Reserved;PTR Desktop;PTR Title;DWORD X;DWORD Y;DWORD XSize;DWORD YSize;DWORD XCountChars;DWORD YCountChars;DWORD FillAttributes;DWORD Flags;WORD ShowWindow;WORD Reserved2;PTR Reserved3;HANDLE StdInput;HANDLE StdOutput;HANDLE StdError"

        Local $tProcessInfo = DllStructCreate($tagPROCESS_INFORMATION)
        Local $pProcessInfo = DllStructGetPtr($tProcessInfo)

        Local $tStartupInfo = DllStructCreate($tagSTARTUPINFO)
        Local $pStartupInfo = DllStructGetPtr($tStartupInfo)

        DllStructSetData($tStartupInfo, "Length", DllStructGetSize($tStartupInfo))
       
        If @NumParams > 2 Then
                If IsKeyword($iShowCmd) Then $iShowCmd = @SW_SHOWNORMAL

                DllStructSetData($tStartupInfo, "ShowWindow", $iShowCmd)
                DllStructSetData($tStartupInfo, "Flags", 1)
        EndIf

        $iResult = DllCall("Advapi32.dll", "bool", "CreateProcessAsUserW", "handle", $hPrimaryToken, "ptr", 0, "wstr", $sCommandLine, "ptr", 0, "ptr", 0, "bool", 0, "dword", 0, "ptr", 0, "wstr", $sWorkingDir, "ptr", $pStartupInfo, "ptr", $pProcessInfo)

        Local $iError = _s2er($iResult)

        DllCall("Advapi32.dll", "bool", "RevertToSelf")
        DllCall("Kernel32.dll", "bool", "CloseHandle", "handle", $hImpersonationToken)
        DllCall("Kernel32.dll", "bool", "CloseHandle", "handle", $hPrimaryToken)

        If $iResult Then
                Return $tProcessInfo
        Else
                Return SetError($iError, 10, 0)
        EndIf
EndFunc        ;==>_SeCreateSystemProcess

Func _s2er($iResult)
        If $iResult Then
                Return 0
        Else
                $iResult = DllCall("Kernel32.dll", "long", "GetLastError")

                Return $iResult
        EndIf
EndFunc        ;==>s2er

131738 发表于 2016-5-23 09:51:29

txm888 发表于 2016-5-23 10:01:09

回复 2# 131738


    老大,你回复的是什么意思?{:face (280):}

131738 发表于 2016-5-23 11:55:48

本帖最后由 131738 于 2016-5-23 11:57 编辑

告诉你 p 版好像一年多没来了吧

txm888 发表于 2016-5-23 13:02:53

回复 4# 131738


    哦,他可能忙其它去了,难道他在忙开书法培训班?

haijie1223 发表于 2016-5-27 15:30:44

回复 5# txm888


    估计是忙于造人计划~{:face (310):}

xiayingming 发表于 2016-5-29 06:58:41

表示下,看不懂

lin6051 发表于 2016-6-1 16:10:11

回复 1# txm888


创建系统级进程 无法操作注册表 问题还没解决呢

penguinl 发表于 2017-6-15 22:23:00

正好有这个需要。感谢P版!

wnscl27 发表于 2017-12-16 16:52:03

搞不定,不知道怎么搞
页: [1]
查看完整版本: P版,你好,关于CreateSystemProcess函数创建进程的问题(已解决)