当前位置: 代码网 > it编程>编程语言>Asp.net > C#调用Windows API实现进程内存读写操作

C#调用Windows API实现进程内存读写操作

2026年08月09日 Asp.net 我要评论
前言软件开发中,有时我们需要对其他程序的内存进行读取或修改,例如用于游戏调试、系统监控、逆向分析等场景。windows 提供了一组强大的 api 函数,允许我们实现对其他进程内存的操作。本文将介绍如何

前言

软件开发中,有时我们需要对其他程序的内存进行读取或修改,例如用于游戏调试、系统监控、逆向分析等场景。windows 提供了一组强大的 api 函数,允许我们实现对其他进程内存的操作。

本文将介绍如何使用 c# 调用 windows api 实现对目标进程内存的读取与写入,并通过一个完整的示例程序演示其具体应用。

1、基础知识

在开始之前,我们需要了解以下几个关键的 windows api 函数:

  • openprocess:获取目标进程的句柄
  • readprocessmemory:读取目标进程的内存数据
  • writeprocessmemory:向目标进程内存写入数据
  • virtualallocex:在目标进程中分配内存(可选)
  • virtualfreeex:释放目标进程中的内存(可选)

这些函数都定义在 kernel32.dll 中,可以通过 dllimport 导入使用。

2、示例目标程序

我们先创建一个简单的 windows 窗体应用程序作为目标程序。该程序包含一个计数器,每秒递增一次,并显示当前值及其内存地址。

public partialclassform1 : form
{
    privateint counter = 100;
    private thread counterthread;
    privatebool isrunning = false;
    public form1()
    {
        initializecomponent();
    }
    private void startcounter()
    {
        if (isrunning) return;
        isrunning = true;
        counterthread = new thread(() =>
        {
            while (isrunning)
            {
                this.invoke((methodinvoker)delegate
                {
                    unsafe
                    {
                        fixed (int* ptr = &counter)
                        {
                            lblcounter.text = $"{counter}";
                            txtaddress.text = $"0x{(intptr)ptr:x}";
                        }
                    }
                });
                thread.sleep(1000);
                counter++;
            }
        });
        counterthread.isbackground = true;
        counterthread.start();
    }
    private void stopcounter()
    {
        isrunning = false;
        if (counterthread != null && counterthread.isalive)
        {
            counterthread.join(1000);
        }
    }
    private void btnstart_click(object sender, eventargs e)
    {
        startcounter();
        btnstart.enabled = false;
        btnstop.enabled = true;
    }
    private void btnstop_click(object sender, eventargs e)
    {
        stopcounter();
        btnstart.enabled = true;
        btnstop.enabled = false;
    }
    protected override void onformclosing(formclosingeventargs e)
    {
        stopcounter();
        base.onformclosing(e);
    }
}

3、内存修改器程序

下面是一个完整的内存修改器程序,可以读取和修改上面目标程序的计数器值:

public partialclassform1 : form
{
    [dllimport("kernel32.dll")]
    public static extern intptr openprocess(int dwdesiredaccess, bool binherithandle, int dwprocessid);
    [dllimport("kernel32.dll")]
    public static extern bool readprocessmemory(intptr hprocess, intptr lpbaseaddress, byte[] lpbuffer, int dwsize, ref int lpnumberofbytesread);
    [dllimport("kernel32.dll")]
    public static extern bool writeprocessmemory(intptr hprocess, intptr lpbaseaddress, byte[] lpbuffer, int dwsize, ref int lpnumberofbyteswritten);
    privateconstint process_all_access = 0x1f0fff;
    private intptr processhandle;
    private process targetprocess;
    public form1()
    {
        initializecomponent();
    }
    private void btnread_click(object sender, eventargs e)
    {
        try
        {
            targetprocess = process.getprocessesbyname(txtprocessname.text)[0];
            processhandle = openprocess(process_all_access, false, targetprocess.id);
            intptr memoryaddress = (intptr)convert.toint64(txtmemoryaddress.text, 16);
            byte[] buffer = newbyte[4];
            int bytesread = 0;
            if (readprocessmemory(processhandle, memoryaddress, buffer, buffer.length, ref bytesread))
            {
                intvalue = bitconverter.toint32(buffer, 0);
                lblcurrentvalue.text = value.tostring();
            }
            else
            {
                messagebox.show("读取内存失败!");
            }
        }
        catch (exception ex)
        {
            messagebox.show($"发生错误:{ex.message}");
        }
    }
    private void btnwrite_click(object sender, eventargs e)
    {
        try
        {
            if (processhandle == intptr.zero)
            {
                messagebox.show("请先读取内存!");
                return;
            }
            intptr memoryaddress = (intptr)convert.toint64(txtmemoryaddress.text, 16);
            int newvalue = convert.toint32(txtnewvalue.text);
            byte[] buffer = bitconverter.getbytes(newvalue);
            int byteswritten = 0;
            if (writeprocessmemory(processhandle, memoryaddress, buffer, buffer.length, ref byteswritten))
            {
                messagebox.show("写入成功!");
                btnread_click(sender, e); // 刷新显示
            }
            else
            {
                messagebox.show("写入内存失败!");
            }
        }
        catch (exception ex)
        {
            messagebox.show($"发生错误:{ex.message}");
        }
    }
}

4、使用说明

  • 1、首先运行目标程序(targetapplication)
  • 2、运行内存修改器(memoryeditor)
  • 3、使用工具如 cheat engine 找到目标程序中 counter 变量的内存地址(本例中直接通过指针获取)
  • 4、在内存修改器中输入进程名和内存地址
  • 5、点击“读取”按钮查看当前值
  • 6、输入新值并点击“写入”按钮修改内存

5、注意事项

1、实际使用时需注意:

  • 确保具有足够的系统权限
  • 注意目标程序的保护机制
  • 内存地址可能动态变化,需要实时更新

2、在 64 位系统上运行时:

  • 需要处理进程权限问题
  • 地址空间差异较大
  • 数据类型大小可能需要调整

总结

通过调用 windows api,我们可以使用 c# 对其他进程的内存进行读写操作。这种技术广泛应用于程序调试、系统监控、游戏辅助等领域。虽然功能强大,但在实际使用过程中需要注意权限控制、内存地址变化以及目标程序的安全机制等问题。

本文提供了一个完整的示例代码,帮助开发快速理解并实践这一技术。希望对你在学习和项目开发中有所帮助。

以上就是c#调用windows api实现进程内存读写操作的详细内容,更多关于c# windows api进程内存读写的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com