Re: Getting command line of another process

Tech-Archive recommends: Fix windows errors by optimizing your registry



I love this newsgroups ;-)

"Pedro Miguel Teixeira" wrote:

Ah, there is another way (actually this is probably Process Explorer way of
doing it - I am just guessing - since he actually does use it for other
things such as page/non-page pool numbers)

Use Debugger API to perform a non-invasive attach to the process. You can
try attaching notepad and issuing:

0:000> !peb
PEB at 7ffdf000
(...)
WindowTitle: 'C:\WINDOWS\system32\notepad.exe'
ImageFile: 'C:\WINDOWS\system32\notepad.exe'
CommandLine: '"C:\WINDOWS\system32\notepad.exe" \boot.ini'
(...)

Then just detatch the process ;)


"BT" <BT@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:0A3D2CCD-FECF-44D9-BEC4-0F31B55106BB@xxxxxxxxxxxxxxxx
Thanks for this very good demonstration ;-)

"Pedro Miguel Teixeira" wrote:


You should never assume the address of the _PEB (the structure that
includes
_RTL_PROCESS_PARAMETERS) to be a certain value. It can vary.

The only guaranty threads have if that NtCurrentTeb() returns the address
of
their_TEB which. in turn, contains a pointer to _PEB. NtCurrentTeb() is
just
a macro, since_TEB is pointed by gs segment on 64bit systems and fs
segment
on 32bit systems. On Itanium it is easier since it is the value in
register
r13. Back on x86, even if you are able to get the value of fs/gs from
another process, this will take you nowhere since the entry on GDT is
probably different.

This, of course, assuming that you already had enough Integrity Level to
OpenProcess in the first place...

Injecting the thread is probably your best bet :)


"BT" <BT@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:05B3FA00-ED8E-4143-B18B-C833A9D13C3A@xxxxxxxxxxxxxxxx
That's still the only way.

It seems to be very complicated code just to retrieve the command line
of
a
process. Why the undocumented structure RTL_PROCESS_PARAMETERS is not
accessible by documented API.

There is another way to retrieve command line, but it is undocumented
and
using it is discouraged (but can resolve your problem). This way does
not
work on Vista. The RTL_PROCESS_PARAMETERS structure is accessible in
the
VA
space of the process at the address 0x0002:0000. Here is the C# :

