NtQuerySystemInformation #SystemProcessIdInformation

Just starting out? Need help? Post your questions and find answers here.
User avatar
Teddy Rogers
User
User
Posts: 98
Joined: Sun Feb 23, 2014 2:05 am
Location: Australia
Contact:

NtQuerySystemInformation #SystemProcessIdInformation

Post by Teddy Rogers »

I am trying to port some NtQuerySystemInformation code to PB because I am trying to get the filename and directory path of processid's protected by Windows process rights so using GetModuleFileNameEx is not helpful. An example of this would be "taskmgr.exe".

You can find what I am trying to replicate in PB here...

http://wj32.org/wp/2010/03/30/get-the-i ... and-above/

Microsoft has some information on NtQuerySystemInformation here...

http://msdn.microsoft.com/en-us/library ... s.85).aspx

My poor PB code currently looks like this, see below. This is my first experience with working with structures in PB so please point out all my glaring mistakes. Obviously there is no procedure return because I haven't got that far yet. Thanks for any help...

Code: Select all

Procedure.s GetProcessImageFileName()
  Protected ProcessID
  
  #SystemProcessIdInformation = 88
  
  Structure ProcessFileName
    ProcessId.l
    ImageName_Length.l
    ImageName_MaximumLength.l
    ImageName_Buffer.l
  EndStructure
  
Dim processIdInfo.ProcessFileName(4096)
  
