zoukankan      html  css  js  c++  java
  • 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怎么使用呢,再说就扯的太远了,网上有不少的教程,有兴趣的可以查一下。

    整理一下,启动VS,创建一个button和一个label,在form1中复制以下代码,然后启动程序,启动扫雷,就可以看到了

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    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();
    }
    }
    }
  • 相关阅读:
    Python中的类(上)
    Django REST Framework API Guide 07
    Django REST Framework API Guide 06
    Django REST Framework API Guide 05
    Django REST Framework API Guide 04
    Django REST Framework API Guide 03
    Django REST Framework API Guide 02
    Django REST Framework API Guide 01
    Django 详解 信号Signal
    Django 详解 中间件Middleware
  • 原文地址:https://www.cnblogs.com/szytwo/p/2284435.html
Copyright © 2011-2022 走看看