本人微信公众号"aeolian"~

C++&C#外挂(内存修改)

大学时候因为主修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");  //窗口停留

C++源码

点赞

Leave a Reply

Your email address will not be published. Required fields are marked *