C# 简单内存补丁

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

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

0x1 看教程

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

0x2 学习到部分概念

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

0x3 网上检索

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

0x4 代码实践

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

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

MCF程序  C++ OK方法中

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);
    }
}
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

转载于:https://www.cnblogs.com/Supperlitt/p/6714111.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值