P/Invoke to get INFOBLOCK structure and Command line

Answered P/Invoke to get INFOBLOCK structure and Command line

  • 2012年4月10日 下午 05:32
     
      包含代碼

    Hi, I've been working on this for several days straight and I can't seem to get it to work correctly... I honestly don't even know that it's getting the correct addresses and don't know how to check for validity:/ But this is what I have so far:

    public partial class Form1 : Form
        {
            IntPtr handle;
            int pebAddress;
            int procInfoAddress;
            string cmdLine;
    
            public Form1()
            {
                InitializeComponent();
    
                if (NativeFunctions.Privileges.EnableDebuggingPrivileges())
                {
                    MessageBox.Show("Successfully got SeDebugPrivilege.");
                    if ((handle = Open(NativeFunctions.Privileges.PROCESS_ALL_ACCESS, true, 3396)) == IntPtr.Zero)
                    {
                        MessageBox.Show("Failed to open process!");
                    }
    
                    else
                    {
                        MessageBox.Show("Successfully opened process.");
                        pebAddress = GetPEBAddress(handle);
                        if (pebAddress == 0 || pebAddress == -1)
                        {
                            MessageBox.Show("Failed to get PEB Address!");
                        }
    
                        else
                        {
                            MessageBox.Show("PEB Address: " + pebAddress.ToString());
                            procInfoAddress = GetProcInfoAddress(handle);
                            if (procInfoAddress == 0)
                            {
                                MessageBox.Show("Failed to get INFOBLOCK Address!");
                            }
    
                            else
                            {
                                MessageBox.Show("INFOBLOCK Address: " + procInfoAddress.ToString());
                                cmdLine = GetCommandLine(handle);
                                MessageBox.Show(cmdLine);
                            }
                        }
                    }
                    Close(handle);
                }
    
                else
                {
                    Application.Exit();
                }
            }
    
            public unsafe int GetPEBAddress(IntPtr handle)
            {
                int address;
                if (handle != null && handle != IntPtr.Zero)
                {
                    NativeFunctions.ProcessInformation.PROCESS_BASIC_INFORMATION pbi = new NativeFunctions.ProcessInformation.PROCESS_BASIC_INFORMATION();
                    uint size = (uint)sizeof(NativeFunctions.ProcessInformation.PROCESS_BASIC_INFORMATION);
                    int returnLength = 0;
                    if (NativeFunctions.ProcessInformation.NtQueryInformationProcess(handle, NativeFunctions.ProcessInformation.PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, size, ref returnLength) == 0)
                    {
                        address = pbi.PebBaseAddress;
                    }
    
                    else
                    {
                        address = 0;
                    }
                }
    
                else
                {
                    address = -1;
                }
                return address;
            }
    
            public unsafe int GetProcInfoAddress(IntPtr handle)
            {
                IntPtr address;
                uint size = (uint)sizeof(IntPtr);
                uint returnLength = 0;
                int offset = (int)0x10;
                int x = pebAddress;
                int y = x + offset;
                MessageBox.Show("Size: " + y);
                if (!NativeFunctions.ProcessInformation.ReadProcessMemory(handle, (IntPtr)y, out address, size, out returnLength)) //(IntPtr)pebAddress + 0x10
                {
                    return 0;
                }
    
                else
                {
                    return address.ToInt32();
                }
            }
    
            public unsafe string GetCommandLine(IntPtr handle)
            {
                IntPtr str;
                uint size = (uint)sizeof(IntPtr);
                uint returnLength = 0;
                int offset = (int)0x40;
                MessageBox.Show(offset.ToString());
                int x = procInfoAddress;
                int y = x + offset;
                MessageBox.Show("Size: " + y);
                if (!NativeFunctions.ProcessInformation.ReadProcessMemory(handle, (IntPtr)y, out str, size, out returnLength))
                {
                    return "FAIL!";
                }
    
                else
                {
                    return Marshal.PtrToStringAuto(str);
                }
            }
    
            public IntPtr Open(int access, bool inherit, int pid)
            {
                return NativeFunctions.Kernel32.OpenProcess(access, inherit, pid);
            }
    
            public void Close(IntPtr handle)
            {
                NativeFunctions.Kernel32.CloseHandle(handle);
            }
        }

    Please help me!

    Aaron Chapman

所有回覆

  • 2012年4月11日 上午 02:27
     
     已答覆

    Why don't you properly define the PEB structure here?

    Also, don't hardcode offset as the PEB structure has changed on x64 systems (Note that it doesn't really matter if your application run as 32 or 64-bit, so don't use that kind of detection. Instead, properly detect whether you're running on a 64-bit machine).


    EDIT: Added a link to others implementation of PEB structure from Koders there. However if you plan to use that on x64 machine, it won't work for aforementioned reason.

  • 2012年5月1日 下午 04:24
     
     
    But I thought you were supposed to use the PROCESS_BASIC_INFORMATION block to find the PEB address? Then from that get the PEB block to find the command line?

    Aaron Chapman

  • 2012年5月2日 上午 03:04
     
     

    If you just want the commandline, use GetCommandLine() API instead.

    As said in the documentation of NTQueryInformation(), it's a function that will potentially change in future versions of Windows. Unless you have plans to release seperate binaries to support that seperate version of Windows, you're advised to find a suitable replacement function instead of containue using this.

    EDIT: When you want command line from other process, you can use WMI instead.


    • 已編輯 cheong00 2012年5月2日 上午 06:13
    •