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

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

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

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

0x5 总结

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

测试代码下载:

WinTestRe.zip

时间: 2024-10-11 12:48:40

C# 简单内存补丁的相关文章

简单内存池实现

#ifndef __MEM_POOL_H__ #define __MEM_POOL_H__ typedef struct tagMemItem { int nSize; int nUsed; void* addr; }MEM_ITEM_S; /***************************************************************************************************** * 4M memory pool * +------

C++ Primer 学习笔记_29_操作符重载与转换(4)--转换构造函数和类型转换运算符归纳、operator new 和 operator delete 实现一个简单内存泄漏跟踪器

C++ Primer 学习笔记_29_操作符重载与转换(4)--转换构造函数和类型转换运算符归纳.operator new 和 operator delete 实现一个简单内存泄漏跟踪器 一.转换构造函数 可以用单个实参来调用的构造函数定义从形参类型到该类型的一个隐式转换.如下: class Integral { public: Integral (int = 0); //转换构造函数 private: int real; }; Integral A = 1; //调用转换构造函数将1转换为In

简单内存池

System Call 先测试系统调用new/delete的用时. #include <iostream> #include <time.h> using namespace std; timespec diff(timespec start, timespec end) { timespec temp; if((end.tv_nsec-start.tv_nsec)<0) { temp.tv_sec = end.tv_sec-start.tv_sec-1; temp.tv_n

Java逆向基础之简单的补丁

本文参考:http://www.vuln.cn/7118 本文参考:<Reverse Engineering for Beginners>Dennis Yurichev著 本文需要用到IDA 简单的补丁 看一个例子 public class nag { public static void nag_screen() { System.out.println("This program is not registered"); }; public static void ma

mapreduce on yarn简单内存分配解释

关于mapreduce程序运行在yarn上时内存的分配一直是一个让我蒙圈的事情,单独查任何一个资料都不能很好的理解透彻.于是,最近查了大量的资料,综合各种解释,终于理解到了一个比较清晰的程度,在这里将理解的东西做一个简单的记录,以备忘却.首先,先将关于mapreduce和yarn关于内存分配的参数粘贴上:yarn.scheduler.minimum-allocation-mbyarn.scheduler.maximum-allocation-mbyarn.nodemanager.resource

_CrtSetBreakAlloc简单内存泄漏检测方法,解决Detected memory leaks!问题

我的环境是: XP SP2 . VS2003 最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} normal block at 0x05785AD0, 152 bytes long. Data: << N N x 7 > 3C AC 4E 10 00 00 00 00 BC A4 4E 10 78 B6 37 00 Object dump complete.   而且每次退出都是一样的.

简单内存泄漏检测方法 解决 Detected memory leaks! 问题

最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} normal block at 0x05785AD0, 152 bytes long. Data: << N N x 7 > 3C AC 4E 10 00 00 00 00 BC A4 4E 10 78 B6 37 00 Object dump complete.   而且每次退出都是一样的.泄漏的内存块都是98500. 解决方法: 1.

C++中的简单内存管理---初步认识

OC里面给变量赋值有2种方法第一种是直接用下划线的,也就是实例变量:_button=       第二种是使用属性:self.button = ....这两种有何区别??? 以下项目是创建了一个C++项目   简单模拟创建对象和给变量赋值的情况 首先创建了一个NSObject类,在OC里面继承NSObject类的都有retain  release  autorelease....等方法来管理内存的 NSObject的头文件,声明方法 // // NSObject.h // autorelease

对象的简单内存分析

在如今学习的过程中,我们更多的是在练习如何使用各种方法或某种套路,例如需要设计某个app的时候,我们可能会说我们之前设计过的模型中直接套过来使用,或者在网上需找类似的demo,随着时间和经验的积累,我们在这一方面越来越得心应手,以后一直是copy.copy等,但对一些简单的本质东西不甚了解了,虽然这些东西也可以不必去知道,但我认为多了解一些基本的东西还是有好处的,下面就来简单的说一些对象的内存的问题: 1.我们先来创建一个Person类: #import <Foundation/Foundati