C# 简单内存补丁_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > C# 简单内存补丁

C# 简单内存补丁

 2017/4/16 5:34:17  Supper_litt  程序员俱乐部  我要评论(0)
  • 摘要:写在开头:看了一些视频教程,感觉OD为什么别人学个破解那么容易,我就那么难了呢,可能是没有那么多时间吧。解释:个人见解:所谓内存补丁,即:通过修改运行程序的内容,来达到某种目的的操作。修改使用OpenProcess打开,WriteProcessMemory写入,CloseHandle关闭。部分需要读取数据判断使用:ReadProcessMemory0x1看教程关于有的学习教程,确实要看看视频才能了解别人的操作,或者很简单一个东西,如果没有别人的指导那么自己操作确实不太容易
  • 标签:C# 补丁 内存

写在开头:看了一些视频教程,感觉OD为什么别人学个破解那么容易,我就那么难了呢,可能是没有那么多时间吧。

解释:个人见解:所谓内存补丁,即:通过修改运行程序的内容,来达到某种目的的操作。修改使用OpenProcess打开,WriteProcessMemory写入,CloseHandle关闭。部分需要读取数据判断使用:ReadProcessMemory

0x1 看教程

  关于有的学习教程,确实要看看视频才能了解别人的操作,或者很简单一个东西,如果没有别人的指导那么自己操作确实不太容易。

0x2 学习到部分概念

  肯定不可能一味的模仿,做一样的东西,所以需要学以致用就很关键了。于是乎,用vs2013 c++写了几行代码,用于自己测试,用C#写内存补丁

0x3 网上检索

  没有人生而知之,所以网上查询也是很关键的一步,查询哪些内容呢?就是查询C#如何写内存补丁,代码大同小异不过不一定能用。

0x4 代码实践

  网上找到的代码也是要在实践中得出能否使用的。所以这一步也是必不可免的。

于是乎有了下面的代码。需要使用OD找到代码的位置即和在内存中和代码的相差位置。

MCF程序  C++ OK方法中

class="code_img_closed" src="/Upload/Images/2017041605/0015B68B3C38AA5B.gif" alt="">
void CMFCTestDlg::OnBnClickedOk()
{
    CString str;
    GetDlgItemText(IDC_EDIT1, str);

    if (str == "test123456789"){
        ::MessageBox(NULL, L"OK", L"提示", 0);
    }
    else{
        ::MessageBox(NULL, L"Fail", L"提示", 0);
    }
}
logs_code_collapse">View Code

C#程序中调用,首先贴一个帮助类,来源网上。当然对其中添加和修改了部分方法。

public abstract class ApiHelper
    {
        [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, ref IntPtr baseAddress)
        {
            Process[] arrayProcess = Process.GetProcessesByName(processName);
            foreach (Process p in arrayProcess)
            {
                baseAddress = p.MainModule.BaseAddress;
                return p.Id;
            }

            return 0;
        }

        //根据进程名获取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[2];
                IntPtr byteAddress = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); //获取缓冲区地址
                IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName));
                ReadProcessMemory(hProcess, (IntPtr)baseAddress, byteAddress, buffer.Length, IntPtr.Zero); //将制定内存中的值读入缓冲区
                CloseHandle(hProcess);
                return Marshal.ReadInt32(byteAddress);
            }
            catch
            {
                return 0;
            }
        }

        //将值写入指定内存地址中
        public static bool WriteMemoryValue(int baseAddress, string processName, int[] value)
        {
            IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName)); //0x1F0FFF 最高权限
            bool result = WriteProcessMemory(hProcess, (IntPtr)baseAddress, value, value.Length, IntPtr.Zero);
            CloseHandle(hProcess);

            return result;
        }
    }
View Code

最后是在具体按钮中的调用了。

private string processName = "MFCTest"; //

        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr startAddress = IntPtr.Zero;
            int pid = ApiHelper.GetPidByProcessName(processName, ref startAddress);
            if (pid == 0)
            {
                MessageBox.Show("哥们启用之前该运行吧!");
                return;
            }

            int baseAddress = startAddress.ToInt32() + 0x1000;
            int value = ReadMemoryValue(baseAddress);             // 读取基址(该地址不会改变)
            int address = baseAddress + 0x14F3;                   // 获取2级地址
            value = ReadMemoryValue(address);
            bool result = WriteMemory(address, new int[] { 144 });
            address = address + 0x1;
            result = WriteMemory(address, new int[] { 144 });

            MessageBox.Show(result ? "成功" : "失败");
        }


        //读取制定内存中的值
        public int ReadMemoryValue(int baseAdd)
        {
            return ApiHelper.ReadMemoryValue(baseAdd, processName);
        }

        //将值写入指定内存中
        public bool WriteMemory(int baseAdd, int[] value)
        {
            return ApiHelper.WriteMemoryValue(baseAdd, processName, value);
        }
View Code

0x5 总结

  只有不断学习才能知道新的知识,同时在学习中进步。很多不懂的概念其实很简单。当然前提是你明白以后。

   其中注意一点。

测试代码下载:WriteProcessMemory的buffer填入一个数组也是可以的。需要计算长度。然后nSize就是,前面的数组作为几个字节进行使用。

// 重构了些许代码


        //将值写入指定内存地址中
        public static bool WriteMemoryValue(int baseAddress, string processName, int[] value, int len)
        {
            IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName)); //0x1F0FFF 最高权限
            bool result = WriteProcessMemory(hProcess, (IntPtr)baseAddress, value, len, IntPtr.Zero);
            CloseHandle(hProcess);

            return result;
        }

// 144=0x90  表示 nop
bool result = ApiHelper.WriteMemoryValue(address, processName, new int[] { 144 + 144 * 256 }, 2);

 

 WinTestRe.zip

发表评论
用户名: 匿名