public static string GetCommandLineOfProcess(int processId)
var pbi = new NativeMethods.PROCESS_BASIC_INFORMATION();
IntPtr proc = NativeMethods.OpenProcess
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid
if (NativeMethods.NtQueryInformationProcess(proc, 0, ref pbi, pbi.Size, IntPtr.Zero) == 0)
var buff = new byte[IntPtr.Size];
if (NativeMethods.ReadProcessMemory
(IntPtr) (pbi.PebBaseAddress.ToInt32() + 0x10),
var buffPtr = BitConverter.ToInt32(buff, 0);
var commandLine = new byte[Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING))];
NativeMethods.ReadProcessMemory
proc, (IntPtr) (buffPtr + 0x40),
Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING)), out _
var ucsData = ByteArrayToStructure<NativeMethods.UNICODE_STRING>(commandLine);
var parms = new byte[ucsData.Length];
NativeMethods.ReadProcessMemory
proc, ucsData.buffer, parms,
return Encoding.Unicode.GetString(parms);
NativeMethods.CloseHandle(proc);
private const uint PROCESS_QUERY_INFORMATION = 0x400;
private const uint PROCESS_VM_READ = 0x010;
private static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var stuff = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
private static class NativeMethods
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr OpenProcess
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ReadProcessMemory
out IntPtr lpNumberOfBytesRead
internal static extern int NtQueryInformationProcess
uint ProcessInformationClass,
ref PROCESS_BASIC_INFORMATION ProcessInformation,
uint ProcessInformationLength,
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct PROCESS_BASIC_INFORMATION
internal int ExitProcess;
internal IntPtr PebBaseAddress;
internal IntPtr AffinityMask;
internal int BasePriority;
internal IntPtr UniqueProcessId;
internal IntPtr InheritedFromUniqueProcessId;
internal uint Size => (uint) Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION));
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct UNICODE_STRING
internal ushort MaximumLength;