C#WinAPIを使用した読み書きプロセスメモリ


0x01
kernel 32を使用する.dllのReadProcessMemoryとWriteProcessMemoryメモリ関数は、プログラムメモリの読み書きを完了します.
私はメモリ整数型、メモリ整数型、メモリ小数型の3つの方法を書くときに、プロセスアドレスを正しく読み書きできるメモリをテストしましたが、メモリ小数型を書くときに問題が発生しました.記録してください.
0x02
ReadProcessMemory関数のプロトタイプは次のとおりです.
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead
);

hProcessリモートプロセスハンドル、被読取者プロセスハンドルを指す
lpBaseAddressリモートプロセスにおけるメモリアドレスとは、具体的にどこから読み出すかを指す
lpBufferローカルプロセスにおけるメモリアドレスとは、関数が読み出した内容をここに書き込むことを指す.
nSizeが転送するバイト数は、どのくらい書き込むかを指します
lpNumberOfBytesRead実際に転送されたバイト数は、関数が返されたときに実際にどのくらい書き込まれたかを報告することを意味します.
WriteProcessMemory関数のプロトタイプは次のとおりです.
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesWritten
);

hProcess OpenProcessから返されるプロセスハンドル、例えばパラメータ伝達データがINVALID_HANDLE_VALUE【即ち-1】目標プロセスは自己プロセスである
lpBaseAddressが書くメモリヘッダアドレス
lpBuffer書き込みデータへのポインタ
nSize書き込みバイト数
0x03
テストクラス
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;

    namespace C_Sharp    
    {
        public abstract class test
        {
            [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
            public static extern int _MemoryReadByteSet(int hProcess, int lpBaseAddress, byte[] lpBuffer, int nSize, int lpNumberOfBytesRead);

            [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
            public static extern int _MemoryReadInt32(int hProcess, int lpBaseAddress, ref int lpBuffer, int nSize, int lpNumberOfBytesRead);

            [DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
            public static extern int _MemoryWriteByteSet(int hProcess, int lpBaseAddress, byte[] lpBuffer, int nSize, int lpNumberOfBytesWritten);

            [DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
            public static extern int _MemoryWriteInt32(int hProcess, int lpBaseAddress, ref int lpBuffer, int nSize, int lpNumberOfBytesWritten);

            [DllImport("kernel32.dll", EntryPoint = "GetCurrentProcess")]
            public static extern int GetCurrentProcess();

            [DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
            public static extern int OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId);

            [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
            public static extern int CloseHandle(int hObject);

            [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
            public static extern int _CopyMemory_ByteSet_Float(ref float item, ref byte source, int length);


            const int PROCESS_POWER_MAX = 2035711;




            /// 
            ///       
            /// 
            ///   ID
            /// 0x  
            /// 0  
            public static int ReadMemoryInt32(int pID, int bAddress)
            {
                int num = 0;
                int handle = GetProcessHandle(pID);
                int num3 = test._MemoryReadInt32(handle, bAddress, ref num, 4, 0);
                test.CloseHandle(handle);
                if (num3==0)
                {
                    return 0;
                }
                else
                {
                    return num;
                }
            }

            /// 
            ///       
            /// 
            ///   ID
            /// 0x  
            ///    
            /// false   true  
            public static bool WriteMemoryInt32(int pID, int bAddress,int value)
            {
                int handle = GetProcessHandle(pID);
                int num2 = test._MemoryWriteInt32(handle, bAddress, ref value, 4, 0);
                test.CloseHandle(handle);
                return num2 != 0;
            }

            /// 
            ///       
            /// 
            ///   ID
            /// 0x  
            /// 0  
            public static float ReadMemoryFloat(int pID, int bAddress)
            {
                //byte[] array = test.GetVoidByteSet(4);
                byte[] array = new byte[4];//                    
                int handle = GetProcessHandle(pID);
                int temp = test._MemoryReadByteSet(handle, bAddress, array, 4, 0);
                if (temp == 0)
                {
                    return 0f;
                }
                else
                {
                    return test.GetFloatFromByteSet(array, 0);
                }
            }

            /// 
            ///       
            /// 
            ///   ID
            /// 0x  
            ///     
            /// false  
            public static bool WriteMemoryFloat(int pID, int bAddress, float value)
            {
                //byte[] byteSet = test.GetByteSet(value);
                byte[] byteSet = BitConverter.GetBytes(value);//https://msdn.microsoft.com/en-us/library/yhwsaf3w
                //byte[] byteSet = Encoding.GetEncoding("gb2312").GetBytes(value.ToString());
                return test.WriteMemoryByteSet(pID, bAddress, byteSet, 0);
            }

            /// 
            ///       
            /// 
            ///   ID
            /// 0x  
            ///     
            ///      0         
            /// false  
            private static bool WriteMemoryByteSet(int pID, int bAddress, byte[] value, int length=0)
            {
                int handle = test.GetProcessHandle(pID);
                int nSize = (length == 0) ? value.Length : length;
                int tmp = test._MemoryWriteByteSet(handle, bAddress, value, nSize, 0);//byte[]             ref           
                //test.CloseHandle(pID);
                return tmp != 0;
            }

            /// 
            ///       
            /// 
            /// 
            /// 
            public static byte[] GetVoidByteSet(int num)
            {
                if (num<=0)
                {
                    num = 1;
                }
                string text = "";
                for (int i = 0; i < num; i++)
                {
                    text += "0";
                }
                return Encoding.UTF8.GetBytes(text);
            }

            /// 
            ///      
            /// 
            ///   ID
            ///     
            public static int GetProcessHandle(int pID)
            {
                if (pID == -1)
                {
                    return test.GetCurrentProcess();
                }
                else
                {
                    return test.OpenProcess(PROCESS_POWER_MAX, 0, pID);
                }
            }

            /// 
            ///        
            /// 
            ///    
            ///   
            /// 
            public static float GetFloatFromByteSet(byte[] sourceValue, int index)
            {
                float result = 0f;
                test._CopyMemory_ByteSet_Float(ref result, ref sourceValue[index], 4);
                return result;
            }

            /// 
            ///      
            /// 
            ///            
            /// 
            public static byte[] GetByteSet(float data)
            {
                return Encoding.UTF8.GetBytes(data.ToString());
            }
        }
    }

0x04
書き込みメモリバイトセットを使用して小数点を書き込む場合は、floatタイプのパラメータをBitConvert.GetBytes(value)はEncodingを使用することなくバイト配列に変換される.UTF8.GetBytes(value.ToString())は、文字列内のすべての文字を1バイトシーケンスに符号化します.
これにより、プロセス指定アドレスの値は小数ではなくテキスト型に書き込まれます.Cheat Engineでは直感的に観察できる.
0x05
BitConvertクラス転送ゲート:https://msdn.microsoft.com/zh-cn/library/3kftcaf9.aspx