선언:

WriteProcessMemory (C#)
[DllImport("kernel32")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, out uint nNumberOfBytesWritten);

WriteProcessMemory (VB.NET)
<DllImport("kernel32")>
Shared Function WriteProcessMemory(hProcess As IntPtr, lpBaseAddress As IntPtr, lpBuffer As IntPtr, nSize As UInteger, ByRef nNumberOfBytesWritten As UInteger) As Boolean
End Function



사용 예제:

WriteProcessMemory Example (C#)
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ApiReference {
    class ApiExample {
        [DllImport("kernel32")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, out uint nNumberOfBytesRead);
        [DllImport("kernel32")]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, out uint nNumberOfBytesWritten);
        
        public unsafe static void Main(string[] args) {
            // myAge 라는 변수에 23 을 저장한다.
            int myAge = 23;
            
            // myAge 변수의 주소 값을 가지는 변수와 결과를 받을 변수를 선언한다.
            IntPtr pAgeAddress = new IntPtr(&myAge), pResultAge;
            pResultAge = Marshal.AllocHGlobal(4);
            uint reads, written;
            
            if ( !ReadProcessMemory(Process.GetCurrentProcess().Handle, pAgeAddress, pResultAge, 4, out reads) ) {
                Console.WriteLine("메모리 읽기 실패!");
            } else {
                Console.WriteLine("메모리 읽기 성공!");
                Console.WriteLine("myAge 변수의 값: {0}", myAge);
                // 이 방법도 되지만
                Console.WriteLine("pResultAge 변수가 가리키는 주소의 값: {0}", *(int *)pResultAge.ToPointer());
                // 이 방법도 됨
                Console.WriteLine("pResultAge 변수가 가리키는 주소의 값: {0}", Marshal.ReadInt32(pResultAge));
            }
            
            Marshal.FreeHGlobal(pResultAge);
            
            // WriteProcessMemory 부분:
            // 변경될 값을 적는다.
            int changedAge = 777;
            
            // 변경될 값이 저장된 변수의 주소값을 얻어온다. 
            IntPtr pValue = new IntPtr(&changedAge);
            
            // 이거는 Marshal 클래스를 이용한 아래 방법으로도 가능함.
            // 이 방법을 쓴 경우에는 반드시 Marshal.FreeHGlobal 메서드를 이용하여
            // 할당한 메모리를 해제하도록 한다.
            /*
                IntPtr pValue = Marshal.AllocHGlobal(4);
                Marshal.WriteInt32(pValue, 777);
            */
           
            if ( !WriteProcessMemory(Process.GetCurrentProcess().Handle, pAgeAddress, pValue, 4, out written) ) {
                Console.WriteLine("메모리 쓰기 실패!");
            } else {
                Console.WriteLine("메모리 쓰기 성공!");
                Console.WriteLine("myAge 변수의 값: {0}", myAge);
                // 이 방법도 되지만
                Console.WriteLine("pValue 변수가 가리키는 주소의 값: {0}", *(int *)pValue.ToPointer());
                // 이 방법도 됨
                Console.WriteLine("pValue 변수가 가리키는 주소의 값: {0}", Marshal.ReadInt32(pValue));
            }
            
            
            Console.ReadKey(true);
        }
    }
}
예제 코드 (.NET Fiddle)


WriteProcessMemory Example (VB.NET)
Imports System
Imports System.Diagnostics
Imports System.Runtime.InteropServices

Class ApiExample
    <DllImport("kernel32")>
    Shared Function WriteProcessMemory(hProcess As IntPtr, lpBaseAddress As IntPtr, lpBuffer As IntPtr, nSize As UInteger, ByRef nNumberOfBytesWritten As UInteger) As Boolean
    End Function
    <DllImport("kernel32")>
    Shared Function ReadProcessMemory(hProcess As IntPtr, lpBaseAddress As IntPtr, lpBuffer As IntPtr, nSize As UInteger, ByRef lpNumberOfBytesRead As UInteger) As Boolean
    End Function
    
    Public Shared Sub Main(args As String())
        Dim myAge As Integer = 23
        Dim pAgeAddress, pResultAge As IntPtr
        
            
        pAgeAddress = Marshal.AllocHGlobal(4)
        pResultAge = Marshal.AllocHGlobal(4)
        
        Marshal.StructureToPtr(myAge, pAgeAddress, False)
        
        Dim reads, written As UInteger
        If Not ReadProcessMemory(Process.GetCurrentProcess().Handle, pAgeAddress, pResultAge, 4, reads) Then
            Console.WriteLine("메모리 읽기 실패!")
        Else
            ' 비주얼 베이직에서는 unsafe 키워드도 없고 포인터도 사용할 수 없으므로
            ' Marshal 클래스를 통해서만 작업이 가능하다.
            Console.WriteLine("메모리 읽기 성공!")
            Console.WriteLine("myAge 변수의 값: {0}", myAge)
            Console.WriteLine("pResultAge 변수가 가리키는 주소의 값: {0}", Marshal.ReadInt32(pResultAge))
        End If
        
        ' 값을 쓴다.
        Marshal.WriteInt32(pResultAge, 777)
       
           If Not WriteProcessMemory(Process.GetCurrentProcess().Handle, pAgeAddress, pResultAge, 4, written) Then
            Console.WriteLine("메모리 쓰기 실패!")
        Else
            ' 비주얼 베이직에서는 unsafe 키워드도 없고 포인터도 사용할 수 없으므로
            ' Marshal 클래스를 통해서만 작업이 가능하다.
            Console.WriteLine("메모리 쓰기 성공!")
            Console.WriteLine("pAgeAddress 변수가 가리키는 주소의 값: {0}", Marshal.ReadInt32(pAgeAddress))
            Console.WriteLine("pResultAge 변수가 가리키는 주소의 값: {0}", Marshal.ReadInt32(pResultAge))
        End If
        Console.ReadKey(True)
    End Sub
End Class
예제 코드 (.NET Fiddle)




예제 실행 결과:




매개변수 설명(기울임꼴로 표시된 매개변수는 생략 가능합니다):

hProcess - 메모리를 쓸 프로세스의 핸들입니다.

lpBaseAddress - 쓸 메모리의 주소입니다.

lpBuffer - 메모리에 쓸 데이터가 저장된 버퍼입니다.

nSize - 메모리에 쓸 데이터의 크기입니다.

nNumberOfBytesWritten - 쓴 데이터의 크기입니다.




API 설명:

프로세스의 메모리에 데이터를 씁니다.




참고:

WriteProcessMemory (MSDN)




문자셋:

없음




요구 사항:

Windows XP 이상

Windows Server 2003 이상




비고:

프로세스의 메모리를 쓰는 경우에는 반드시 PROCESS_VM_WRITE 권한을 명시하여 연 프로세스의 핸들이 필요합니다. 만약 프로세스 핸들을 열었을 때 PROCESS_VM_WRITE 권한을 명시하지 않은 경우 이 API는 ERROR_ACCESS_DENIED 오류로 실패합니다.

읽으려는 프로세스의 메모리 주소는 반드시 쓸 수 있어야 합니다. 만약 0x00001000 ~ 0x00002000 주소에 데이터를 쓰려는 경우 중간에 단 한바이트라도 쓰기 권한이 없을 경우 이 API는 ERROR_PARTIAL_COPY 오류 또는 기타 다른 오류로 실패합니다.

VB.NET에서는 포인터를 사용할 수 없으므로 Marshal 클래스를 이용한 모든 작업을 해야합니다.




.NET Fiddle 의 .NET 보안 수준으로 인해 P/Invoke 를 직접 테스트하실 수 없습니다. .NET Fiddle 사이트는 코드 참고용으로만 이용해 주시기 바랍니다.
틀린 부분이나 개선되야할 부분을 찾으셨다면 주저없이 댓글로 남겨주세요~ 바로 반영하도록 하겠습니다!!
Powered by SlaneR & TeamDEV Korea


 


'API Reference' 카테고리의 다른 글

63. ReadProcessMemory  (1) 2015.11.12
62. PROCESS_EXTENDED_BASIC_INFORMATION  (0) 2015.10.09
61. LoadLibraryEx  (0) 2015.10.03
60. RegisterWindowMessage  (0) 2015.10.03
59. IsWindow  (0) 2015.09.29

+ Recent posts