- 2018-03-17 ~ (P2) - 다른 프로세스의 메모리 읽기

1. 다른 프로세스(Cpp_AnotherProcess.exe)의 핸들 얻기

1-1 TlHelp32.h

1) CreateToolhelp32Snapshot(), Process32First(), Process32Next()로 pId 얻기

2) OpenProcess()로 핸들 얻기

※특정 프로세스의 핸들을 얻는 다른 방법 찾아보기

2. ReadProcessMemory()로 0x40108B부터 6바이트만큼 읽어서 버퍼에 저장

3. 버퍼 출력


프로그램의 기능은 이렇다

//1. 현재 돌아가는 프로그램의 모든 스냅샷 출력

//2. 메모리를 읽고싶은 프로그램 입력

//3. WriteProcessMemory()로 0x40108E부터 2바이트를 {0x00,0xEB}로 쓰기

//4. ReadProcessMemory()로 0x40108E부터 6바이트를 읽어서 버퍼에저장, 출력



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<stdio.h>
#include<stdlib.h>
#include<wchar.h>
#include<Windows.h>
#include<tlhelp32.h>
 
 
void Read(PROCESSENTRY32 *sub) {
    HANDLE openPro;
    SIZE_T readSize;
    int buf1[3= { 0x00,0xEB }, buf2[20= { 0 };
    int errCode;
    openPro = OpenProcess(PROCESS_ALL_ACCESS, FALSE, sub->th32ProcessID);
 
    printf("값 바꾸기 전..\n");
    ReadProcessMemory(openPro, (LPCVOID)0x40108E, buf2, 6&readSize);
    for (int i = 0; i < 6; i++) {
        printf("%#02x ", buf2[i]);
    }
    printf("\n");
    memset(buf2, 0sizeof(buf2));
 
    printf("값 바꾼 후..\n");
    WriteProcessMemory(openPro, (LPVOID)0x40108E, buf1, 2&readSize);
    ReadProcessMemory(openPro, (LPCVOID)0x40108E, buf2, 6&readSize);
    for (int i = 0; i < 6; i++) {
        printf("%#02x ", buf2[i]);
    }
    printf("\n");
    errCode = GetLastError();
    printf("errCode : %d\n", errCode);
}
 
int main() {
    HANDLE hProcessSnap;
    PROCESSENTRY32 processinform,sub;
    processinform.dwSize = sizeof(PROCESSENTRY32);
    sub.dwSize = sizeof(PROCESSENTRY32);
 
    hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE) 
        printf("CreateToolhelp32Snapshot error \n");
 
    if (!Process32First(hProcessSnap, &processinform)) {
        printf("Process32First error ! \n");
        CloseHandle(hProcessSnap);
        return 0;
    }
    printf("LIST> \n");
    printf("\t\t[Process name \t[PID]\t[개수]\t[부모프로세스ID] \n");
 
    do {
        wprintf(L"%25s %8d %8d %16d \n"//유니코드 출려과 아스키코드 출력은 다르므로 유니코드를 출력하는 wprintf를 사용해야함
            processinform.szExeFile, processinform.th32ProcessID, processinform.cntThreads, processinform.th32ParentProcessID);
    } while (Process32Next(hProcessSnap, &processinform));
 
 
    printf("프로세스 이름 입력 :");
    memset(&sub, 0sizeof(sub));
    wscanf(L"%s",&sub.szExeFile);
    CloseHandle(hProcessSnap);
    //이미 앞에서 한번 더 읽어줬기 때문에 이전의 핸들을 반환하고 다시 새로운 핸들을 생성해야한다
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
        printf("CreateToolhelp32Snapshot error \n");
 
    if (!Process32First(hProcessSnap, &processinform)) {
        printf("Process32First error ! \n");
        CloseHandle(hProcessSnap);
        return 0;
    }
    while (Process32Next(hProcessSnap, &processinform)) {
        if (!wcscmp(sub.szExeFile, processinform.szExeFile)) {
            sub.th32ProcessID = processinform.th32ProcessID;
            sub.cntThreads = processinform.cntThreads;
            sub.th32ParentProcessID = processinform.th32ParentProcessID;
            printf("\t\t[Process name] \t[PID]\t[개수]\t[부모프로세스 ID] \n");
            wprintf(L"%25s %8d %8d %16d \n"//유니코드 출려과 아스키코드 출력은 다르므로 유니코드를 출력하는 wprintf를 사용해야함
                sub.szExeFile, sub.th32ProcessID, sub.cntThreads, sub.th32ParentProcessID);
            Read(&sub);
        }
    }
    CloseHandle(hProcessSnap);
 
    return 0;
}
 
cs



CreateToolhelp32Snapshot()

지정된 프로세스뿐만 아니라 이러한 프로세스가 사용하는 힙, 모듈 및 스레드의 스냅 샷을 가져옵니다.

1
HANDLE CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID );

