大学时候因为主修C#语言(当然现在做的是javaweb开发),那时在网上学了用C#做外挂的教程,外挂嘛,大家都懂的.这里只是低级的修改内存,不涉及到截获数据包.如果是欺骗服务器,修改服务器数据,那就难的多了.这里给出两个修改内存代码的例子,一个是C#的一个是C++的.C#做东西比较简单,但是运行需要.net环境.C++编译出来的exe执行文件就没有这多要求.查找基质和偏移量的方法大都是用CE,网上教程很多.这里只有简单的代码给大家参考
首先看看C#的,我封装了一个ECHelper.cs工具类,代码如下
//打开进程获取句柄 [DllImport("kernel32.dll", EntryPoint = "OpenProcess")] public static extern IntPtr OpenProcess(int desiredAccess, bool heritHandle, int pocessID);//访问权限(16进制),是否继承句柄,进程ID //关闭句柄 [DllImport("kernel32.dll", EntryPoint = "CloseHandle")] public static extern void CloseHandle(IntPtr hObject); //读取内存 [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")] public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr baseadress, IntPtr buffer, int nsize, IntPtr bytesread); //写入内存 [DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")] public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr baseadress, long[] buffer, int nSize, IntPtr byteswrite); //根据进程名获得PID public static int GetPIDByProcessName(string name) { Process[] pros = Process.GetProcessesByName(name); if (pros.Count() > 0) { return pros[0].Id; } else { return 0; } } public static int ReadMemoryValue(string name, IntPtr baseadress) { try { byte[] buffer = new byte[4]; IntPtr bufferadress = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); IntPtr hprocess = OpenProcess(0x1F0FFF, false, ECHelper.GetPIDByProcessName(name)); ReadProcessMemory(hprocess, baseadress, bufferadress, 4, IntPtr.Zero); CloseHandle(hprocess); return Marshal.ReadInt32(bufferadress); } catch { return 0; } } public static void WriteMemoryValue(string name, IntPtr baseadress, long value) { IntPtr hprocess = OpenProcess(0x1F0FFF, false, ECHelper.GetPIDByProcessName(name)); WriteProcessMemory(hprocess, baseadress, new long [] { value }, 4, IntPtr.Zero); CloseHandle(hprocess); }
调用方法如下
string name = "cstrike"; int baseadress = 0x025069BC; private void btnShoot_Click(object sender, EventArgs e) { timShoot.Start(); } private void timShoot_Tick(object sender, EventArgs e) { timShoot.Interval = 300; int adress1 = ECHelper.ReadMemoryValue(name, (IntPtr)baseadress); adress1 = adress1 + 0x7C; int adress2 = ECHelper.ReadMemoryValue(name, (IntPtr)adress1); adress2 = adress2 + 0x5EC; int adress3 = ECHelper.ReadMemoryValue(name, (IntPtr)adress2); adress3 = adress3 + 0xCC; ECHelper.WriteMemoryValue(name, (IntPtr)adress3, 0x64); //cs子弹无线 }
这里是C#源码
下面看C++语言的
DWORD getLastError; //1.根据窗口名获取窗口 HWND hWinmine = FindWindow(NULL,"Counter-Strike"); DWORD dwPID = 0; //窗口进程标示 //2.根据窗口获取pid GetWindowThreadProcessId(hWinmine, &dwPID); if (dwPID == 0) { printf("获取PID失败\n"); return -1; } //3.根据pid获取进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwPID); if (hProcess == NULL) { printf("进程打开失败\n"); getLastError = GetLastError(); return -1; } DWORD dwNum = 0, dwSize = 0; //基址 DWORD CSBaseAddress = 0x025069BC; //基址值 DWORD CSBaseAddressValue = 0; if (0 == ReadProcessMemory(hProcess, (LPVOID)CSBaseAddress, &CSBaseAddressValue, sizeof(DWORD), &dwSize)) { printf("静态址获取失败\n"); getLastError = GetLastError(); return -1; } //一级偏移 DWORD CSOffsetFirst = 0x7C; //一级偏移值 DWORD CSOffsetFirstValue = 0; if (0 == ReadProcessMemory(hProcess, (LPVOID)(CSBaseAddressValue + CSOffsetFirst), &CSOffsetFirstValue, sizeof(DWORD), &dwSize)) { printf("一级偏移获取失败\n"); getLastError = GetLastError(); return -1; } //二级偏移 DWORD CSOffsetSecond = 0x5EC; //二级偏移值 DWORD CSOffsetSecondValue = 0; if (0 == ReadProcessMemory(hProcess, (LPVOID)(CSOffsetFirstValue + CSOffsetSecond), &CSOffsetSecondValue, sizeof(DWORD), &dwSize)) { printf("二级偏移获取失败\n"); getLastError = GetLastError(); return -1; } //三级偏移 DWORD CSOffsetThird = 0xCC; DWORD CSNum=0; //这里是当前子弹值 if (0 == ReadProcessMemory(hProcess, (LPVOID)(CSOffsetSecondValue + CSOffsetThird), &CSNum, sizeof(DWORD), &dwSize)) { printf("三级偏移获取失败\n"); getLastError = GetLastError(); return -1; } int modifyCS; printf("CSNum:%d\n", CSNum); printf("输入你要修改后的值:"); scanf("%d", &modifyCS); //更改值 WriteProcessMemory(hProcess, (LPVOID)(CSOffsetSecondValue + CSOffsetThird), &modifyCS, sizeof(DWORD), &dwSize); CloseHandle(hProcess); //关闭进程 system("pause"); //窗口停留