获取进程命令行之四
在此之前我已经写了3篇关于如何获取进程命令行的文章,并且都提供了完整源码,这次也不例外。
由于博客上发表的文章都是在出差之间发布的有些文章没有详细的注释,只把代码贴了出来在这里请大家谅解。以后我会尽量把注释写上让大家更好的阅读我的文章和代码。这次由于项目接近尾声有了点时间就把怎么“获取进程命令行之四”这篇文章的原理给大家说说。
其实几篇文章的原理都很简单,有的都是通过进程环境块PEB来获取进程命令路径的。我们可以通过下面结构可以看出来一:
lkd> dt _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 SpareBool        : UChar
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA '前面有几篇文章我们是通过这个结构来获取进程命令行路径的
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS '今天我们通过此结构获取进程命令行
   +0x014 SubSystemData    : Ptr32 Void
   +0x018 ProcessHeap      : Ptr32 Void
   +0x01c FastPebLock      : Ptr32 _RTL_CRITICAL_SECTION
   +0x020 FastPebLockRoutine : Ptr32 Void
   +0x024 FastPebUnlockRoutine : Ptr32 Void
   +0x028 EnvironmentUpdateCount : Uint4B
   +0x02c KernelCallbackTable : Ptr32 Void
   +0x030 SystemReserved   : [1] Uint4B
   +0x034 AtlThunkSListPtr32 : Uint4B
   +0x038 FreeList         : Ptr32 _PEB_FREE_BLOCK
   +0x03c TlsExpansionCounter : Uint4B
   +0x040 TlsBitmap        : Ptr32 Void
   +0x044 TlsBitmapBits    : [2] Uint4B
   +0x04c ReadOnlySharedMemoryBase : Ptr32 Void
   +0x050 ReadOnlySharedMemoryHeap : Ptr32 Void
   +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
   +0x058 AnsiCodePageData : Ptr32 Void
   +0x05c OemCodePageData  : Ptr32 Void
   +0x060 UnicodeCaseTableData : Ptr32 Void
   +0x064 NumberOfProcessors : Uint4B
   +0x068 NtGlobalFlag     : Uint4B
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER
   +0x078 HeapSegmentReserve : Uint4B
   +0x07c HeapSegmentCommit : Uint4B
   +0x080 HeapDeCommitTotalFreeThreshold : Uint4B
   +0x084 HeapDeCommitFreeBlockThreshold : Uint4B
   +0x088 NumberOfHeaps    : Uint4B
   +0x08c MaximumNumberOfHeaps : Uint4B
   +0x090 ProcessHeaps     : Ptr32 Ptr32 Void
   +0x094 GdiSharedHandleTable : Ptr32 Void
   +0x098 ProcessStarterHelper : Ptr32 Void
   +0x09c GdiDCAttributeList : Uint4B
   +0x0a0 LoaderLock       : Ptr32 Void
   +0x0a4 OSMajorVersion   : Uint4B
   +0x0a8 OSMinorVersion   : Uint4B
   +0x0ac OSBuildNumber    : Uint2B
   +0x0ae OSCSDVersion     : Uint2B
   +0x0b0 OSPlatformId     : Uint4B
   +0x0b4 ImageSubsystem   : Uint4B
   +0x0b8 ImageSubsystemMajorVersion : Uint4B
   +0x0bc ImageSubsystemMinorVersion : Uint4B
   +0x0c0 ImageProcessAffinityMask : Uint4B
   +0x0c4 GdiHandleBuffer  : [34] Uint4B
   +0x14c PostProcessInitRoutine : Ptr32     void 
   +0x150 TlsExpansionBitmap : Ptr32 Void
   +0x154 TlsExpansionBitmapBits : [32] Uint4B
   +0x1d4 SessionId        : Uint4B
   +0x1d8 AppCompatFlags   : _ULARGE_INTEGER
   +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
   +0x1e8 pShimData        : Ptr32 Void
   +0x1ec AppCompatInfo    : Ptr32 Void
   +0x1f0 CSDVersion       : _UNICODE_STRING
   +0x1f8 ActivationContextData : Ptr32 Void
   +0x1fc ProcessAssemblyStorageMap : Ptr32 Void
   +0x200 SystemDefaultActivationContextData : Ptr32 Void
   +0x204 SystemAssemblyStorageMap : Ptr32 Void
   +0x208 MinimumStackCommit : Uint4B
