原文:[转]C#内存操作

最近闲来无事发现周围的朋友都在玩《植物大战僵尸》的游戏!于是动了制作这游戏工具的念头!虽然在网上同类工具很多 但是用C#写的我几乎看不到!所以我想用C#写一个!
  首先用CE或者OD或者其他反汇编工具找出游戏的内存基址!
  游戏内存基址:base = 0x006A9EC0
  游戏阳光地址:[base+0x768]+0x5560
  游戏金钱地址:[base+0x82C]+0x28
  游戏关卡地址:[base+0x82C]+0x24 //关卡如:A-B 实际值为:(A-1)×10+B
至于如何获取这些地址不在我们这论坛研究的范围中!
对了我是用工具vs2008编写的!
新建窗体:
C# code

using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms; namespace PlantsVsZombiesTool
{
/// <summary>
///
/// </summary>
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void Form1_Load(object sender, EventArgs e)
{ } //启动无线阳光
private void btnGet_Click(object sender, EventArgs e)
{
if (Helper.GetPidByProcessName(processName) == )
{
MessageBox.Show("哥们启用之前游戏总该运行吧!");
return;
}
if (btnGet.Text == "启用-阳光无限")
{
timer1.Enabled = true;
btnGet.Text = "关闭-阳光无限";
}
else
{
timer1.Enabled = false;
btnGet.Text = "启用-阳光无限";
}
} private void timer1_Tick(object sender, EventArgs e)
{ if (Helper.GetPidByProcessName(processName) == )
{
timer1.Enabled = false;
btnGet.Text = "启用-阳光无限";
}
int address = ReadMemoryValue(baseAddress); //读取基址(该地址不会改变)
address = address + 0x768; //获取2级地址
address = ReadMemoryValue(address);
address = address + 0x5560; //获取存放阳光数值的地址
WriteMemory(address, 0x1869F); //写入数据到地址(0x1869F表示99999)
timer1.Interval = ;
} //启动无线金钱
private void btnMoney_Click(object sender, EventArgs e)
{ if (Helper.GetPidByProcessName(processName) == )
{
MessageBox.Show("哥们启用之前游戏总该运行吧!");
return;
}
if (btnMoney.Text == "启用-金钱无限")
{
timer2.Enabled = true;
btnMoney.Text = "关闭-金钱无限";
}
else
{
timer2.Enabled = false;
btnMoney.Text = "启用-金钱无限";
}
} private void timer2_Tick(object sender, EventArgs e)
{
if (Helper.GetPidByProcessName(processName) == )
{
timer2.Enabled = false;
btnMoney.Text = "启用-金钱无限";
}
int address = ReadMemoryValue(baseAddress); //读取基址(该地址不会改变)
address = address + 0x82C; //获取2级地址
address = ReadMemoryValue(address);
address = address + 0x28; //得到金钱地址
WriteMemory(address, 0x1869F); //写入数据到地址(0x1869F表示99999)
timer2.Interval = ;
} private void btnGo_Click(object sender, EventArgs e)
{
if (Helper.GetPidByProcessName(processName) == )
{
MessageBox.Show("哥们启用之前游戏总该运行吧!");
return;
}
int address = ReadMemoryValue(baseAddress); //读取基址(该地址不会改变)
address = address + 0x82C; //获取2级地址
address = ReadMemoryValue(address);
address = address + 0x24;
int lev = ;
try
{
lev = int.Parse(txtLev.Text.Trim());
}
catch
{
MessageBox.Show("输入的关卡格式不真确!默认设置为1");
} WriteMemory(address, lev); } //读取制定内存中的值
public int ReadMemoryValue(int baseAdd)
{
return Helper.ReadMemoryValue(baseAdd, processName);
} //将值写入指定内存中
public void WriteMemory(int baseAdd, int value)
{
Helper.WriteMemoryValue(baseAdd, processName, value);
} private int baseAddress = 0x006A9EC0; //游戏内存基址
private string processName = "PlantsVsZombies"; //游戏进程名字
}
}

下面这个类是整个工具的核心

C# code

using System;
using System.Text; using System.Diagnostics;
using System.Runtime.InteropServices; namespace PlantsVsZombiesTool
{ public abstract class Helper
{
[DllImportAttribute("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern bool ReadProcessMemory
(
IntPtr hProcess,
IntPtr lpBaseAddress,
IntPtr lpBuffer,
int nSize,
IntPtr lpNumberOfBytesRead
); [DllImportAttribute("kernel32.dll", EntryPoint = "OpenProcess")]
public static extern IntPtr OpenProcess
(
int dwDesiredAccess,
bool bInheritHandle,
int dwProcessId
); [DllImport("kernel32.dll")]
private static extern void CloseHandle
(
IntPtr hObject
); //写内存
[DllImportAttribute("kernel32.dll", EntryPoint = "WriteProcessMemory")]
public static extern bool WriteProcessMemory
(
IntPtr hProcess,
IntPtr lpBaseAddress,
int[] lpBuffer,
int nSize,
IntPtr lpNumberOfBytesWritten
); //获取窗体的进程标识ID
public static int GetPid(string windowTitle)
{
int rs = ;
Process[] arrayProcess = Process.GetProcesses();
foreach (Process p in arrayProcess)
{
if (p.MainWindowTitle.IndexOf(windowTitle) != -)
{
rs = p.Id;
break;
}
} return rs;
} //根据进程名获取PID
public static int GetPidByProcessName(string processName)
{
Process[] arrayProcess = Process.GetProcessesByName(processName); foreach (Process p in arrayProcess)
{
return p.Id;
}
return ;
} //根据窗体标题查找窗口句柄(支持模糊匹配)
public static IntPtr FindWindow(string title)
{
Process[] ps = Process.GetProcesses();
foreach (Process p in ps)
{
if (p.MainWindowTitle.IndexOf(title) != -)
{
return p.MainWindowHandle;
}
}
return IntPtr.Zero;
} //读取内存中的值
public static int ReadMemoryValue(int baseAddress,string processName)
{
try
{
byte[] buffer = new byte[];
IntPtr byteAddress = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, ); //获取缓冲区地址
IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName));
ReadProcessMemory(hProcess, (IntPtr)baseAddress, byteAddress, , IntPtr.Zero); //将制定内存中的值读入缓冲区
CloseHandle(hProcess);
return Marshal.ReadInt32(byteAddress);
}
catch
{
return ;
}
} //将值写入指定内存地址中
public static void WriteMemoryValue(int baseAddress, string processName, int value)
{
IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName)); //0x1F0FFF 最高权限
WriteProcessMemory(hProcess, (IntPtr)baseAddress, new int[] { value }, , IntPtr.Zero);
CloseHandle(hProcess);
}
}
}

