Windows Memory Read

Windows memory Read

윈도우즈에서 Visual Studio와 “Windows.h“를 사용해 우리가 다른 프로그램의 메모리를 읽어 원하는 값의 주소를 찾는다.


Flowchart _흐름도

  1. 윈도우즈에서 작동중인 모든 프로세스에 대한 정보를 표현한다. 
  2. 원하는 프로세스 ID(pid)검색하고자 하는 값(value)을 입력 받는다.
  3. 해당 프로세스가 실행 중인지 확인하고, 모든 메모리 읽을 수 있는 주소값들을 불러온다.
  4. 불러온 값들 중 value와 일치하는 값이 있는지 확인하고 따로 저장한다.
  5. 찾아낸 주소를 반환한다.

Detail _자세히

1. Process List

목적 :: 윈도우에서 실행 중인 프로세스의 리스트를 표시한다.
Class :: PROCESSENTRY32[MSDN] 클래스, TH32CS_SNAPPROCESS 클래스
Func :: CreateToolhelp32Snapshot()[MSDN],  Process32First()[MSDN]

PROCESSENTRY32 클래스 변수 pe를 선언
 pedwSizesizeof(PROCESSENTRY32)크기로 초기화 시켜준다.
HANDLE 형 변수 hSnapShot 선언 후 CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL)를 대입 해준다. :: 인자로 들어간 TH32CS_SNAPPROCESS는 모든 프로세스를 가져온다는 것을 의미
Process32First 를 통해 pe 변수에 프로세스 정보를 넣는다.
      ▶ 프로세스의 핸들이 할당 가능 한지 알기 위해 HANDLE형 임시 변수 proh를 선언, OpenProcess(/프로세스 모든 권한/, /상속 여부/, pe.th32ProcessID)을 대입 :: 만약 사용가능한 process라면 0이 아닌 값을 반환
pe.th32ProcessID, pe.szExeFile로 프로세스 아이디와 프로그램 이름 출력
Process32Next 를 통해 pe 변수에 다음 프로세스 정보를 넣는다.

2. Insert pID and Value

“1.” 과정을 통해 표시된 pid 중에서 원하는 프로세스의 pid를 입력
찾을 값을 입력

3. Check memory & Find data

본래 메모리의 권한을 바꾼뒤 작업 후 다시 원래 권한으로 돌려 놓아야한다.
하지만 아직 Virtual_Protect의 사용법을 모르기에 이후 진행하도록 한다.
” 읽기 가능한 메모리 주소를 찾기 위해 MEMORY_BASIC_INFORMATION 클래스의 Protect를 사용

MEMORY_BASIC_INFORMATION 클래스 변수 mbi선언 
▶ mbi.Protect중 PAGE_READONLY, PAGE_READWRITE등 읽기 가능한 메모리 주소만 선정후 찾고자 하는 값과 같은지 비교한다.
▶ 

4. Save Find data

 

 

 

[structure]SYSTEM_INFO

SYSTEM_INFO[MSDN]

typedef struct _SYSTEM_INFO {
    union {
        DWORD dwOemId;
        struct {
             WORD wProcessorArchitecture;
             WORD wReserved;
        };
    };
    DWORD dwPageSize;
    LPVOID lpMinimumApplicationAddress;
    LPVOID lpMaximumApplicationAddress;
    DWORD_PTR dwActiveProcessorMask;
    DWORD dwNumberOfProcessors;
    DWORD dwProcessorType;
    DWORD dwAllocationGranularity;
    WORD wProcessorLevel;
    WORD wProcessorRevision;
} SYSTEM_INFO;

분석

… 많으니 필요한것만

dwOemId 

Windows NT 3.5과 그 전버전을 위한 호환성을 유지하기 위해 사용되는 항목이다.
이후 버전은 wProcessorArchitecture 항목을 참조해야한다.

wProcessorArchitecture

프로세서의 아키텍쳐이다. 멤버는 다음값을 가질수 있다.