二:
lkd> dt _PEB_LDR_DATA
ntdll!_PEB_LDR_DATA
   +0x000 Length           : Uint4B
   +0x004 Initialized      : UChar
   +0x008 SsHandle         : Ptr32 Void
   +0x00c InLoadOrderModuleList : _LIST_ENTRY --通过这过链表获取路径
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY
   +0x024 EntryInProgress  : Ptr32 Void
三:
lkd> dt _RTL_USER_PROCESS_PARAMETERS
ntdll!_RTL_USER_PROCESS_PARAMETERS
   +0x000 MaximumLength    : Uint4B
   +0x004 Length           : Uint4B
   +0x008 Flags            : Uint4B
   +0x00c DebugFlags       : Uint4B
   +0x010 ConsoleHandle    : Ptr32 Void
   +0x014 ConsoleFlags     : Uint4B
   +0x018 StandardInput    : Ptr32 Void
   +0x01c StandardOutput   : Ptr32 Void
   +0x020 StandardError    : Ptr32 Void
   +0x024 CurrentDirectory : _CURDIR 
   +0x030 DllPath          : _UNICODE_STRING
   +0x038 ImagePathName    : _UNICODE_STRING
   +0x040 CommandLine      : _UNICODE_STRING  --从这里获取进程命令行路径,位置在0x44上
   +0x048 Environment      : Ptr32 Void
   +0x04c StartingX        : Uint4B
   +0x050 StartingY        : Uint4B
   +0x054 CountX           : Uint4B
   +0x058 CountY           : Uint4B
   +0x05c CountCharsX      : Uint4B
   +0x060 CountCharsY      : Uint4B
   +0x064 FillAttribute    : Uint4B
   +0x068 WindowFlags      : Uint4B
   +0x06c ShowWindowFlags  : Uint4B
   +0x070 WindowTitle      : _UNICODE_STRING
   +0x078 DesktopInfo      : _UNICODE_STRING
   +0x080 ShellInfo        : _UNICODE_STRING
   +0x088 RuntimeData      : _UNICODE_STRING
   +0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR好了既然原理知道了那就请看下面完整代码吧!!Option ExplicitPrivate Type CLIENT_ID
    UniqueProcess As Long
    UniqueThread  As Long
End TypePrivate Const SYNCHRONIZE As Long = &H100000
Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000
Private Const PROCESS_VM_READ = &H10
Private Const PROCESS_QUERY_INFORMATION As Long = (&H400)
Private Declare Function NtQueryInformationProcess Lib "ntdll.dll" (ByVal ProcessHandle As Long, _
                                ByVal ProcessInformationClass As PROCESSINFOCLASS, _
                                ByVal ProcessInformation As Long, _
                                ByVal ProcessInformationLength As Long, _
                                ByRef ReturnLength As Long) As Long

