博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#读写内存也不差
阅读量:6658 次
发布时间:2019-06-25

本文共 5389 字,大约阅读时间需要 17 分钟。

最近闲来无事发现周围的朋友都在玩《植物大战僵尸》的游戏!于是动了制作这游戏工具的念头!虽然在网上同类工具很多 但是用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) 
== 
0
) { 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) 
== 
0
) { 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 
= 
1000
; } 
//
启动无线金钱 
private 
void 
btnMoney_Click(
object 
sender, EventArgs e) {
 
if 
(Helper.GetPidByProcessName(processName) 
== 
0
) { 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) 
== 
0
) { 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 
= 
1000
; } 
private 
void 
btnGo_Click(
object 
sender, EventArgs e) {
 
if 
(Helper.GetPidByProcessName(processName) 
== 
0
) { MessageBox.Show(
"
哥们启用之前游戏总该运行吧!
"
); 
return
; } 
int 
address 
= 
ReadMemoryValue(baseAddress); 
//
读取基址(该地址不会改变) 
address 
= 
address 
+ 
0x82C
; 
//
获取2级地址 
address 
= 
ReadMemoryValue(address); address 
= 
address 
+ 
0x24
; 
int 
lev 
= 
1
; 
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 
=
0
; Process[] arrayProcess 
= 
Process.GetProcesses(); 
foreach 
(Process p 
in 
arrayProcess) {
 
if 
(p.MainWindowTitle.IndexOf(windowTitle) 
!= 
-
1
) { 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
0
; } 
//
根据窗体标题查找窗口句柄(支持模糊匹配) 
public 
static 
IntPtr FindWindow(
string 
title) { Process[] ps 
= 
Process.GetProcesses(); 
foreach 
(Process p 
in 
ps) {
 
if 
(p.MainWindowTitle.IndexOf(title)
!= 
-
1
) {
 
return 
p.MainWindowHandle; } } 
return 
IntPtr.Zero; } 
//
读取内存中的值 
public 
static 
int 
ReadMemoryValue(
int 
baseAddress,
string 
processName) {
 
try 
{
 
byte
[] buffer 
= 
new 
byte
[
4
]; IntPtr byteAddress 
= 
Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 
0
); 
//
获取缓冲区地址 
IntPtr hProcess 
= 
OpenProcess(
0x1F0FFF
, 
false
, GetPidByProcessName(processName)); ReadProcessMemory(hProcess, (IntPtr)baseAddress, byteAddress, 
4
, IntPtr.Zero); 
//
将制定内存中的值读入缓冲区 
CloseHandle(hProcess); 
return 
Marshal.ReadInt32(byteAddress); } 
catch 
{
 
return 
0
; } } 
//
将值写入指定内存地址中 
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 }, 
4
, IntPtr.Zero); CloseHandle(hProcess); } } }
本文转自黄聪博客园博客,原文链接:http://www.cnblogs.com/huangcong/archive/2010/03/26/1697053.html,如需转载请自行联系原作者
你可能感兴趣的文章
一个搞ACM需要掌握的算法
查看>>
kvm-net模式(三)
查看>>
rpmのyum详解
查看>>
Ansible配置及使用
查看>>
java inputStream ,outputStream
查看>>
系统服务
查看>>
Linux 文件与目录管理+用户管理命令
查看>>
C#中父类和子类之间相互转换
查看>>
《Linux菜鸟入门2》mail服务
查看>>
Mysql DOS: 进入Mysql运行文目录 F:\mysql-8.0.13-winx64\bin
查看>>
中小型企业网络构建之路由的简单配置
查看>>
Create an inbound email action
查看>>
oracle教程之DML事务锁定的机制
查看>>
Oracle RMAN 维护(一)--RMAN的维护
查看>>
centos6.6关闭防火墙和selinux
查看>>
JAVA RMI远程方法调用简单实例
查看>>
Citrix桌面虚拟化解决方案介绍
查看>>
WCF学习2
查看>>
python之潜心研究多线程(thread模块) 建议使用threading模块
查看>>
阵列无法解挂导致VCS双机倒换失败
查看>>