cs


매개변수
DWORD dwFlags : 상황에 따라 많음

DWORD th32ProcessID :스냅 샷에 포함될 프로세스의 프로세스 식별자. 이 매개 변수는 현재 프로세스를 나타내는 0 일 수 있음

추가의 내용이 많으니 링크를 ! 

https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot



Process32First()

시스템 스냅 샷에서 발생한 첫 번째 프로세스에 대한 정보를 검색

1
BOOL Process32First( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );

cs


매개변수

HANDLE hSnapshot : CreateToolhelp32Snapshot() 함수에 대한 이전 호출에서 반환 된 스냅 샷 핸들입니다.

LPPROCESSENTRY32 lppe :  processentry32 구조체에 대한 포인터. 실행 파일의 이름, 프로세스 식별자 및 상위 프로세스의 프로세스 ID와 같은 프로세스 정보를 포함합니다.( 구조체의 사이즈는 deSize로 해야함)

프로세스 목록의 첫 번째 항목이 버퍼에 복사 된 경우 TRUE를 반환하고 그렇지 않으면 FALSE를 반환


Process32Next()

시스템 스냅 샷에 기록 된 다음 프로세스에 대한 정보를 검색합니다.

1
BOOL Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
cs
매개변수
Process32First()와 기능은 비슷 링크를 ! 
https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-process32next



ReadProcessMemory()

지정된 프로세스에서 메모리 영역에서 데이터를 읽습니다. 읽을 전체 영역에 액세스하거나 작업이 실패합니다.

1
2
3
4
5
6
7
8
BOOL WINAPI ReadProcessMemory(
  _In_  HANDLE  hProcess,
  _In_  LPCVOID lpBaseAddress,
  _Out_ LPVOID  lpBuffer,
  _In_  SIZE_T  nSize,
  _Out_ SIZE_T  *lpNumberOfBytesRead
);
 
cs

매개변수

hProcess : 읽히는 메모리가 있는 프로세스에 대한 핸들입니다. 핸들은 프로세스에 대한 PROCESS_VM_READ 액세스 권한이 있어야 합니다.


lpBaseAddress : 읽을 지정된 프로세스의 기본 주소에 대한 포인터 


IpBuffer :지정된 프로세스의 주소 공간으로부터 내용을 수신하는 버퍼에 대한 포인터


nSize : 지정된 프로세스에서 읽을 바이트 수


lpNumberOfBytesRead : 지정된 버퍼로 전송된 바이트 수를 수신하는 변수에 대한 포인터


링크 ! https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms680553(v=vs.85).aspx


WriteProcessMemory()

지정된 프로세스의 메모리 영역에 데이터를 기록합니다. 기록할 전체 영역에 액세스해야 합니다. 그렇지 않으면 작업이 실패합니다.


1
2
3
4
5
6
7
BOOL WINAPI WriteProcessMemory(
  _In_  HANDLE  hProcess,
  _In_  LPVOID  lpBaseAddress,
  _In_  LPCVOID lpBuffer,
  _In_  SIZE_T  nSize,
  _Out_ SIZE_T  *lpNumberOfBytesWritten
);
cs

ReadProcessMemory()와 거의 비슷... 링크를!

https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms681674(v=vs.85).aspx


'@안티치트' 카테고리의 다른 글

실제 프로그램에 적용해보기(메모리 읽고 쓰기)  (0) 2018.11.05
프로세스 메모리 읽고 쓰기(ASLR)  (0) 2018.10.05
프로세스 메모리 읽어오기  (0) 2018.10.05
START!  (0) 2018.10.05

+ Recent posts