You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Linux下C#读取其他进程内存结果异常的问题排查

Linux下C#读取其他进程内存结果异常的问题排查

嘿,我来帮你捋捋这个问题,你遇到的情况在Linux下用C#读其他进程内存时真的挺常见的,咱们一步步拆解排查:

先看几个核心问题点

1. 你代码里的Seek参数大概率有问题

你贴的代码里fs.Seek(address, ...)没写完,正确的写法应该是fs.Seek(address, SeekOrigin.Begin),要是这里填错了起始位置(比如写成了Current或者End),那你定位的内存地址完全是错的,读出来的自然是垃圾数据,这是最可能的直接原因。

2. 读取长度和数据解析要对应上

GDB里你用的是*(uint64_t*)0x1234ABCD,也就是读8字节的64位无符号整数,但你调用自己的ReadMemory时,有没有把length参数设成8?要是你传了别的数值(比如1或者4),那读出来的字节数组肯定没法解析成正确的指针值。另外,读出来的字节数组要转成ulong类型才能和GDB的结果对比——Linux是小端字节序,直接用BitConverter.ToUInt64(buffer, 0)转换就对了,别直接把字节数组当字符串拼,那肯定出乱子。

3. 权限是绕不开的坎

GDB能读对,大概率是你用了sudo或者GDB本身有ptrace权限,但你的C#程序要是没以足够权限运行(比如普通用户身份),读取/proc/{pid}/mem时会拿到无效数据或者零填充的内容。试试用sudo dotnet run启动你的程序,再看结果。

4. 先确认目标地址的有效性

你可以先去读/proc/{pid}/maps文件,找一找0x1234ABCD这个地址在不在进程的有效内存映射里,还要看对应的映射段是不是有r--p(可读)的权限。要是这个地址根本没被映射到物理内存,读出来的肯定是垃圾。

给你调整后的参考代码

我把你没写完的部分补全,还加了一些错误检查:

public static byte[] ReadMemory(int pid, long address, int length)
{
    try
    {
        string memPath = $"/proc/{pid}/mem";
        Console.WriteLine($"Reading memory from: {memPath}");

        using (FileStream fs = new FileStream(memPath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = new byte[length];
            // 必须用SeekOrigin.Begin定位到目标虚拟地址
            fs.Seek(address, SeekOrigin.Begin);
            int actualRead = fs.Read(buffer, 0, length);
            
            // 检查实际读取的字节数,避免返回不完整的无效数据
            if (actualRead != length)
            {
                Console.WriteLine($"Warning: Only read {actualRead} bytes (requested {length})");
                Array.Resize(ref buffer, actualRead);
            }
            return buffer;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error reading memory: {ex.Message}");
        return null;
    }
}

调用的时候要注意传对参数,还要做正确的类型转换:

// 替换成你的目标进程PID和地址
int targetPid = 1234;
long targetAddr = 0x1234ABCD;
// 读8字节对应uint64_t
byte[] memBytes = ReadMemory(targetPid, targetAddr, 8);

if (memBytes != null && memBytes.Length == 8)
{
    ulong pointerValue = BitConverter.ToUInt64(memBytes, 0);
    Console.WriteLine($"读取到的指针值: 0x{pointerValue:X8}");
}

最后再试几个排查步骤

  • 先确认你的C#程序以root权限运行
  • 核对ReadMemorylength参数是8
  • 检查/proc/{pid}/maps确认目标地址的有效性

备注:内容来源于stack exchange,提问作者ThePrime

火山引擎 最新活动