C#简易辅助脚本制作
【修改器简单介绍】
游戏外挂分为很多种类型,例如本地客户端的内存修改、远程服务器的封包破解。
一般的网游由于服务器的机能限制,并不会将游戏产生的所有数据、计算都提供给服务器来承担。经常的,服务器只会将玩家人物的属性、血量、加点、金钱、装备等重要信息储存在服务器本地,计算结果和数据传递则是通过加密封包来和客户端传输。
因此网游如果封包被破解而被用户发送伪造的封包数据将造成非常严重的后果。
【C#本地修改器】
如上所述,虽然封包的一般无法破解,但是利用服务器无法储存所有的信息这个特点,我们可以通过修改本地客户端的内存数据来制作一些建议的外挂,如修改坐标达到穿墙、加速的效果。
修改这类的本地数据,一般我们使用到 Cheatgine 来搜索内存特定数值。关于这个这工具网上已经有很多完善的教程,这边就不赘述了。
这边通过QQ连连看的示例来教程一般的C#的外挂制作。
通过Cheatgine搜索到时间、罗盘、重列的数量、本机座位的内存基址偏移量,再绘制出界面就可以开始制作。
(CheatEngine)
这边提供一个C#的内存修改读取抽象类
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, GetPid(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, GetPid(processName)); //0x1F0FFF 最高权限
WriteProcessMemory(hProcess, (IntPtr)baseAddress, new int[] { value }, 4, IntPtr.Zero);
CloseHandle(hProcess);
}
}
当然现在有不少网游有保护盾,可以防止游戏客户端内存被修改,这类的技术一般是用驱动、内核、进程挂钩完成,可以利用XT手动解除这些保护。