의미
PROCESSOR_ARCHITECTURE_AMD64 x64 (AMD or Intel)
PROCESSOR_ARCHITECTURE_IA64 Intel Itanium Processor Family (IPF)
PROCESSOR_ARCHITECTURE_INTEL x86
PROCESSOR_ARCHITECTURE_UNKNOWN Unknown processor.

wReserved 

나중에 사용되기 위해 예약되어있는 멤버.

dwPageSize

페이지의 크기 또는 페이지 보호와 규약의 단위.

lpMinimumApplicationAddress

가장 낮은 메모리 주소 응용 프로그램과 동적 연결 라이브러리 (DLL)에 액세스할 수에 대한 포인터.

lpMaximumApplicationAddress

가장 높은 메모리 주소 응용 프로그램 및 DLL을 액세스할 수에 대한 포인터.

dwActiveProcessorMask

마스크 프로세서의 집합을 시스템으로 구성된 대표. 비트0은 프로세서 0, 비트 31은 프로세서는 31.

dwNumberOfProcessors 

시스템에 프로세서의 수

dwProcessorType

호환성을 유지하기 위해 사용된다.

dwAllocationGranularity

어떤에서 가상 메모리가 할당될수 있는 시작 주소에 대한 단위.

wProcessorLevel

아키텍처 의존 프로세서 수준. 표시 목적으로만 사용해야한다.
    만약에 wProcessorArchitecture값이 PROCESSOR_ARCHITECTURE_INTEL 이라면
    wProcessorLevel값은 CPU 제조사에서 정의된 값.

만약에 wProcessorArchitecture값이 PROCESSOR_ARCHITECTURE_ IA64 이라면
wProcessorLevel값은 1이다.

wProcessorRevision 

호환성을 위해 폐기됨

예시코드

#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

void main()
{
   SYSTEM_INFO siSysInfo;
 
   // Copy the hardware information to the SYSTEM_INFO structure. 
 
   GetSystemInfo(&siSysInfo); 
 
   // Display the contents of the SYSTEM_INFO structure. 

   printf("Hardware information: \n");  
   printf("  OEM ID: %u\n", siSysInfo.dwOemId);
   printf("  Number of processors: %u\n", 
      siSysInfo.dwNumberOfProcessors); 
   printf("  Page size: %u\n", siSysInfo.dwPageSize); 
   printf("  Processor type: %u\n", siSysInfo.dwProcessorType); 
   printf("  Minimum application address: %lx\n", 
      siSysInfo.lpMinimumApplicationAddress); 
   printf("  Maximum application address: %lx\n", 
      siSysInfo.lpMaximumApplicationAddress); 
   printf("  Active processor mask: %u\n", 
      siSysInfo.dwActiveProcessorMask); 
}

 

 

 


GetSystemInfo[MSDN]

void GetSystemInfo( LPSYSTEM_INFO lpSystemInfo );

분석

_Out _ lpSystemInfo

SYSTEM_INFO

[Function]VirtualQueryEx

VirtualQueryEx[MSDN]

SIZE_T VirtualQueryEx( HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength );

VritualQueryEx을 사용하여 사용이 가능/불가능한 페이지를 구분할 수 있다.

분석

_In_ hProcess

OpenProcess함수 등을 통해 얻을 수 있는 프로세스 handle

_In_opt_ lpAddress

프로세스의 Base Address
GetSystemInfo함수 등을 사용하여 가져올 수 있다.

_Out_ lpBuffer

데이터가 반환되는 M.B.I. 포인터

_In_ dwLength

lpBuffer의 크기

Return

함수의 호출이 성공적이면 MBI의 크기가 return된다.

 

[structure]MEMORY_BASIC_INFORMATION

MEMORY_BASIC_INFORMATION[MSDN]

