Home > Code, NTDLL > Remote process Environment Variables

Remote process Environment Variables

February 23rd, 2010 Cobein Leave a comment Go to comments

A simple module to read Environment Variables from a remote process. Tested on XP and 7.

'---------------------------------------------------------------------------------------
' Module      : mRemoteGetEnviron
' DateTime    : 23/02/2010 21:29
' Author      : Cobein
' Mail        : cobein27@hotmail.com
' WebPage     : http://www.advancevb.com.ar
' Purpose     : Read remote process environment variables.
' Usage       : At your own risk
' Requirements: None
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce
'               or publish this code on any web site,
'               online service, or distribute as source
'               on any media without express permission.
'
' Reference   : http://www.codeproject.com/KB/threads/ReadProcEnv.aspx
'
' History     : 23/02/2010 First Cut....................................................
'---------------------------------------------------------------------------------------
Option Explicit

Private Const PROCESS_QUERY_INFORMATION As Long = &H400
Private Const PROCESS_VM_READ           As Long = 16&

Public Type PROCESS_BASIC_INFORMATION
    ExitStatus                      As Long
    PEBBaseAddress                  As Long
    AffinityMask                    As Long
    BasePriority                    As Long
    UniqueProcessId                 As Long
    InheritedFromUniqueProcessId    As Long
End Type

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function NtQueryInformationProcess Lib "ntdll.dll" (ByVal ProcessHandle As Long, ByVal ProcessInformationClass As Long, ByVal ProcessInformation As Long, ByVal ProcessInformationLength As Long, ReturnLength As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal hProcess As Long, ByRef lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function RtlAdjustPrivilege Lib "ntdll" (ByVal Privilege As Long, ByVal bEnablePrivilege As Long, ByVal bCurrentThread As Long, ByRef OldState As Long) As Long

Public Function ReadEnviron(ByVal lPid As Long) As Collection
    Dim lPtr            As Long
    Dim lProc           As Long
    Dim cData           As New Collection

    Set ReadEnviron = cData

    Call RtlAdjustPrivilege(20, 1, 0, 0)

    lPtr = GetPEB(lPid)

    lProc = OpenProcess(PROCESS_VM_READ, 0, lPid)

    If lProc Then

        If Not ReadProcessMemory(lProc, ByVal lPtr + &H10, lPtr, &H4, 0&) = 0 Then 'RTL_USER_PROCESS_PARAMETERS

            If Not ReadProcessMemory(lProc, ByVal lPtr + &H48, lPtr, &H4, 0&) = 0 Then 'environment variables block

                Dim bData As Byte
                Dim sData As String
                Dim lOffset As Long

                Do
                    lOffset = lOffset + 2
                    If bData = 0 Then
                        If Not sData = vbNullString Then cData.Add sData
                        sData = vbNullString
                        Call ReadProcessMemory(lProc, ByVal lPtr + lOffset, bData, &H1, 0&)
                        If bData = 0 Then
                            Exit Do
                        End If
                    Else
                        Call ReadProcessMemory(lProc, ByVal lPtr + lOffset, bData, &H1, 0&)
                    End If
                    sData = sData & Chr$(bData)
                Loop
            End If

        End If

        Call CloseHandle(lProc)

    End If

    Set ReadEnviron = cData

End Function

Private Function GetPEB(ByVal lPid As Long) As Long
    Dim tPBI    As PROCESS_BASIC_INFORMATION
    Dim lRet    As Long
    Dim lProc   As Long

    lProc = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, lPid)
    If lProc Then
        If NtQueryInformationProcess(lProc, 0, VarPtr(tPBI), Len(tPBI), lRet) = 0 Then
            GetPEB = tPBI.PEBBaseAddress
        End If
        CloseHandle lProc
    End If

End Function
Categories: Code, NTDLL
  1. February 24th, 2010 at 14:42 | #1

    Buen codigo… pero creo que tal vez abrian problemas con rutas UNICODE… porque estas unicamente sacando el primer BYTE… Por eso creo que seria mejor utilizar lstrcpyW y lstrlenW =P

  2. February 24th, 2010 at 14:53 | #2

    Aqui esta la modiciacion:
    <code>
    Public Function ReadEnviron(ByVal lPid As Long) As Collection
    Dim lPtr As Long
    Dim lProc As Long
    Dim cData As New Collection
    Dim lOffset As Long
    Dim lSize As Long
    Dim sData As String

    Set ReadEnviron = cData

    Call RtlAdjustPrivilege(20, 1, 0, 0)
    lPtr = GetPEB(lPid)
    lProc = OpenProcess(PROCESS_VM_READ, 0, lPid)

    If lProc Then

    If Not ReadProcessMemory(lProc, ByVal lPtr + &H10, lPtr, &H4, 0&) = 0 Then 'RTL_USER_PROCESS_PARAMETERS

    If Not ReadProcessMemory(lProc, ByVal lPtr + &H48, lOffset, &H4, 0&) = 0 Then 'environment variables block
    Do
    lSize = lstrlen(lOffset)
    sData = Space$(lSize)
    Call lstrcpy(StrPtr(sData), lOffset)
    cData.Add sData
    lOffset = lOffset + ((lSize + 1) * 2)
    Loop Until lSize = 0
    End If
    End If
    Call CloseHandle(lProc)
    End If
    Set ReadEnviron = cData
    End Function
    </code>

    No lo he probado mucho, pero deberia ir exactamente igual…

    Saludos =D

    • February 24th, 2010 at 16:38 | #3

      Me parece que no va a funcionar remotamente de esa manera. Tengo que testearlo.

      • February 24th, 2010 at 17:44 | #4

        Cieeerto! Es por eso que no me daba la misma cantidad de bytes jajajjaja
        Como no he caido en eso =$ x'DDD

        Loops de Cobein- 1
        Karcrack- 0

        XDD

        • February 24th, 2010 at 19:41 | #5

          Igualmente hay un "error", hay que limpiar las cadenas porque quedan con un null al final y no se si vi otra cosa, tengo que testearlo.

          • February 24th, 2010 at 20:17 | #6

            Si, es por ese chr(0) que empeze a probar lo de lstrcpy… pero claro, no sirve para otros procesos…
            El problema del caracter nulo es que compruebas que si es 0 despues de haberlo añadido…

  1. No trackbacks yet.
You must be logged in to post a comment.