| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4556 人关注过本帖, 2 人收藏
标题:c#对内存的操作~~
取消只看楼主 加入收藏
athenalux
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:河北石家庄
等 级:小飞侠
威 望:8
帖 子:975
专家分:2514
注 册:2008-11-26
结帖率:100%
收藏(2)
已结贴  问题点数:20 回复次数:1 
c#对内存的操作~~
最近一直不务正,老打算用C#写个外挂出来。
这方面对C#来说是个弱项,但并不表示无法做到。
下面写个简单的例子,和大家交流一下。
以windows中的扫雷为例,比如说读取雷的数量。
1.首先导入API(对底层的操作都要用API):
[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(uint flag,bool ihh,int processid);
openprocess是用来打开进程的,要对系统中的某一个进程进行读写,必须先打开进程。第一个参数为打开的标记,例如全权打开进程为0x1F0FFF(16进制数)。第二个没什么好说的,第三个参数为要打开进程的PID.现在第一个参数为常量,就差第三个参数PID了,PID怎么得到呢?用.net的方法是:
Process[] p = Process.GetProcessesByName("winmine");
 p[0].Id;这样就能返回相应进程的PID了。
它的返回值为相应进程的句柄。它是下面API将要使用的。
IntPtr handle = OpenProcess(0x1F0FFF, false, processid);

2.第二步就可以读取了。
[DllImport("kernel32.dll")]
private static extern bool ReadProcessMemory(IntPtr handle,int address,int[] buffer,int size,int[] nor);
readrpocessmemory可以用来读取某个进程地址的值。第一个参数就是上面API返回的值;第二个是要读取进程的地址;第三个参数为读取出的内容,要求为指针,它相当于一个out类型的参数,读出的内容并不是以函数返回值的方式得到;第四个为读取值的字节大小,int为4,byte为1,就是这样;第五个参数也要求为一个指针,一般用数组就可以了,数组名相当于指针。
int[] result=new int[1];
int[] lpdw=new int[1];//这样定义就可以了,一个元素的数组,能起到指针的作用。
bool b = ReadProcessMemory(handle, 0x1005194, result, 4, lpdw);
读出的东西到哪去了,result数组中的内容就是了。由于只有一个元素,result[0]就是你要的东西了。

基本上做外挂,读出内存是最基本的东西,一个游戏中人物的生命值,真气值,等等基础的信息如果不知道,下一步就更加无法进行了。
除了上面的两个API,还可能用到以下几个:
写内存:
        [DllImport("kernel32.dll")]
        public static extern Int32 WriteProcessMemory(
            IntPtr hProcess,
            IntPtr lpBaseAddress,
            [In, Out] byte[] buffer,
            int size,
            out IntPtr lpNumberOfBytesWritten
            );
创建线程:
 [DllImport("kernel32", EntryPoint = "CreateRemoteThread")]
        public static extern int CreateRemoteThread(
            int hProcess,
            int lpThreadAttributes,
            int dwStackSize,
            int lpStartAddress,
            int lpParameter,
            int dwCreationFlags,
            ref int lpThreadId
            );

开辟指定进程的内存空间:
        [DllImport("Kernel32.dll")]
        public static extern System.Int32 VirtualAllocEx(
         System.IntPtr hProcess,
         System.Int32 lpAddress,
         System.Int32 dwSize,
         System.Int16 flAllocationType,
         System.Int16 flProtect
         );
释放内存空间:
        [DllImport("Kernel32.dll")]
        public static extern System.Int32 VirtualFreeEx(
        int hProcess,
        int lpAddress,
        int dwSize,
        int flAllocationType
        );
关闭句柄:
        [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
        public static extern int CloseHandle(int hObject);
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
   下面说下sendmessage的问题,其实不论用API还是.net的方法,对现在的游戏都难以发挥作用,为什么呢?因为早就被屏掉了。sendmessge与sendkey其实本质上是同一个东西。现在流行的模拟按键的库winio大家可能听说过,它应用了驱动程序的相关技术,使自己运行在ring0级别上(一般程序运行在ring3级上,一些驱动程序,操作系统核心模块才运行在ring0级),这样能绕过游戏的检测。不过由于winio的名气太大,使用太大众化,所以最近可能也不能用了。
   现在流行的方法是使用CALL,CALL就是调用游戏本身内部的函数,比如攻击怪物,调用相应的攻击函数,而不是发送按键。不过找CALL是个需要知识的耐心的过程。流行的工具是OD,本菜鸟还没研究透,另外CE这个工具也是必不可少的,例如上面的地址0x1005194就是用CE找出来的,CE怎么使用呢,再说就扯的太远了,网上有不少的教程,有兴趣的可以查一下。
搜索更多相关主题的帖子: 内存 
2010-06-11 08:57
athenalux
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:河北石家庄
等 级:小飞侠
威 望:8
帖 子:975
专家分:2514
注 册:2008-11-26
收藏
得分:0 
整理一下,启动VS,创建一个button和一个label,在form1中复制以下代码,然后启动程序,启动扫雷,就可以看到了
using System;
using System.Collections.Generic;
using
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace saolei
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private const uint PROCESS_ALL_ACCESS = 0x1f0fff;
        [DllImport("kernel32.dll")]
        public extern static IntPtr OpenProcess(UInt32 dwdesiredaccess, int binherithandle, Int32 dwprocessid);
        [DllImport("kernel32.dll")]
        public extern static bool ReadProcessMemory(IntPtr hprocess, UInt32 lpbaseaddress, int[] plbuffer, UInt32 nsize, Int32[] lpnbr);
        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            Process[] p = Process.GetProcessesByName("winmine");
            IntPtr handle = OpenProcess(0x1F0FFF, 0, p[0].Id);
            int[] result = new int[1];
            int[] lpdw = new int[1];
            bool b = ReadProcessMemory(handle, 0x1005194, result, 4, lpdw);
            this.label1.Text = result[0].ToString();
        }
    }
}

QQ:81704464
2010-06-25 19:59
快速回复:c#对内存的操作~~
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017330 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved