在没有 WMI 的情况下获取进程的命令行

2024-02-07

我找到了wj32post https://wj32.org/wp/2009/01/24/howto-get-the-command-line-of-processes/关于如何通过WinAPI读取指定进程的命令行。我尝试在 C# 上翻译该示例,但有几个问题。我可以获得指向 RTL_USER_PROCESS_PARAMETERS 结构的 CommandLine 字段的有效指针,但困难在于获取字符串本身。我应该使用不安全的代码吗?如何使用 wj32 的示例正确获取进程的命令行?

using System;
using System.Runtime.InteropServices;

namespace CommandLine {
  internal static class NativeMethods {
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern Boolean CloseHandle(
        IntPtr hObject
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr OpenProcess(
        UInt32  dwDesiredAccess,
        [MarshalAs(UnmanagedType.Bool)]
        Boolean bInheritHandle,
        Int32   dwProcessId
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern Boolean ReadProcessMemory(
        IntPtr hProcess,
        IntPtr lpBaseAddress,
        out IntPtr lpBuffer,
        Int32  nSize,
        out IntPtr lpNumberOfBytesRead
    );

    [DllImport("ntdll.dll")]
    internal static extern Int32 NtQueryInformationProcess(
        IntPtr ProcessHandle,
        UInt32 ProcessInformationClass,
        ref PROCESS_BASIC_INFORMATION ProcessInformation,
        UInt32 ProcessInformationLength,
        IntPtr ReturnLength
    );

    [StructLayout(LayoutKind.Sequential)]
    internal struct PROCESS_BASIC_INFORMATION {
      internal Int32  ExitProcess;
      internal IntPtr PebBaseAddress;
      internal IntPtr AffinityMask;
      internal Int32  BasePriority;
      internal IntPtr UniqueProcessId;
      internal IntPtr InheritedFromUniqueProcessId;

      internal UInt32 Size {
        get { return (UInt32)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); }
      }
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct UNICODE_STRING {
      internal UInt16 Length;
      internal UInt16 MaximumLength;
      [MarshalAs(UnmanagedType.LPWStr)]
      internal String Buffer;
    }
  }

  internal sealed class Program {
    private const UInt32 PROCESS_QUERY_INFORMATION = 0x400;
    private const UInt32 PROCESS_VM_READ = 0x010;

    [STAThread()]
    static void Main(String[] args) {
      if (args.Length != 1) return;

      Int32 pid;
      if (!Int32.TryParse(args[0], out pid)) return;

      IntPtr proc;
      NativeMethods.PROCESS_BASIC_INFORMATION pbi = new NativeMethods.PROCESS_BASIC_INFORMATION();
      IntPtr rupp; //RTL_USER_PROCESS_PARAMETERS
      IntPtr cmdl; //CommandLine field
      IntPtr read;

      if ((proc = NativeMethods.OpenProcess(
          PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid
      )) == IntPtr.Zero) return;

      if (NativeMethods.NtQueryInformationProcess(proc, 0, ref pbi, pbi.Size, IntPtr.Zero) == 0) {
        if (NativeMethods.ReadProcessMemory(
            proc, (IntPtr)(pbi.PebBaseAddress.ToInt32() + 0x10), out rupp, IntPtr.Size, out read
        )) {
          if (NativeMethods.ReadProcessMemory(
              proc, (IntPtr)(rupp.ToInt32() + 0x40), out cmdl,
              Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING)), out read
          )) {
            // what I need to do to get command line?
          }
        }
      }

      NativeMethods.CloseHandle(proc);
    }
  }
}

好的,我已经在几个进程上测试了这个版本。请注意,它仅适用于 32 位进程,因为 64 位的内存布局不同。我没有时间来写为什么我做出了这些改变,但希望你能解决这个问题。如果我有时间我会回来更新答案

using System;
using System.Runtime.InteropServices;

namespace CommandLine
{
    internal static class NativeMethods
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern Boolean CloseHandle(
            IntPtr hObject
        );

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern IntPtr OpenProcess(
            UInt32 dwDesiredAccess,
            [MarshalAs(UnmanagedType.Bool)]
        Boolean bInheritHandle,
            Int32 dwProcessId
        );


        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern Boolean ReadProcessMemory(
            IntPtr hProcess,
            IntPtr lpBaseAddress,
            byte[] lpBuffer,
            Int32 nSize,
            out IntPtr lpNumberOfBytesRead
        );