If GetWindowThreadProcessId_(hWnd,@ProcessID)

  ntdlllib=OpenLibrary(#PB_Any, "ntdll.dll")
  If ntdlllib
    NtQuerySystemInformation=GetFunction(ntdlllib, "NtQuerySystemInformation")
    If NtQuerySystemInformation
      
      processIdInfo(0)\ProcessId = ProcessID
      processIdInfo(0)\ImageName_Length = 0
      processIdInfo(0)\ImageName_MaximumLength = 256
      processIdInfo(0)\ImageName_Buffer = 512
      
      Status = CallFunctionFast(NtQuerySystemInformation, #SystemProcessIdInformation, @processIdInfo, SizeOf(processIdInfo), #Null)
      Debug Status
      Debug (processIdInfo(0)\ImageName_Buffer)
      
      EndIf
    EndIf
  EndIf

CloseLibrary(ntdlllib)

  ProcedureReturn FileName$
EndProcedure
Ted.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

Try this:

Code: Select all

Prototype.i protoGetProcessImageFileName(hProcess, lpImageFileName, nSize)
Global GetProcessImageFileName.protoGetProcessImageFileName

Prototype.b protoQueryFullProcessImageName(hProcess, dwFlags, lpExeName, lpdwSize)
Global QueryFullProcessImageName.protoQueryFullProcessImageName

Procedure.b AdjustCurrentProcessPrivilege()
  Result.b = #False

  If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @TokenHandle)
    lpLuid.LUID

    If LookupPrivilegeValue_(#Null, #SE_DEBUG_NAME, @lpLuid)
      NewState.TOKEN_PRIVILEGES

      With NewState
        \PrivilegeCount = 1
        \Privileges[0]\Luid\LowPart = lpLuid\LowPart
        \Privileges[0]\Luid\HighPart = lpLuid\HighPart
        \Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
      EndWith
      Result = AdjustTokenPrivileges_(TokenHandle, #False, @NewState, SizeOf(TOKEN_PRIVILEGES), @PreviousState.TOKEN_PRIVILEGES, @ReturnLength)
    EndIf
    CloseHandle_(TokenHandle)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetProcessPath(hProcess)
  Result.s = ""

  If hProcess
    Select OSVersion()
      Case #PB_OS_Windows_XP
        psapi = OpenLibrary(#PB_Any, "psapi.dll")

        If IsLibrary(psapi)
          GetProcessImageFileName = GetFunction(psapi, "GetProcessImageFileNameA")

          If GetProcessImageFileName
            nSize = #MAX_PATH
            Dim lpBuffer.c(nSize)
            lpImageFileName.s = Space(nSize)
            GetProcessImageFileName(hProcess, @lpImageFileName, nSize)
            BufferLength = GetLogicalDriveStrings_(nSize, @lpBuffer(0))

            Repeat
              lpDeviceName.s = ""

              While lpBuffer(rtnCount)
                lpDeviceName + Chr(lpBuffer(rtnCount))
                rtnCount + 1
              Wend
              lpDeviceName = Left(lpDeviceName, Len(lpDeviceName) - 1)
              lpTargetPath.s = Space(nSize)
              QueryDosDevice_(lpDeviceName, @lpTargetPath, nSize)

              If Left(lpImageFileName, Len(lpTargetPath)) = lpTargetPath
                Result = Trim(ReplaceString(lpImageFileName, lpTargetPath, lpDeviceName))
                Break
              EndIf
              rtnCount + 1
            Until rtnCount >= BufferLength
          EndIf
          CloseLibrary(psapi)
        EndIf
      Case #PB_OS_Windows_Vista, #PB_OS_Windows_7
        kernel32 = OpenLibrary(#PB_Any, "kernel32.dll")

        If IsLibrary(kernel32)
          QueryFullProcessImageName = GetFunction(kernel32, "QueryFullProcessImageNameA")

          If QueryFullProcessImageName
            lpdwSize = #MAX_PATH
            lpExeName.s = Space(lpdwSize)
            QueryFullProcessImageName(hProcess, 0, @lpExeName, @lpdwSize)
            Result = Trim(lpExeName)
          EndIf
          CloseLibrary(kernel32)
        EndIf
    EndSelect
    CloseHandle_(hProcess)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure GetProcessList()
  hSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, #Null)

  If hSnapshot
    ProcEntry.PROCESSENTRY32
    ProcEntry\dwSize = SizeOf(PROCESSENTRY32)

    If Process32First_(hSnapshot, @ProcEntry)
      While Process32Next_(hSnapshot, @ProcEntry)
        AdjustCurrentProcessPrivilege()
        dwProcessId = ProcEntry\th32ProcessID
        hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, dwProcessId)

        If hProcess
          Debug GetProcessPath(hProcess)
          CloseHandle_(hProcess)
        EndIf
      Wend
      CloseLibrary(kernel32)
    EndIf
    CloseHandle_(hSnapshot)
  EndIf
EndProcedure
GetProcessList()

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

This is for Command Line Process information:
(if you're on a 64bit system then run it in the 64bit version of PureBasic)

Code: Select all

Structure UNICODE_STRING Align #PB_Structure_AlignC
  Length.w
  MaximumLength.w
  Buffer.i
EndStructure

Structure RTL_DRIVE_LETTER_CURDIR Align #PB_Structure_AlignC
  Flags.w
  Length.w
  TimeStamp.l
  DosPath.UNICODE_STRING
EndStructure

Structure RTL_USER_PROCESS_PARAMETERS Align #PB_Structure_AlignC
  MaximumLength.l
  Length.l
  Flags.l
  DebugFlags.l
  ConsoleHandle.i
  ConsoleFlags.i
  StdInputHandle.i
  StdOutputHandle.i
  StdErrorHandle.i
  CurrentDirectoryPath.UNICODE_STRING
  CurrentDirectoryHandle.i
  DllPath.UNICODE_STRING
  ImagePathName.UNICODE_STRING
  CommandLine.UNICODE_STRING
  Environment.i
  StartingPositionLeft.l
  StartingPositionTop.l
  Width.l
  Height.l
  CharWidth.l
  CharHeight.l
  ConsoleTextAttributes.l
  WindowFlags.l
  ShowWindowFlags.l
  WindowTitle.UNICODE_STRING
  DesktopName.UNICODE_STRING
  ShellInfo.UNICODE_STRING
  RuntimeData.UNICODE_STRING
  DLCurrentDirectory.RTL_DRIVE_LETTER_CURDIR[$20]
EndStructure

Structure PEB Align #PB_Structure_AlignC
  InheritedAddressSpace.b
  ReadImageFileExecOptions.b
  BeingDebugged.b
  Spare.b
  Mutant.i
  ImageBaseAddress.i
  *LoaderData.PEB_LDR_DATA
  *ProcessParameters.RTL_USER_PROCESS_PARAMETERS
  SubSystemData.i
  ProcessHeap.i
  FastPebLock.i
  *FastPebLockRoutine.PEBLOCKROUTINE
  *FastPebUnlockRoutine.PEBLOCKROUTINE
  EnvironmentUpdateCount.l
  KernelCallbackTable.i
  EventLogSection.i
  EventLog.i
  *FreeList.PEB_FREE_BLOCK
  TlsExpansionCounter.l
  TlsBitmap.i
  TlsBitmapBits.l[$2]
  ReadOnlySharedMemoryBase.i
  ReadOnlySharedMemoryHeap.i
  ReadOnlyStaticServerData.i
  AnsiCodePageData.i
  OemCodePageData.i
  UnicodeCaseTableData.i
  NumberOfProcessors.l
  NtGlobalFlag.l
  Spare2.b[$4]
  CriticalSectionTimeout.LARGE_INTEGER
  HeapSegmentReserve.l
  HeapSegmentCommit.l
  HeapDeCommitTotalFreeThreshold.l
  HeapDeCommitFreeBlockThreshold.l
  NumberOfHeaps.l
  MaximumNumberOfHeaps.l
  ProcessHeaps.i
  GdiSharedHandleTable.i
  ProcessStarterHelper.i
  GdiDCAttributeList.i
  LoaderLock.i
  OSMajorVersion.l
  OSMinorVersion.l
  OSBuildNumber.l
  OSPlatformId.l
  ImageSubsystem.l
  ImageSubSystemMajorVersion.l
  ImageSubSystemMinorVersion.l
  GdiHandleBuffer.l[$22]
  PostProcessInitRoutine.l
  TlsExpansionBitmap.l
  TlsExpansionBitmapBits.b[$80]
  SessionId.l
EndStructure

Structure PROCESS_BASIC_INFORMATION Align #PB_Structure_AlignC
  ExitStatus.i
  *PebBaseAddress.PEB
  AffinityMask.i
  BasePriority.i
  UniqueProcessId.i
  InheritedFromUniqueProcessId.i
EndStructure

Procedure TestForError()
  dwMessageId = GetLastError_()

  If dwMessageId
    *lpBuffer = AllocateMemory(#MAX_PATH)
    FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, #Null, dwMessageId, #Null, *lpBuffer, #MAX_PATH, #Null)
    dwErrorMsg.s = Trim(PeekS(*lpBuffer, #MAX_PATH, #PB_Ascii))
    Debug "-- Error: " + Str(dwMessageId) + " - " + Left(dwErrorMsg, Len(dwErrorMsg) - 2)
    FreeMemory(*lpBuffer)
  EndIf
EndProcedure

Procedure.b AdjustProcessPrivilege()
  Protected Result.b = #False

  If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @TokenHandle)
    lpLuid.LUID

    If LookupPrivilegeValue_(#Null, #SE_DEBUG_NAME, @lpLuid)
      NewState.TOKEN_PRIVILEGES

      With NewState
        \PrivilegeCount = 1
        \Privileges[0]\Luid\LowPart = lpLuid\LowPart
        \Privileges[0]\Luid\HighPart = lpLuid\HighPart
        \Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
      EndWith
      Result = AdjustTokenPrivileges_(TokenHandle, #False, @NewState, SizeOf(TOKEN_PRIVILEGES), @PreviousState.TOKEN_PRIVILEGES, @ReturnLength)
    EndIf
    CloseHandle_(TokenHandle)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure GetPBI(hProcess)
  Protected Result = #Null
  #ProcessBasicInformation = 0
  Protected pbi.PROCESS_BASIC_INFORMATION

  If Not NtQueryInformationProcess_(hProcess, #ProcessBasicInformation, @pbi, SizeOf(pbi), @ReturnLength)
    If pbi\PebBaseAddress
      Result = pbi\PebBaseAddress
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure GetPEB(hProcess, PebBaseAddress)
  Protected Result = #Null
  Protected peb.PEB

  If ReadProcessMemory_(hProcess, PebBaseAddress, @peb, SizeOf(PEB), #Null)
    If peb\ProcessParameters
      Result = peb\ProcessParameters
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetCMD(hProcess, ProcessParameters)
  Protected Result.s = ""
  Protected rtl.RTL_USER_PROCESS_PARAMETERS
  ZeroMemory_(@rtl, SizeOf(rtl))

  If ReadProcessMemory_(hProcess, ProcessParameters, @rtl, SizeOf(rtl), #Null)
    If rtl\CommandLine\Buffer
      *CmdLine = AllocateMemory(rtl\CommandLine\MaximumLength)

      If ReadProcessMemory_(hProcess, rtl\CommandLine\Buffer, *CmdLine, rtl\CommandLine\MaximumLength, #Null)
        Result = PeekS(*CmdLine, rtl\CommandLine\MaximumLength, #PB_Unicode)
      EndIf
      FreeMemory(*CmdLine)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure GetProcessList()
  hSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, #Null)

  If hSnapshot
    ProcEntry.PROCESSENTRY32
    ProcEntry\dwSize = SizeOf(PROCESSENTRY32)

    If Process32First_(hSnapshot, @ProcEntry)
      While Process32Next_(hSnapshot, @ProcEntry)
        AdjustProcessPrivilege()
        dwProcessId = ProcEntry\th32ProcessID
        hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, dwProcessId)

        If hProcess
          Protected pbi.PROCESS_BASIC_INFORMATION
          ZeroMemory_(@pbi, SizeOf(pbi))
          pbi\PebBaseAddress = GetPBI(hProcess)
          Protected peb.PEB
          ZeroMemory_(@peb, SizeOf(PEB))
          peb\ProcessParameters = GetPEB(hProcess, pbi\PebBaseAddress)
          CommandLine.s = GetCMD(hProcess, peb\ProcessParameters)

          If CommandLine : Debug CommandLine : Else : TestForError() : EndIf

          CloseHandle_(hProcess)
        EndIf
      Wend
    EndIf
    CloseHandle_(hSnapshot)
  EndIf
EndProcedure
GetProcessList()

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Teddy Rogers
User
User
Posts: 98
Joined: Sun Feb 23, 2014 2:05 am
Location: Australia
Contact:

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by Teddy Rogers »

I don't think elevating access privilages like that will work to retrieve information on protected processes. GetProcessImageFileName is still restricted by access rights for those processes as far as I am aware. It may work on earlier OS's, has this been tested as working on Windows 8.1?

Ted.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

I could only test it on Windows 7 64bit, and Windows XP Pro.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Teddy Rogers
User
User
Posts: 98
Joined: Sun Feb 23, 2014 2:05 am
Location: Australia
Contact:

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by Teddy Rogers »

From the code you posted are you able to find the directory path of Windows Task Manager with out the process running in administrator mode?

Ted.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

Yes,
...
C:\Program Files\PureBasic\PureBasic.exe
C:\Program Files\PureBasic\Compilers\pbcompiler.exe
C:\Windows\System32\conhost.exe
C:\Windows\System32\MsSpellCheckingFacility.exe
C:\Windows\System32\taskmgr.exe
...
------------------------

Sorry, correction - that was from Administrator mode... I may have a script that can help, give me a minute.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

Tested in Windows 7 64bit, and Windows XP Pro.

Elevates a process to SYSTEM... test it by compiling the previous code, and running it from this script?
(just throwing stuff out there and seeing if it sticks)

*** if you run it as is - the Calculator should open - check Task Manager to make sure it's running as SYSTEM ***

Code: Select all

#UNTRUSTED_INTEGRITY_SID = "S-1-16-0"
#LOW_INTEGRITY_SID = "S-1-16-4096"
#MEDIUM_INTEGRITY_SID = "S-1-16-8192"
#MEDIUM_PLUS_INTEGRITY_SID = "S-1-16-8448"
#HIGH_INTEGRITY_SID = "S-1-16-12288"
#SYSTEM_INTEGRITY_SID = "S-1-16-16384"
#PROTECTED_PROCESS_MANDATORY_SID = "S-1-16-20480"

#SECURITY_MANDATORY_UNTRUSTED_RID = $00000000
#SECURITY_MANDATORY_LOW_RID = $00001000
#SECURITY_MANDATORY_MEDIUM_RID = $00002000
#SECURITY_MANDATORY_MEDIUM_PLUS_RID = $00002100
#SECURITY_MANDATORY_HIGH_RID = $00003000
#SECURITY_MANDATORY_SYSTEM_RID = $00004000
#SECURITY_MANDATORY_PROTECTED_PROCESS_RID = $00005000

#SE_GROUP_INTEGRITY = $00000020

Enumeration
  #TokenUser = 1
  #TokenGroups
  #TokenPrivileges
  #TokenOwner
  #TokenPrimaryGroup
  #TokenDefaultDacl
  #TokenSource
  #TokenType
  #TokenImpersonationLevel
  #TokenStatistics
  #TokenRestrictedSids
  #TokenSessionId
  #TokenGroupsAndPrivileges
  #TokenSessionReference
  #TokenSandBoxInert
  #TokenAuditPolicy
  #TokenOrigin
  #TokenElevationType
  #TokenLinkedToken
  #TokenElevation
  #TokenHasRestrictions
  #TokenAccessInformation
  #TokenVirtualizationAllowed
  #TokenVirtualizationEnabled
  #TokenIntegrityLevel
  #TokenUIAccess
  #TokenMandatoryPolicy
  #TokenLogonSid
  #MaxTokenInfoClass
EndEnumeration

Enumeration
  #SE_UNKNOWN_OBJECT_TYPE
  #SE_FILE_OBJECT
  #SE_SERVICE
  #SE_PRINTER
  #SE_REGISTRY_KEY
  #SE_LMSHARE
  #SE_KERNEL_OBJECT
  #SE_WINDOW_OBJECT
  #SE_DS_OBJECT
  #SE_DS_OBJECT_ALL
  #SE_PROVIDER_DEFINED_OBJECT
EndEnumeration

Structure TOKEN_MANDATORY_LABEL
  Label.SID_AND_ATTRIBUTES
EndStructure

Prototype.b protoConvertStringSidToSid(StringSid.s, *Sid)
Global ConvertStringSidToSid.protoConvertStringSidToSid

Prototype.i protoCreateProcessWithToken(hToken.i, dwLogonFlags.l, lpApplicationName.s, lpCommandLine.s, dwCreationFlags.l, lpEnvironment.i, lpCurrentDirectory.s, lpStartupInfo.i, lpProcessInfo.i)
Global CreateProcessWithToken.protoCreateProcessWithToken

Prototype.b protoCreateEnvironmentBlock(lpEnvironment, hToken, bInherit.b)
Global CreateEnvironmentBlock.protoCreateEnvironmentBlock

Prototype.b protoDestroyEnvironmentBlock(lpEnvironment)
Global DestroyEnvironmentBlock.protoDestroyEnvironmentBlock

Procedure.i GetWindowsVersion()
  Result.i = 0

  Select OSVersion()
    Case #PB_OS_Windows_2000 : Result = 50
    Case #PB_OS_Windows_XP : Result = 51
    Case #PB_OS_Windows_Server_2003 : Result = 52
    Case #PB_OS_Windows_Vista : Result = 60
    Case #PB_OS_Windows_7 : Result = 61
  EndSelect
  ProcedureReturn Result
EndProcedure

Procedure.b AdjustCurrentProcessPrivilege()
  Result.b = #False

  If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @TokenHandle)
    lpLuid.LUID

    If LookupPrivilegeValue_(#Null, #SE_DEBUG_NAME, @lpLuid)
      NewState.TOKEN_PRIVILEGES

      With NewState
        \PrivilegeCount = 1
        \Privileges[0]\Luid\LowPart = lpLuid\LowPart
        \Privileges[0]\Luid\HighPart = lpLuid\HighPart
        \Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
      EndWith
      Result = AdjustTokenPrivileges_(TokenHandle, #False, @NewState, SizeOf(TOKEN_PRIVILEGES), @PreviousState.TOKEN_PRIVILEGES, @ReturnLength)
    EndIf
    CloseHandle_(TokenHandle)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetProcessIntegrityLevel(ProcessId)
  Result.s = ""
  ProcessHandle = OpenProcess_(#MAXIMUM_ALLOWED, #False, ProcessId)

  If ProcessHandle <> 0
    If OpenProcessToken_(ProcessHandle, #MAXIMUM_ALLOWED, @TokenHandle)
      GetTokenInformation_(TokenHandle, #TokenIntegrityLevel, #Null, 0, @ReturnLength)
      *SIDAndAttributes.SID_AND_ATTRIBUTES
      *SIDAndAttributes = AllocateMemory(ReturnLength)

      If *SIDAndAttributes <> #Null
        If GetTokenInformation_(TokenHandle, #TokenIntegrityLevel, *SIDAndAttributes, ReturnLength, @ReturnLength)
          If IsValidSid_(*SIDAndAttributes\Sid)
            Select PeekL(GetSidSubAuthority_(*SIDAndAttributes\Sid, PeekL(GetSidSubAuthorityCount_(*SIDAndAttributes\Sid)) - 1))
              Case #SECURITY_MANDATORY_UNTRUSTED_RID
                Result = "UntrustedIntegrityLevel"
              Case #SECURITY_MANDATORY_LOW_RID
                Result = "LowIntegrityLevel"
              Case #SECURITY_MANDATORY_MEDIUM_RID
                Result = "MediumIntegrityLevel"
              Case #SECURITY_MANDATORY_MEDIUM_PLUS_RID
                Result = "MediumPlusIntegrityLevel"
              Case #SECURITY_MANDATORY_HIGH_RID
                Result = "HighIntegrityLevel"
              Case #SECURITY_MANDATORY_SYSTEM_RID
                Result = "SystemIntegrityLevel"
              Case #SECURITY_MANDATORY_PROTECTED_PROCESS_RID
                Result = "ProtectedProcessLevel"
            EndSelect
          EndIf
        EndIf
        FreeMemory(*SIDAndAttributes)
      EndIf
      CloseHandle_(TokenHandle)
    EndIf
    CloseHandle_(ProcessHandle)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetTokenUserName(ProcessId)
  Result.s = ""
  ProcessHandle = OpenProcess_(#MAXIMUM_ALLOWED, #False, ProcessId)

  If ProcessHandle <> 0
    If OpenProcessToken_(ProcessHandle, #MAXIMUM_ALLOWED, @TokenHandle)
      GetTokenInformation_(TokenHandle, #TokenUser, #Null, 0, @ReturnLength)
      *SIDAndAttributes.SID_AND_ATTRIBUTES
      *SIDAndAttributes = AllocateMemory(ReturnLength)

      If *SIDAndAttributes <> #Null
        If GetTokenInformation_(TokenHandle, #TokenUser, *SIDAndAttributes, ReturnLength, @ReturnLength)
          *Name = AllocateMemory(#MAX_PATH)
          *Domain = AllocateMemory(#MAX_PATH)

          If *Name <> #Null And *Domain <> #Null
            If LookupAccountSid_(#Null, *SIDAndAttributes\Sid, *Name, @ReturnLength, *Domain, @ReturnLength, @peUse)
              Result = PeekS(*Name)
            EndIf
            FreeMemory(*Name)
            FreeMemory(*Domain)
          EndIf
        EndIf
        FreeMemory(*SIDAndAttributes)
      EndIf
      CloseHandle_(TokenHandle)
    EndIf
    CloseHandle_(ProcessHandle)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure GetWinlogonProcessId()
  Result = 0
  hSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0)

  If hSnapshot <> #INVALID_HANDLE_VALUE
    ProcEntry.PROCESSENTRY32
    ProcEntry\dwSize = SizeOf(PROCESSENTRY32)

    If Process32First_(hSnapshot, @ProcEntry)
      Repeat
        If LCase(PeekS(@ProcEntry\szExeFile, 260)) = "winlogon.exe"
          If GetWindowsVersion() >= 60
            IntegrityLevel.s = GetProcessIntegrityLevel(ProcEntry\th32ProcessID)

            If IntegrityLevel = "SystemIntegrityLevel"
              Result = ProcEntry\th32ProcessID
              Break
            EndIf
          Else
            If GetTokenUserName(ProcEntry\th32ProcessID) = "SYSTEM"
              Result = ProcEntry\th32ProcessID
              Break
            EndIf
          EndIf
        EndIf
      Until Not Process32Next_(hSnapshot, @ProcEntry)
    EndIf
    CloseHandle_(hSnapshot)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.b RunProcessAsSystem(lpApplicationName.s, IntegrityLevel.s)
  Result = #False
  ProcessHandle = OpenProcess_(#MAXIMUM_ALLOWED, #False, GetWinlogonProcessId())

  If ProcessHandle <> 0
    If OpenProcessToken_(ProcessHandle, #MAXIMUM_ALLOWED, @TokenHandle)
      #SecurityImpersonation = 2
      #TokenPrimary = 1

      If DuplicateTokenEx_(TokenHandle, #MAXIMUM_ALLOWED, #Null, #SecurityImpersonation, #TokenPrimary, @ImpersonateToken)
        If Not GetTokenInformation_(ImpersonateToken, #TokenIntegrityLevel, #Null, 0, @ReturnLength) And GetLastError_() = #ERROR_INSUFFICIENT_BUFFER
          *MandatoryLabel.TOKEN_MANDATORY_LABEL
          *MandatoryLabel = AllocateMemory(ReturnLength)

          If *MandatoryLabel <> #Null
            If GetTokenInformation_(ImpersonateToken, #TokenIntegrityLevel, *MandatoryLabel, ReturnLength, @ReturnLength)
              Select IntegrityLevel
                Case "UntrustedIntegrityLevel"
                  PIntegrityLevel.s = #UNTRUSTED_INTEGRITY_SID
                Case "LowIntegrityLevel"
                  PIntegrityLevel.s = #LOW_INTEGRITY_SID
                Case "MediumIntegrityLevel"
                  PIntegrityLevel.s = #MEDIUM_INTEGRITY_SID
                Case "MediumPlusIntegrityLevel"
                  PIntegrityLevel.s = #MEDIUM_PLUS_INTEGRITY_SID
                Case "HighIntegrityLevel"
                  PIntegrityLevel.s = #HIGH_INTEGRITY_SID
                Case "SystemIntegrityLevel"
                  PIntegrityLevel.s = #SYSTEM_INTEGRITY_SID
                Case "ProtectedProcessLevel"
                  PIntegrityLevel.s = #PROTECTED_PROCESS_MANDATORY_SID
              EndSelect
              advapi32 = OpenLibrary(#PB_Any, "advapi32.dll")
              
              If IsLibrary(advapi32)
                ConvertStringSidToSid = GetFunction(advapi32, "ConvertStringSidToSidW")
                CreateProcessWithToken = GetFunction(advapi32, "CreateProcessWithTokenW")

                If ConvertStringSidToSid(PIntegrityLevel, @*Sid)
                  *MandatoryLabel\Label\Sid = *Sid
                  *MandatoryLabel\Label\Attributes = #SE_GROUP_INTEGRITY
  
                  If SetTokenInformation_(ImpersonateToken, #TokenIntegrityLevel, *MandatoryLabel, SizeOf(TOKEN_MANDATORY_LABEL) + GetLengthSid_(*Sid))
                    userenv = OpenLibrary(#PB_Any, "userenv.dll")
                    
                    If IsLibrary(userenv)
                      CreateEnvironmentBlock = GetFunction(userenv, "CreateEnvironmentBlock")
                      DestroyEnvironmentBlock = GetFunction(userenv, "DestroyEnvironmentBlock")
                      
                      If CreateEnvironmentBlock(@pEnvironment, #Null, #False)
                        #CREATE_UNICODE_ENVIRONMENT = $400
                        dwCreationFlag = #NORMAL_PRIORITY_CLASS | #CREATE_NEW_CONSOLE | #CREATE_UNICODE_ENVIRONMENT
                        si.STARTUPINFO
                        ZeroMemory_(@si, SizeOf(STARTUPINFO))
                        si\cb = SizeOf(STARTUPINFO)
                        si\lpDesktop = @"WinSta0\Default"
                        pi.PROCESS_INFORMATION
                        ZeroMemory_(@pi, SizeOf(PROCESS_INFORMATION))
                        Result = CreateProcessWithToken(ImpersonateToken, 0, lpApplicationName, lpCommandLine.s, dwCreationFlag, pEnvironment, lpCurrentDirectory.s, @si, @pi)
                        SetLastError_(0)
                        DestroyEnvironmentBlock(pEnvironment)
                      EndIf
                      CloseLibrary(userenv)
                    EndIf
                  EndIf
                EndIf
                CloseLibrary(advapi32)
              EndIf
            EndIf
            FreeMemory(*MandatoryLabel)
          EndIf
        EndIf
        CloseHandle_(ImpersonateToken)
      EndIf
      CloseHandle_(TokenHandle)
    EndIf
    CloseHandle_(ProcessHandle)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.b RunProcessAsSystemXP(lpApplicationName.s)
  Result = #False
  ProcessHandle = OpenProcess_(#MAXIMUM_ALLOWED, #False, GetWinlogonProcessId())

  If ProcessHandle <> 0
    If OpenProcessToken_(ProcessHandle, #MAXIMUM_ALLOWED, @TokenHandle)
      #DACL_SECURITY_INFORMATION = $4

      If GetSecurityInfo_(TokenHandle, #SE_KERNEL_OBJECT, #DACL_SECURITY_INFORMATION, #Null, #Null, @ppDacl, #Null, @PSD) = 0
        If SetSecurityInfo_(TokenHandle, #SE_KERNEL_OBJECT, #DACL_SECURITY_INFORMATION, #Null, #Null, #Null,#Null) = 0
          If OpenProcessToken_(ProcessHandle, #MAXIMUM_ALLOWED, @TokenHandle2)
            #SecurityImpersonation = 2
            #TokenPrimary = 1

            If DuplicateTokenEx_(TokenHandle2, #MAXIMUM_ALLOWED, #Null, #SecurityImpersonation, #TokenPrimary, @ImpersonateToken)
              If ImpersonateLoggedOnUser_(ImpersonateToken)
                userenv = OpenLibrary(#PB_Any, "userenv.dll")
                
                If IsLibrary(userenv)
                  CreateEnvironmentBlock = GetFunction(userenv, "CreateEnvironmentBlock")
                  DestroyEnvironmentBlock = GetFunction(userenv, "DestroyEnvironmentBlock")
                  
                  If CreateEnvironmentBlock(@pEnvironment, #Null, #False)
                    #CREATE_UNICODE_ENVIRONMENT = $400
                    dwCreationFlag = #NORMAL_PRIORITY_CLASS | #CREATE_NEW_CONSOLE | #CREATE_UNICODE_ENVIRONMENT
                    si.STARTUPINFO
                    ZeroMemory_(@si, SizeOf(STARTUPINFO))
                    si\cb = SizeOf(STARTUPINFO)
                    si\lpDesktop = @"WinSta0\Default"
                    pi.PROCESS_INFORMATION
                    ZeroMemory_(@pi, SizeOf(PROCESS_INFORMATION))
                    Result = CreateProcessAsUser_(ImpersonateToken, lpApplicationName, lpCommandLine.s, #Null, #Null, #False, dwCreationFlag, pEnvironment, lpCurrentDirectory.s, @si, @pi)
                    SetLastError_(0)
                    DestroyEnvironmentBlock(pEnvironment)
                  EndIf
                  CloseLibrary(userenv)
                EndIf
                RevertToSelf_()
              EndIf
              CloseHandle_(ImpersonateToken)
            EndIf
            CloseHandle_(TokenHandle2)
          EndIf
          SetSecurityInfo_(TokenHandle, #SE_KERNEL_OBJECT, #DACL_SECURITY_INFORMATION, #Null, #Null, ppDacl, #Null)
        EndIf
        LocalFree_(ppDacl)
        LocalFree_(PSD)
      EndIf
      CloseHandle_(TokenHandle)
    EndIf
    CloseHandle_(ProcessHandle)
  EndIf
  ProcedureReturn Result
EndProcedure
AdjustCurrentProcessPrivilege()

If GetWindowsVersion() >= 60
  RunProcessAsSystem("C:\Windows\System32\calc.exe", "SystemIntegrityLevel")
Else
  RunProcessAsSystemXP("C:\Windows\System32\calc.exe")
EndIf

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Teddy Rogers
User
User
Posts: 98
Joined: Sun Feb 23, 2014 2:05 am
Location: Australia
Contact:

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by Teddy Rogers »

I just tested the code in Windows 8.1 and I can't get taskmgr.exe or other protected system processes from working (without running the process with adminstrator rights). I've tried similar code of my own with the same problems. The only way I know of getting it to work without having to raise access privilages is through Windows undocumented function NtQuerySystemInformation and SystemProcessIdInformation...

Ted.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

This only returns the Process ID and Process Name - no path:

Code: Select all

Structure UNICODE_STRING Align #PB_Structure_AlignC
  Length.w
  MaximumLength.w
  Buffer.s
EndStructure

Structure PSYSTEM_PROCESS_INFO
  NextEntryOffset.l
  NumberOfThreads.l
  Reserved.LARGE_INTEGER[3]
  CreateTime.LARGE_INTEGER
  UserTime.LARGE_INTEGER
  KernelTime.LARGE_INTEGER
  ImageName.UNICODE_STRING
  BasePriority.l
  ProcessId.l
  InheritedFromProcessId.l
EndStructure

*buffer = VirtualAlloc_(#Null, 1024 * 1024, #MEM_COMMIT | #MEM_RESERVE, #PAGE_READWRITE)
*spi.PSYSTEM_PROCESS_INFO
*spi = *buffer
#SystemProcessInformation = 5
status = NtQuerySystemInformation_(#SystemProcessInformation, *spi, 1024 * 1024, #Null)

While *spi\NextEntryOffset
  Debug Str(*spi\ProcessId) + " | " + *spi\ImageName\Buffer
  *spi + *spi\NextEntryOffset
Wend
VirtualFree_(*buffer, 0 , #MEM_RELEASE)

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Teddy Rogers
User
User
Posts: 98
Joined: Sun Feb 23, 2014 2:05 am
Location: Australia
Contact:

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by Teddy Rogers »

Thanks for all the example code but for now I would like to see if I can get NtQuerySystemInformation function with SystemProcessIdInformation working correctly in PB as I think it's the only option likely to work for what I want to do. If you have any tips or insight on this it would be greatly appreciated!

Ted.
Last edited by Teddy Rogers on Tue Apr 08, 2014 8:30 pm, edited 1 time in total.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

Take a second look at my last example - its using the NtQuerySystemInformation function with SystemProcessInformation. :)

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Teddy Rogers
User
User
Posts: 98
Joined: Sun Feb 23, 2014 2:05 am
Location: Australia
Contact:

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by Teddy Rogers »

JHPJHP wrote:Take a second look at my last example - its using the NtQuerySystemInformation function with SystemProcessIdInformation. :)
I can already get the processid and process name, its the directory path I'm specifically trying to get... or do you mean something else?

Ted.
User avatar
JHPJHP
Addict
Addict
Posts: 2257
Joined: Sat Oct 09, 2010 3:47 am

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by JHPJHP »

I would like to see if I can get NtQuerySystemInformation function with SystemProcessIdInformation working correctly in PB
I didn't know you had it working correctly, your first post didn't run for me; I thought my example was a working version of your first post.
- CallFunctionFast: not needed with this function and the latest version of PureBasic

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: NtQuerySystemInformation #SystemProcessIdInformation

Post by Thunder93 »

The code posted by OP has dependences.

JHPJHP, for future references. I think your PSYSTEM_PROCESS_INFO structure should look like..

Code: Select all

Structure PSYSTEM_PROCESS_INFO
  NextEntryOffset.l
  NumberOfThreads.l
  Reserved.LARGE_INTEGER[3]
  CreateTime.LARGE_INTEGER
  UserTime.LARGE_INTEGER
  KernelTime.LARGE_INTEGER
  ImageName.UNICODE_STRING
  BasePriority.l
  ProcessId.i
  InheritedFromProcessId.l
EndStructure
more work needed if you don't want to make Unicode executable.
Last edited by Thunder93 on Wed Apr 09, 2014 1:45 am, edited 1 time in total.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Post Reply