You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Linux环境下隐藏进程名中的启动参数

解决Linux下C#控制台进程命令行参数隐藏问题

针对Linux下C#控制台进程命令行参数暴露的问题,以下是几种无需改为交互式输入的解决方法:

方法1:直接修改进程的argv数组(Linux专属)

Linux系统允许进程修改自身的argv数组,从而让ps、Screen等工具读取不到原始敏感参数。可以通过P/Invoke调用Linux系统函数实现:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("libc", SetLastError = true)]
    private static extern IntPtr getenv(string name);

    [DllImport("libc", SetLastError = true)]
    private static extern IntPtr memcpy(IntPtr dest, IntPtr src, UIntPtr count);

    static void Main(string[] args)
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            // 通过环境变量指针推导argv的地址
            IntPtr environ = getenv("__environ");
            if (environ != IntPtr.Zero)
            {
                // argv[0]的地址为environ减去指针大小(64位系统为8字节)
                IntPtr argv = environ - IntPtr.Size;
                // 替换进程名,覆盖原始命令行开头
                string newProcessName = "./MyProgram";
                byte[] nameBytes = System.Text.Encoding.ASCII.GetBytes(newProcessName + '\0');
                memcpy(argv, Marshal.StringToHGlobalAnsi(newProcessName), (UIntPtr)nameBytes.Length);
                
                // 将后续参数置为null,清除敏感信息残留
                for (int i = 1; i < args.Length; i++)
                {
                    IntPtr argPtr = argv + i * IntPtr.Size;
                    Marshal.WriteIntPtr(argPtr, IntPtr.Zero);
                }
            }
        }

        // 后续业务逻辑执行
        Console.WriteLine("程序运行中...");
        Console.ReadLine();
    }
}

注意:该方法仅在Linux生效,需要程序具备基础运行权限,修改后/proc/self/cmdline将不再包含敏感参数。

方法2:通过子进程传递敏感参数(跨平台兼容)

主进程接收命令行参数后,启动子进程执行核心逻辑,将敏感参数通过标准输入或环境变量传递,主进程随即退出。子进程的命令行不会包含敏感参数:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

class Program
{
    static void Main(string[] args)
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            // 通过环境变量标记是否为子进程
            string isChild = Environment.GetEnvironmentVariable("MY_PROCESS_CHILD");
            if (string.IsNullOrEmpty(isChild))
            {
                // 主进程:启动子进程并传递参数到标准输入
                ProcessStartInfo psi = new ProcessStartInfo();
                psi.FileName = Process.GetCurrentProcess().MainModule.FileName;
                psi.EnvironmentVariables["MY_PROCESS_CHILD"] = "1";
                psi.RedirectStandardInput = true;
                psi.UseShellExecute = false;

                using (Process childProcess = Process.Start(psi))
                {
                    foreach (string arg in args)
                    {
                        childProcess.StandardInput.WriteLine(arg);
                    }
                    childProcess.StandardInput.Close();
                    // 主进程退出,子进程独立运行
                    return;
                }
            }
            else
            {
                // 子进程:从标准输入读取原始参数
                var childArgs = new System.Collections.Generic.List<string>();
                string line;
                while ((line = Console.ReadLine()) != null)
                {
                    childArgs.Add(line);
                }
                args = childArgs.ToArray();
            }
        }

        // 核心业务逻辑,使用读取到的参数
        Console.WriteLine("子进程运行中,参数已加载");
        Console.ReadLine();
    }
}

此方法跨平台可用,子进程的命令行仅显示程序路径,完全隐藏敏感参数。

方法3:使用prctl修改进程显示名(补充优化)

配合上述方法,可以调用Linux的prctl函数设置进程的显示名称,让监控工具显示自定义名称而非默认路径:

[DllImport("libc", SetLastError = true)]
private static extern int prctl(int option, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5);

// 在Linux代码块中调用:
const int PR_SET_NAME = 15;
string processDisplayName = "MyProgram";
prctl(PR_SET_NAME, Marshal.StringToHGlobalAnsi(processDisplayName), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

该方法仅修改进程显示名,不会改变/proc/self/cmdline内容,建议和方法1或2配合使用。

内容的提问来源于stack exchange,提问作者Boyfinn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:41:29