public class CProcessHelper
{
//
// RTL_PROCESS_PARAMETERS (undocumented structure)
//
// Memory Address : 0x0002:0000
// + 0x038 ImagePathName : UNICODE_STRING
// + 0x040 CmdLine : UNICODE_STRING
// + 0x078 DesktopName : UNICODE_STRING
//

public static IntPtr RtlProcessParametersAddress = new
IntPtr(0x00020000);
public static IntPtr RtlProcessParametersAddressNtVDM = new
IntPtr(0x02010000);

public static UInt32 RtlProcessParameterImagePathnameOffset =
0x38;
public static UInt32 RtlProcessParameterCommandLineOffset =
0x40;
public static UInt32 RtlProcessParameterDesktopNameOffset =
0x78;

/// <summary>
/// Retrieve a process parameter into RTL_PROCESS_PARAMETERS
page
located at address 0x0002:0000
/// </summary>
/// <param name="HandleProcess">Handle of process with
PROCESS_VM_READ access</param>
/// <param name="PageBaseAddress">Base address of
RTL_PROCESS_PARAMETERS (normally 0x0002:0000)</param>
/// <param name="UnicodeStringOffset">Relative offset (from
PageBaseAddress) where UNICODE_STRING structure is situated </param>
/// <param name="Result">String read</param>
/// <returns></returns>
static public bool RetrieveUserModeProcessString(IntPtr
HandleProcess, IntPtr PageBaseAddress, UInt32 UnicodeStringOffset, out
string
Result)
{
UInt32 UnicodeStringSize = 8;
UInt32 UnicodeStringSizeRead;

IntPtr pUnicodeString =
Marshal.AllocCoTaskMem((Int32)UnicodeStringSize);
IntPtr pUnicodeStringAddress;
UInt64 UnicodeStringAddress =
(UInt64)(PageBaseAddress.ToInt64() + UnicodeStringOffset);

UInt64 StringAddress;
UInt32 StringLength;

IntPtr pStringContent = IntPtr.Zero;
IntPtr pStringAddress;

Result = null;

try
{
// Translate UNICODE_STRUCTURE offset into pointer
pUnicodeStringAddress = new
IntPtr((Int64)UnicodeStringAddress);

// Read the UNICODE_STRING structure
if (CKernel32API.ReadProcessMemory(HandleProcess,
pUnicodeStringAddress, pUnicodeString, UnicodeStringSize, out
UnicodeStringSizeRead) == false)
return false;

// Check that all the structure has been read
if (UnicodeStringSizeRead != UnicodeStringSize)
return false;

// Retrieve the length
StringLength =
(UInt16)Marshal.ReadInt16(pUnicodeString);

// Null string ? Ok, all done
if (StringLength == 0) return true;

// heuristic should be use on the string length
retrieved

// Adjust the length for an Unicode string terminated by
'\0'
StringLength = (UInt32)((StringLength + 1) * 2);

// Allocate space for retrieve the string
pStringContent =
Marshal.AllocCoTaskMem((Int32)StringLength);

// Read the string address
StringAddress =
(UInt32)Marshal.ReadInt32(pUnicodeString,
4);

// Translate offset into pointer
// Two solutions : either a relative offset or a
absolute
address
if (StringAddress > (UInt64)PageBaseAddress.ToInt64())
pStringAddress = new IntPtr((Int64)StringAddress);
else pStringAddress = new
IntPtr(PageBaseAddress.ToInt64()
+
(Int64) StringAddress);

// Read the string
if (CKernel32API.ReadProcessMemory(HandleProcess,
pStringAddress, pStringContent, StringLength, out StringLength) ==
false)
return false;

// Retrieve the string in managed result
Result = Marshal.PtrToStringUni(pStringContent);
}
catch
{
return false;
}
finally
{
Marshal.FreeCoTaskMem(pUnicodeString);
if (pStringContent != IntPtr.Zero)
Marshal.FreeCoTaskMem(pStringContent);
}

return true;
}











code where CKernel32API class just declare the dllimport :






.



Relevant Pages

  • Re: Getting command line of another process
    ... public static IntPtr RtlProcessParametersAddressNtVDM = new ... IntPtr pStringContent = IntPtr.Zero; ... pUnicodeStringAddress, pUnicodeString, UnicodeStringSize, out ... // Null string? ...
    (microsoft.public.win32.programmer.kernel)
  • Re: Getting command line of another process
    ... public static IntPtr RtlProcessParametersAddressNtVDM = new ... IntPtr pStringContent = IntPtr.Zero; ... pUnicodeStringAddress, pUnicodeString, UnicodeStringSize, out ... // Null string? ...
    (microsoft.public.win32.programmer.kernel)
  • Re: Getting command line of another process
    ... public static IntPtr RtlProcessParametersAddressNtVDM = new ... HandleProcess, IntPtr PageBaseAddress, UInt32 UnicodeStringOffset, out string ... IntPtr pStringContent = IntPtr.Zero; ... pUnicodeStringAddress, pUnicodeString, UnicodeStringSize, out ...
    (microsoft.public.win32.programmer.kernel)
  • Re: Getting command line of another process
    ... It seems to be very complicated code just to retrieve the command line of a process. ... static public bool RetrieveUserModeProcessString(IntPtr HandleProcess, IntPtr PageBaseAddress, UInt32 UnicodeStringOffset, out string Result) ... UInt32 UnicodeStringSize = 8; ... pStringContent = Marshal.AllocCoTaskMemStringLength); ...
    (microsoft.public.win32.programmer.kernel)
  • VirtualAllocEx returns a bad pointer in some processes
    ... (ByVal hWnd As IntPtr, _ ... (ByVal hWndParent As IntPtr, _ ... ByVal lParam As String) As Integer ... Dim aihWnds As ArrayList ...
    (microsoft.public.vc.mfc)