解决方案 »

  1.   

    Private Enum PROCESSINFOCLASS
        ProcessBasicInformation = 0
        ProcessQuotaLimits
        ProcessIoCounters
        ProcessVmCounters
        ProcessTimes
        ProcessBasePriority
        ProcessRaisePriority
        ProcessDebugPort
        ProcessExceptionPort
        ProcessAccessToken
        ProcessLdtInformation
        ProcessLdtSize
        ProcessDefaultHardErrorMode
        ProcessIoPortHandlers
        ProcessPooledUsageAndLimits
        ProcessWorkingSetWatch
        ProcessUserModeIOPL
        ProcessEnableAlignmentFaultFixup
        ProcessPriorityClass
        ProcessWx86Information
        ProcessHandleCount
        ProcessAffinityMask
        ProcessPriorityBoost
        ProcessDeviceMap
        ProcessSessionInformation
        ProcessForegroundInformation
        ProcessWow64Information
        ProcessImageFileName
        ProcessLUIDDeviceMapsEnabled
        ProcessBreakOnTermination
        ProcessDebugObjectHandle
        ProcessDebugFlags
        ProcessHandleTracing
        ProcessIoPriority
        ProcessExecuteFlags
        ProcessResourceManagement
        ProcessCookie
        ProcessImageInformation
        MaxProcessInfoClass
    End EnumPrivate Type PROCESS_BASIC_INFORMATION
        ExitStatus As Long 'NTSTATUS
        PebBaseAddress As Long 'PPEB
        AffinityMask As Long 'ULONG_PTR
        BasePriority As Long 'KPRIORITY
        UniqueProcessId As Long 'ULONG_PTR
        InheritedFromUniqueProcessId As Long 'ULONG_PTR
    End TypePrivate Declare Function NtOpenProcess Lib "ntdll.dll" (ByRef ProcessHandle As Long, _
                                    ByVal AccessMask As Long, _
                                    ByRef ObjectAttributes As OBJECT_ATTRIBUTES, _
                                    ByRef ClientID As CLIENT_ID) As LongPrivate Type OBJECT_ATTRIBUTES
        Length As Long
        RootDirectory As Long
        ObjectName As Long
        Attributes As Long
        SecurityDescriptor As Long
        SecurityQualityOfService As Long
    End Type
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, _
                                          ByRef Source As Any, _
                                          ByVal Length As Long)
                                          
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPrivate Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long'判断Nt系列函数调用是否成功
    Private Function NT_SUCCESS(ByVal nStatus As Long) As Boolean
        NT_SUCCESS = (nStatus >= 0)
    End Function'获取进程命令行
    Public Function GetProcessCommandLine(ByVal dwProcessId As Long) As String
        Dim ntStatus As Long
        Dim objBasic As PROCESS_BASIC_INFORMATION
        Dim objFlink As Long
        Dim objPEB As Long, objLdr As Long
        Dim objBaseAddress As Long
        Dim bytName(260 * 2 - 1) As Byte
        Dim strModuleName As String, objName As Long
        Dim objCid As CLIENT_ID
        Dim objOa As OBJECT_ATTRIBUTES
        Dim hProcess As Long
        objOa.Length = Len(objOa)
        objCid.UniqueProcess = dwProcessId
        ntStatus = NtOpenProcess(hProcess, PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, objOa, objCid)
        If hProcess = 0 Then
            GetProcessCommandLine = ""
            Exit Function
        End If
        Dim lngRet As Long, lngReturn As Long
        ntStatus = NtQueryInformationProcess(hProcess, ProcessBasicInformation, VarPtr(objBasic), Len(objBasic), ByVal 0&)
        If (NT_SUCCESS(ntStatus)) Then
            '获取PEB指针
            objPEB = objBasic.PebBaseAddress
            '获取_RTL_USER_PROCESS_PARAMETERS结构指针
            lngRet = ReadProcessMemory(hProcess, ByVal objPEB + &H10, objLdr, 4, ByVal 0&)
            If lngRet <> 1 Then Exit Function
            '获取路径指针
            lngRet = ReadProcessMemory(hProcess, ByVal objLdr + &H44, objName, 4, ByVal 0&)
            If lngRet <> 1 Then Exit Function
            '获取路径
            lngRet = ReadProcessMemory(hProcess, ByVal objName, bytName(0), 260 * 2, ByVal 0&)
            If lngRet <> 1 Then Exit Function
            strModuleName = bytName
            If InStr(strModuleName, """") = 0 Then
                strModuleName = Mid(strModuleName, InStr(strModuleName, Chr(0)) + 1, Len(strModuleName) - InStr(strModuleName, Chr(0)))
                strModuleName = SetPath(strModuleName)
            Else
                strModuleName = Mid(strModuleName, InStr(strModuleName, """"), Len(strModuleName) - InStr(strModuleName, """"))
            End If
            strModuleName = Left(strModuleName & Chr(0), InStr(strModuleName & Chr(0), Chr(0)) - 1)
            GetProcessCommandLine = strModuleName
        End If
        CloseHandle hProcess
    End Function
      

  2.   

    windbg是个好东西好好利用可以发掘出很多好东西出来