C#内存操作的更多相关文章

  1. java 21-11 数据输入、输出流和内存操作流

    IO数据流: 可以读写基本数据类型的数据 数据输入流:DataInputStream DataInputStream(InputStream in)   数据输出流:DataOutputStream ...

  2. 【转】《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误

    原文地址:http://blog.csdn.net/slvher/article/details/9150597 对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构 ...

  3. c++ void,内存操作函数

    void的含义 void的字面意思是“无类型”, void * 则为“无类型指针”, void * 可以指向任何类型的数据 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变 ...

  4. java基础知识回顾之javaIO类--内存操作流ByteArrayInputStream和ByteArrayOutputSteam(操作字节数组)

    直接看代码: package cn.itcast.io.p6.bytestream; import java.io.ByteArrayInputStream; import java.io.ByteA ...

  5. Java API —— IO流(数据操作流 & 内存操作流 & 打印流 & 标准输入输出流 & 随机访问流 & 合并流 & 序列化流 & Properties & NIO)

    1.操作基本数据类型的流     1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出 ...

  6. 【C++基础】内存操作 getMemory改错

    内存操作的考察点:①指针 ②变量生存期及作用范围 ③动态内存申请和释放 笔试题************************************************************* ...

  7. 《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误

    对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的模块跑起来后才出现内存崩溃,是很让人痛苦的.因为崩溃的位置在时间和空间上,通常是在距真正的错误源一段距离之后才 ...

  8. Java基础知识强化之IO流笔记58:内存操作流

    1. 内存操作流: 用来操作处理临时存储的信息的. (1)操作字节数组: ByteArrayInputStream ByteArrayOutputStream 代码示例: package cn.itc ...

  9. C语言嵌入式系统编程修炼之三:内存操作

    数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力.在嵌入式系统的实际调试中,多借助C语言指针所具 ...

  10. Marshal 类的内存操作的一般功能

    Marshal类 提供了一个方法集,这些方法用于分配非托管内存.复制非托管内存块.将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法. 命名空间:System.Runtim ...

随机推荐

  1. Yii console 创建命令行应用

    大家都知道PHP的程序没有进程概念,而且生命周期极短,无法实现一些定时计划或者是计划任务,今天我们看看在YII框架中如何使用计划任务创建命令行应用. 1.在 console/controllers 文 ...

  2. java学习:AWT组件和事件处理的笔记(1)--文本框

    java.awt包中的TextField类是专门用来建立文本框的,即TextField类创建的一个对象便是一个文本框. 1.TextField类的主要方法    (1)TextField()      ...

  3. 今天在研究jquery用ajax提交form表单中得数据时,学习到了一种新的提交方式

    今天在研究jquery用ajax提交form表单中得数据时,学习到了一种新的提交方式 jquery中的serialize() 方法 该方法通过序列化表单值,创建 URL 编码文本字符串 序列化的值可在 ...

  4. 解决Java调用Azure SDK证书错误javax.net.ssl.SSLHandshakeException

    Azure作为微软的公有云平台,提供了非常丰富的SDK和API让开发人员可以非常方便的调用的各项服务,目前除了自家的.NET, Java, Python, nodeJS, Ruby,PHP等语言都提供 ...

  5. C# 如何获取当前应用程序的父目录

    //获取当前运行路径的上级目录(父目录) System.IO.DirectoryInfo topDir = System.IO.Directory.GetParent(System.Environme ...

  6. Unix/Linux环境C编程入门教程(27) 内存那些事儿

    calloc() free() getpagesize() malloc() mmap() munmap()函数介绍 calloc(配置内存空间) 相关函数 malloc,free,realloc,b ...

  7. mfc窗口,父窗口parentwindow,所有者窗口ownerwindow 区别

    一. parent:创建者,owner:所有者 小玉的父母生下小玉,养到8岁,卖给贾府当丫头小玉的父母是parent,贾府是owner 二. 1.Pop-up窗口: 一个弹出窗口是必须具有WS_POP ...

  8. C与C++动态分配二维数组

    C: C中使用函数malloc和free两个函数. //动态分配M*N维 int **a=(int **)malloc(sizeof(int*)*M); ;i<M;i++) a[i]=(int ...

  9. hdu 1698 Just a Hook_线段树

    题意:给你个n,表示区间[1,n],价值初始为1,给你m段区间和价值,更新区间,区间价值以最后更新为准,问更新后区间价值总和为多少 思路:两种方法,可以先存下来,倒过来更新,一更新节点马上跳出,比较快 ...

  10. hdu 2665 Kth number_划分树

    题意:求区间[a,b]的第k大 因为多次询问要用到划分树 #include <iostream> #include<cstdio> #include<algorithm& ...