        [DllImport("ntdll.dll")]
        internal static extern Int32 NtQueryInformationProcess(
            IntPtr ProcessHandle,
            UInt32 ProcessInformationClass,
            ref PROCESS_BASIC_INFORMATION ProcessInformation,
            UInt32 ProcessInformationLength,
            IntPtr ReturnLength
        );

        [StructLayout(LayoutKind.Sequential, Pack=1)]
        internal struct PROCESS_BASIC_INFORMATION
        {
            internal Int32 ExitProcess;
            internal IntPtr PebBaseAddress;
            internal IntPtr AffinityMask;
            internal Int32 BasePriority;
            internal IntPtr UniqueProcessId;
            internal IntPtr InheritedFromUniqueProcessId;

            internal UInt32 Size
            {
                get { return (UInt32)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); }
            }
        }

        [StructLayout(LayoutKind.Sequential, Pack=1)]
        internal struct UNICODE_STRING
        {
            internal UInt16 Length;
            internal UInt16 MaximumLength;
            internal IntPtr buffer;
        }
    }

    internal sealed class Program
    {
        private const UInt32 PROCESS_QUERY_INFORMATION = 0x400;
        private const UInt32 PROCESS_VM_READ = 0x010;

        [STAThread()]
        static void Main(String[] args)
        {
            if (args.Length != 1) return;

            Int32 pid;
            if (!Int32.TryParse(args[0], out pid)) return;

            IntPtr proc;
            NativeMethods.PROCESS_BASIC_INFORMATION pbi = new NativeMethods.PROCESS_BASIC_INFORMATION();
            IntPtr read;

            if ((proc = NativeMethods.OpenProcess(
                PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid
            )) == IntPtr.Zero) return;

            if (NativeMethods.NtQueryInformationProcess(proc, 0, ref pbi, pbi.Size, IntPtr.Zero) == 0)
            {
                byte[] rupp = new byte[IntPtr.Size];
                if (NativeMethods.ReadProcessMemory(
                    proc, (IntPtr)(pbi.PebBaseAddress.ToInt32() + 0x10), rupp, IntPtr.Size, out read
                ))
                {
                    Int32 ruppPtr = BitConverter.ToInt32(rupp,0);
                    byte[] cmdl = new byte[Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING))];

                    if (NativeMethods.ReadProcessMemory(
                        proc, (IntPtr)(ruppPtr + 0x40), cmdl,
                        Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING)), out read
                    ))
                    {
                        NativeMethods.UNICODE_STRING ucsData;
                        ucsData = ByteArrayToStructure<NativeMethods.UNICODE_STRING>(cmdl);
                        byte[] parms =new byte[ucsData.Length];
                        if (NativeMethods.ReadProcessMemory(
                            proc, ucsData.buffer, parms,
                            ucsData.Length, out read
                            ))
                        {
                            var s = System.Text.Encoding.Unicode.GetString(parms);
                            Console.WriteLine("Parameters = {0}", s);
                        }
                    }
                }
            }

            NativeMethods.CloseHandle(proc);
        }
        static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
        {
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
            handle.Free();
            return stuff;
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在没有 WMI 的情况下获取进程的命令行 的相关文章

  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • CMake 找不到请求的 Boost 库

    既然我已经浏览了其他人的解决方案几个小时 但找不到适合我的问题的正确答案 我想将我的具体问题带给您 我正在尝试使用 CMake 构建 vsomeip 为此 我之前构建了 boost 1 55 但是 我在 CMake 中收到以下错误 The
  • Poco c++Net:Http 从响应中获取标头

    我使用 POCO C Net 库进行 http 我想尝试制定持久缓存策略 首先 我认为我需要从缓存标头中获取过期时间 并与缓存值进行交叉检查 如果我错了 请告诉我 那么我如何从中提取缓存头httpResponse 我已经看到你可以用 Jav
  • 在路由mvc 4中添加公司名称

    我一直在尝试为 Facebook 等用户提供在 URL 中添加公司名称的选项 http localhost 50753 MyCompany Login 我尝试过不同的网址 但没有成功 routes MapRoute name Default
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 如何从 Rx Subscribe 回调异步函数?

    我想回调 Rx 订阅中的异步函数 例如 像那样 public class Consumer private readonly Service service new Service public ReplaySubject
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • C++ 中 void(*)() 和 void(&)() 之间的区别[重复]

    这个问题在这里已经有答案了 在此示例代码中 func1是类型void int double and funky是类型void int double include
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc

随机推荐