typedef struct _MEMORY_BASIC_INFORMATION {
    PVOID    BaseAddress;
    PVOID    AllocationBase;
    DWORD  AllocationProtect;
    SIZE_T    RegionSize;
    DWORD State;
    DWORD Protect;
    DWORD Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

분석

*BaseAddress

Page 영역의 Base Address 포인터

*AllocationBase

VirtualAlloc함수의 의해 할당된 페이지 범위의 Base Address 포인터,
BaseAddress포인터가 가리키는 영역이 이 영역에 포함됨.

AllocationProtect

페이지가 할당 될 때의 메모리 보호 옵션

RegionSize

페이지의 크기 

State

MEM_COMMIT  : 현재 메모리가 사용되는 상태
MEM_FREE          : 현재 메모리가 쓰지 않는 상태
MEM_RESERVE : 현재 사용하고 있지 않지만 사용을 대비한 상태

Protect

지역 페이지에 대한 액세스 보호

Type

MEM_IMAGE      : 영역 내의 메모리 페이지가 이미지 섹션의 뷰에 매핑됨을 나타냅니다.
MEM_MAPPED  : 영역 내의 메모리 페이지가 섹션보기에 매핑됨을 나타냅니다.
MEM_PRIVATE : 영역 내의 메모리 페이지가 비공개 (즉, 다른 프로세스와 공유되지 않음)임을 나타냅니다.

[Function]Windows OpenProcess

Windows OpenProcess Function


HANDLE OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId );

분석

반환:
HANDLE = 프로세스를 제어할 수 있는 handle을 반환 (if Error: Return NULL)

인자 설명:
[_In_]dwDesiredAccess = 단순 읽기위해선 PROCESS_VM_READ, 단순 쓰기위해선 PROCESS_VM_WRITE, 읽고 쓰기위해선 PROCESS_ALL_ACCESS
[_In_]bInheritHandle = 이 값이 TRUE이면 프로세스에 Handle이 상속되며 FALSE면 상속되지 않는다.
[_In_]dwProcessId = PID (Process ID)

[Function]Read/WriteProcessMemory

Windows Memory Read/Write Lib


Windows Memory Read[MSDN]

Memory Read Function
BOOL ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead );

함수명 : ReadProcessMemory
인자명 : hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead


분석

인자명 자료형 설명 비고

hProcess

HANDLE
[_In_]
OpenProcess() 함수를 통해
Process의 메모리를 제어하는 Handle

단순 읽기위해선 PROCESS_VM_READ,
단순 쓰기위해선 PROCESS_VM_WRITE,
쓰고 읽기위해선 PROCESS_ALL_ACCESS

lpBaseAddress

LPCVOID
[_In_]
읽을 메모리 주소를 가르키는 포인터
 

lpBuffer

LPVOID
[_Out_]
읽어낸 데이터를 저장할 포인터
 

nSize

SIZE_T
[_In_] 
읽은 내용을 저장할 Buffer의 크기
 

lpNumberOfBytesRead

SIZE_T*
[_Out_]
쓰거나, 읽은 메모리의 크기
 만약 NULL일 경우 해당 인자는 무시된다.

반환

자료형 : BOOL
    Memory Read Success != 0
    Memory Read Fail       == 0


Windows Memory Write[MSDN]

Memory Write Function
BOOL WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten );

함수명 : WriteProcessMemory
인자명 : hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead


분석

인자명 자료형 설명 비고

hProcess

HANDLE
[_In_]
OpenProcess() 함수를 통해
Process의 메모리를 제어하는 Hendle

단순 읽기위해선 PROCESS_VM_READ,
단순 쓰기위해선 PROCESS_VM_WRITE,
쓰고 읽기위해선 PROCESS_ALL_ACCESS

lpBaseAddress

LPVOID
[_In_]
쓴 메모리 주소를 가르키는 포인터
 

lpBuffer

LPCVOID
[_In_]
쓸 데이터가 저장된 포인터
 

nSize

SIZE_T
[_In_]
쓸 내용을 저장한 Buffer의 크기
 

lpNumberOfBytesRead

SIZE_T*
[_Out_]
쓰거나, 읽은 메모리의 크기
 WriteProcessMemory에선 옵션이다.

반환

자료형 : BOOL
    Memory Write Success != 0
    Memory Write Fail       == 0

Reference

http://paladin.tistory.com/100