一个共公类 Data.cs ,用于存放游戏的 信息,如人物属性,
1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4 using System.Linq; 5 using System.Runtime.InteropServices; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace huojuzhiguang 10 { 11 12 public class Game 13 { 14 public static String gameName = "Torchlight2"; //游戏的进程名称 15 public static bool findGame = false; 16 17 } 18 public class Role 19 { 20 public static int Name_Addr; //人物名称地址 21 public static int Level_Addr; //等级地址 22 public static int Strength_Addr; //力量 23 public static int Dexterity_Addr; //敏捷 24 public static int Wit_Addr; //智力 25 public static int Tizhi_Addr; //体质 26 public static int ShuXingDian_Addr; //属性点 27 public static int JiNengDian_Addr; //技能点 28 public static int Money_Addr; //金币 29 public static int Move_Addr; //移动速度 30 31 } 32 public class ZhuangBei 33 { 34 public static int Name_Addr; //装备名称 35 public static int wlgj_Addr1; //物理攻击1 36 public static int wlgj_Addr2; //物理攻击2 37 public static int wlfy_Addr1; //物理防御1 38 public static int wlfy_Addr2; //物理防御2 39 public static int fmcs_Addr; //附魔次数 40 public static int kongshu_Addr; //孔数 41 42 } 43 44 public class Pet 45 { 46 public static int Level_Addr; //宠物等级 47 public static int XueLiang_Addr; //宠物血量 48 public static int MoFa_Addr; //宠物魔法 49 public static int Jingyan_Addr; //宠物经验 50 public static int Move_Addr; //宠物经验 51 } 52 }
写一个共公方法 OperateMemory.cs ,减少窗体内的的代码
1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4 using System.Linq; 5 using System.Runtime.CompilerServices; 6 using System.Runtime.InteropServices; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace huojuzhiguang 11 { 12 public class OperateMemory 13 { 14 /// <summary> 15 /// 从指定内存中读取字节集数据 16 /// </summary> 17 /// <param name="hProcess">进程句柄</param> 18 /// <param name="pvAddressRemote">内存地址</param> 19 /// <param name="pvBufferLocal">数据存储变量</param> 20 /// <param name="dwSize">长度</param> 21 /// <param name="pdwNumBytesRead">读取长度</param> 22 23 #region 引入DLL 24 private const uint PROCESS_ALL_ACCESS = 0x1f0fff; 25 [DllImport("kernel32.dll")] 26 private extern static IntPtr OpenProcess(uint dwDesiredAccess,int bInheritHandle,int dwProcessId); 27 28 29 [DllImport("kernel32.dll")] 30 private extern static bool ReadProcessMemory(IntPtr hProcess, UInt32 pvAddressRemote, int[] pvBufferLocal, UInt32 dwSize, Int32[] pdwNumBytesRead); 31 32 [DllImportAttribute("kernel32.dll", EntryPoint = "WriteProcessMemory")] 33 private static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, int[] lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten); 34 [DllImportAttribute("kernel32.dll", EntryPoint = "WriteProcessMemory")] 35 private static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, int lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten); 36 37 #endregion 38 39 private static Process[] p = Process.GetProcessesByName(Game.gameName); //读取游戏进程 40 private static IntPtr handle = OpenProcess(0x1F0FFF, 0, p[0].Id); //获取句柄权限 41 42 /// <summary> 43 /// 判断游戏是否已运行 44 /// </summary> 45 /// <param name="gameName">程序进程名</param> 46 /// <returns>false 未运行,true已运行</returns> 47 public static Boolean findGame(String gameName) 48 { 49 if (p == null || p.Length < 1) 50 { 51 return Game.findGame = false; 52 } 53 else 54 { 55 return Game.findGame = true; 56 } 57 58 } 59 60 /// <summary> 61 /// 读取内存,int默认读取4个字节 62 /// </summary> 63 /// <param name="readAddr">读取地址</param> 64 /// <returns></returns> 65 public static Int32 readMemory(UInt32 readAddr) 66 { 67 int[] result = new int[1]; 68 int[] lpdw = new int[1]; 69 bool b = ReadProcessMemory(handle, readAddr, result, 4, lpdw); 70 return result[0]; 71 } 72 73 /// <summary> 74 /// 读取内存,数组为[基址,便宜地址] 75 /// </summary> 76 /// <param name="readAddr">读取地址</param> 77 /// <returns></returns> 78 public static Int32 readMemory(int[] readAddr) 79 { 80 int values = 0; 81 for (int i = 0; i < readAddr.Length; i++) 82 { 83 values = readMemory((uint)(values + readAddr[i])); 84 } 85 return values; 86 } 87 88 /// <summary> 89 /// 读取内存,数组为[基址,便宜地址] 90 /// </summary> 91 /// <param name="readAddr">读取地址</param> 92 /// <param name="addr">数值存放的逻辑地址</param> 93 /// <returns></returns> 94 public static Int32 readMemory(int[] readAddr,out int addr) 95 { 96 int values = 0; 97 int temp=0; //临时存放人物属性的逻辑地址 98 for (int i = 0; i < readAddr.Length; i++) 99 { 100 temp = values + readAddr[i]; 101 values = readMemory((uint)(values + readAddr[i])); 102 } 103 addr = temp; 104 return values; 105 } 106 107 /// <summary> 108 /// 写入内存4字节 109 /// </summary> 110 /// <param name="writeAddr">写入地址</param> 111 /// <param name="writeNumber">写入数值</param> 112 public static void writeMemory(UInt32 writeAddr, UInt32 writeNumber) 113 { 114 Process[] p = Process.GetProcessesByName(Game.gameName); 115 IntPtr handle = OpenProcess(0x1F0FFF, 0, p[0].Id); 116 WriteProcessMemory(handle, (IntPtr)writeAddr, new int[] { Convert.ToInt32(writeNumber) }, 4, IntPtr.Zero); 117 } 118 119 /// <summary> 120 /// 写入内存,类型Byte,1字节 121 /// </summary> 122 /// <param name="writeAddr">写入地址</param> 123 /// <param name="writeNumber">写入数值</param> 124 public static void writeByte(UInt32 writeAddr, UInt32 writeNumber) 125 { 126 WriteProcessMemory(handle, (IntPtr)writeAddr, new int[] { Convert.ToInt32(writeNumber) }, 1, IntPtr.Zero); 127 } 128 129 /// <summary> 130 /// 读取文本 131 /// </summary> 132 /// <param name="readAddr">读取地址</param> 133 /// <param name="str_length">读取长度</param> 134 /// <returns>读取内存中的 文本内容,文本长度就是偶数,且2位字节表示一个汉字</returns> 135 public static string readText(int[] readAddr, int str_length) 136 { 137 str_length = str_length * 2;//Unicode每个字符占用2个字节 138 int nameAddr; // 读取每个字节时,放入此临时变量 139 byte[] num_String = new byte[str_length]; //存放读取的内容 140 byte[] arr1 = new byte[str_length]; //存放整理后的内容 141 for (int i = 0; i < str_length; i++) 142 { 143 readMemory(readAddr, out nameAddr).ToString();//此处读取每个字节 144 num_String[i] = (byte)readMemory((uint)nameAddr + (uint)i); 145 } 146 for (int i = 0; i < num_String.Length; i++) 147 { 148 arr1[i] = num_String[i]; 149 if (i > 0 && i % 2 == 1) 150 { 151 swap(ref arr1[i - 1], ref arr1[i]); 152 } 153 } 154 return System.Text.Encoding.BigEndianUnicode.GetString(arr1); 155 } 156 157 /// <summary> 158 /// 读取float数值 159 /// </summary> 160 /// <param name="readAddr">读取地址</param> 161 /// <returns>/浮点类型的单精度值具有 4 个字节,所以此次数组下标没写成动态的</returns> 162 public static Int32 readMemoryFloat(UInt32 readAddr) 163 { 164 int[] result = new int[1]; 165 int[] lpdw = new int[1]; 166 bool b = ReadProcessMemory(handle, readAddr, result, 1, lpdw); 167 return result[0]; 168 } 169 170 /// <summary> 171 /// 读取float数值 172 /// </summary> 173 /// <param name="readAddr">读取地址</param> 174 /// <param name="addr">数值存放的逻辑地址</param> 175 /// <returns>/浮点类型的单精度值具有 4 个字节,所以此次数组下标没写成动态的</returns> 176 public static float readMemoryFloat(int[] readAddr, out int addr) 177 { 178 int values = 0; 179 byte[] valuesF = new byte[4]; 180 for (int i = 0; i < readAddr.Length - 1; i++) 181 { 182 values = readMemory((uint)(values + readAddr[i])); //拿到最后偏移地址的上一次地址(后面与得到最后地址,而非数值) 183 } 184 for (int j = 0; j <= 3; j++) 185 { 186 valuesF[j] = (byte)readMemoryFloat((uint)(values + readAddr[readAddr.Length - 1] + j)); 187 } 188 addr = values + readAddr[readAddr.Length - 1]; 189 float result = BitConverter.ToSingle(valuesF, 0); 190 return result; 191 192 } 193 /// <summary> 194 /// 写入float数值 195 /// </summary> 196 /// <param name="writeAddr">读取地址</param> 197 /// <param name="value">写入的float数值</param> 198 public static void writeMemoryFloat(UInt32 writeAddr, float value) 199 { 200 byte[] byteArray = BitConverter.GetBytes(value); 201 202 for (int i = 0; i <= byteArray.Length-1; i++) 203 { 204 writeByte((uint)writeAddr + (uint)i, byteArray[i]); 205 } 206 207 } 208 209 //交换数组的两个元素 210 private static void swap(ref byte num1,ref byte num2) 211 { 212 byte temp; 213 temp = num1; 214 num1 = num2; 215 num2 = temp; 216 } 217 } 218 }
然后就是 窗体上的按钮 相应的 事件
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.ComponentModel; 5 using System.Data; 6 using System.Diagnostics; 7 using System.Drawing; 8 using System.Linq; 9 using System.Text; 10 using System.Threading.Tasks; 11 using System.Windows.Forms; 12 13 namespace huojuzhiguang 14 { 15 public partial class hjzg : Form 16 { 17 public hjzg() 18 { 19 InitializeComponent(); 20 } 21 22 public void btn_readData_Click(object sender, EventArgs e) 23 { 24 try 25 { 26 lab_Role_Name.Text = OperateMemory.readText(new[] { 0x0289F22C, 0x34, 0x14, 0x5F0 }, 20); //角色名称 27 lab_Role_SW.Text = (OperateMemory.readText(new[] { 0x0289F22C, 0x34, 0x14, 0x9985c }, 20)); //角色声望 28 txt_Role_Move.Text = OperateMemory.readMemoryFloat(new int[] { 0x0289F22C, 0x34, 0x14, 0x2A0 }, out Role.Move_Addr).ToString(); //角色奔跑速度 29 txt_Level.Text = OperateMemory.readMemory(new int[] { 0x0289F22C, 0x34, 0x14, 0x110 }, out Role.Level_Addr).ToString(); //等级 30 txt_Strength.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x578 }, out Role.Strength_Addr).ToString();//力量 31 txt_Dexterity.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x574 }, out Role.Dexterity_Addr).ToString();//敏捷 32 txt_Wit.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x580 }, out Role.Wit_Addr).ToString();//智力 33 txt_Tizhi.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x57C }, out Role.Tizhi_Addr).ToString();//体质 34 txt_ShuXingDian.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x5A8 }, out Role.ShuXingDian_Addr).ToString();//属性点 35 txt_JingNengDian.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x5AC }, out Role.JiNengDian_Addr).ToString();//技能点 36 txt_Money.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x0249F22C, 0x34, 0x14, 0x590 }, out Role.Money_Addr).ToString();//金币 37 38 btn_write.Enabled = true;// 保存人物属性按钮 39 40 } 41 catch (Exception) 42 { 43 } 44 45 } 46 47 private void btn_write_Click(object sender, EventArgs e) 48 { 49 try 50 { 51 if (lab_Role_Name.Text.Length <= 0) 52 { 53 MessageBox.Show("游戏保存错误!"); 54 } 55 56 OperateMemory.writeMemory((uint)Role.Level_Addr, (uint)int.Parse(txt_Level.Text)); 57 OperateMemory.writeMemory((uint)Role.Strength_Addr, (uint)int.Parse(txt_Strength.Text)); 58 OperateMemory.writeMemory((uint)Role.Dexterity_Addr, (uint)int.Parse(txt_Dexterity.Text)); 59 OperateMemory.writeMemory((uint)Role.Wit_Addr, (uint)int.Parse(txt_Wit.Text)); 60 OperateMemory.writeMemory((uint)Role.Tizhi_Addr, (uint)int.Parse(txt_Tizhi.Text)); 61 OperateMemory.writeMemory((uint)Role.ShuXingDian_Addr, (uint)int.Parse(txt_ShuXingDian.Text)); //属性点 62 OperateMemory.writeMemory((uint)Role.JiNengDian_Addr, (uint)int.Parse(txt_JingNengDian.Text)); //技能点 63 OperateMemory.writeMemory((uint)Role.Money_Addr, (uint)int.Parse(txt_Money.Text)); //金币 64 OperateMemory.writeMemoryFloat((uint)Role.Move_Addr, float.Parse(txt_Role_Move.Text));//角色奔跑速度 65 } 66 catch (Exception) 67 { 68 } 69 } 70 71 private void timer_findGame_Tick(object sender, EventArgs e) 72 { 73 try 74 { 75 if (OperateMemory.findGame(Game.gameName)) 76 { 77 lab_State.Text = "游戏已运行!"; 78 if (OperateMemory.readMemory(new int[] { 0x0289F22C, 0x34, 0x14, 0x110 }) >= 1) 79 { 80 txt_Level.Enabled = true; 81 txt_Strength.Enabled = true; 82 txt_Dexterity.Enabled = true; 83 txt_Wit.Enabled = true; 84 txt_Tizhi.Enabled = true; 85 txt_ShuXingDian.Enabled = true; 86 txt_JingNengDian.Enabled = true; 87 txt_Money.Enabled = true; //金币 88 txt_Role_Move.Enabled = true; 89 90 btn_readData.Enabled = true; //读取人物属性按钮 91 } 92 93 } 94 else 95 { 96 lab_State.Text = "抱歉,游戏未运行!"; 97 txt_Level.Text = ""; 98 txt_Level.Enabled = false; 99 100 txt_Strength.Text = ""; 101 txt_Strength.Enabled = false; 102 103 txt_Dexterity.Text = ""; 104 txt_Dexterity.Enabled = false; 105 106 txt_Wit.Text = ""; 107 txt_Wit.Enabled = false; 108 109 txt_Tizhi.Text = ""; 110 txt_Tizhi.Enabled = false; 111 112 txt_ShuXingDian.Text = ""; 113 txt_ShuXingDian.Enabled = false; 114 115 txt_JingNengDian.Text = ""; 116 txt_JingNengDian.Enabled = false; 117 118 txt_Money.Text = ""; 119 txt_Money.Enabled = false; 120 121 txt_Role_Move.Text= ""; 122 txt_Role_Move.Enabled = false; 123 124 btn_readData.Enabled = false; //读取人物属性 125 btn_write.Enabled = false; //保存人物属性 126 127 } 128 } 129 catch (Exception ex) 130 { 131 } 132 } 133 134 private void btn_ReadZB_Click(object sender, EventArgs e) 135 { 136 137 try 138 { 139 txt_ZBName.Text = ""; 140 txt_ZBName.Text = OperateMemory.readText(new[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0xA0 }, 20); 141 if (txt_ZBName.Text.Length <= 0) 142 { 143 MessageBox.Show("请将物品放入附魔窗体内!","头上有小闪电"); 144 return; 145 } 146 txt_ZBwlgj.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0x134 }, out ZhuangBei.wlgj_Addr1).ToString();//物理攻击1 147 txt_ZBwlgj.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0x138 }, out ZhuangBei.wlgj_Addr2).ToString();//物理攻击2 148 149 txt_ZBwlfy.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0x140 }, out ZhuangBei.wlfy_Addr1).ToString();//物理防御1 150 txt_ZBwlfy.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0x13C }, out ZhuangBei.wlfy_Addr2).ToString();//物理防御2 151 152 txt_ZBfmcs.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0x148 }, out ZhuangBei.fmcs_Addr).ToString();//附魔次数 153 com_ZBks.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x03437E04, 0x18, 0x98, 0x1D4 }, out ZhuangBei.kongshu_Addr).ToString();//打孔数 154 155 } 156 catch (Exception ex) 157 { 158 159 } 160 } 161 162 private void btn_ZBSave_Click(object sender, EventArgs e) 163 { 164 try 165 { 166 if (txt_ZBName.Text.Length <= 0) 167 { 168 MessageBox.Show("请将物品放入附魔窗体内!", "头上有小闪电"); 169 return; 170 } 171 OperateMemory.writeMemory((uint)ZhuangBei.wlgj_Addr1, (uint)int.Parse(txt_ZBwlgj.Text));//物理攻击1 172 OperateMemory.writeMemory((uint)ZhuangBei.wlgj_Addr1, (uint)int.Parse(txt_ZBwlgj.Text));//物理攻击2 173 174 OperateMemory.writeMemory((uint)ZhuangBei.wlfy_Addr1, (uint)int.Parse(txt_ZBwlfy.Text));//物理防御1 175 OperateMemory.writeMemory((uint)ZhuangBei.wlfy_Addr2, (uint)int.Parse(txt_ZBwlfy.Text));//物理防御2 176 177 OperateMemory.writeMemory((uint)ZhuangBei.fmcs_Addr, (uint)int.Parse(txt_ZBfmcs.Text));//附魔次数 178 OperateMemory.writeMemory((uint)ZhuangBei.kongshu_Addr, (uint)int.Parse(com_ZBks.Text));//打孔数 179 } 180 catch (Exception) 181 { 182 } 183 } 184 private void btn_CWread_Click(object sender, EventArgs e) 185 { 186 try 187 { 188 lab_Pet_Name.Text = OperateMemory.readText(new[] { 0x00400000 + 0x31C6674, 0x14, 0x3b5f0 }, 20); 189 txt_CWLevel.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x31C6674, 0x14, 0x3b110 }, out Pet.Level_Addr).ToString(); //宠物等级 190 txt_Pet_XueL.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x31C6674, 0x14, 0x3b564 }, out Pet.XueLiang_Addr).ToString(); //宠物血量 191 txt_Pet_MF.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x31C6674, 0x14, 0x3b588 }, out Pet.MoFa_Addr).ToString(); //宠物魔法 192 txt_CWJingyan.Text = OperateMemory.readMemory(new int[] { 0x00400000 + 0x31C6674, 0x14, 0x3b594 }, out Pet.Jingyan_Addr).ToString(); //宠物经验 193 txt_Pet_Move.Text = OperateMemory.readMemoryFloat(new int[] { 0x00400000 + 0x31C6674, 0x14, 0x3b2a0 }, out Pet.Move_Addr).ToString(); //宠物移动速度 194 } 195 catch (Exception ex) 196 { 197 198 } 199 } 200 201 private void btn_CWsave_Click(object sender, EventArgs e) 202 { 203 try 204 { 205 if (lab_Pet_Name.Text.Length <= 0) 206 { 207 MessageBox.Show("游戏保存错误!"); 208 } 209 210 OperateMemory.writeMemory((uint)Pet.Level_Addr, (uint)int.Parse(txt_CWLevel.Text));//等级 211 OperateMemory.writeMemory((uint)Pet.XueLiang_Addr, (uint)int.Parse(txt_Pet_XueL.Text));//血量 212 OperateMemory.writeMemory((uint)Pet.MoFa_Addr, (uint)int.Parse(txt_Pet_MF.Text));//魔法 213 OperateMemory.writeMemory((uint)Pet.Jingyan_Addr, (uint)int.Parse(txt_CWJingyan.Text)); 214 OperateMemory.writeMemoryFloat((uint)Pet.Move_Addr, float.Parse(txt_Pet_Move.Text));//角色奔跑速度 215 } 216 catch (Exception) 217 { 218 } 219 } 220 221 } 222 }
游戏修改截图 虐boss啦