티스토리 뷰
IDA와 올리디버거로 지뢰찾기를 분석해서 지뢰찾기 게임의 맵 정보를 찾았습니다.
이 부분을 검색해서 실시간으로 게임의 맵 정보를 출력해주는 맵 핵 프로그램을 만들었습니다.
아래는 프로젝트의 소스코드입니다.
자세한 코드 설명은 주석에 달아놓았습니다!
※github : https://github.com/A6ly/WinmineMapHack
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
#include <locale.h>
#include <wchar.h>
#include <conio.h>
#define BUFFER_SIZE 512
#define MAP_SIZE 700
typedef struct {
BYTE MaxWidthX;
BYTE MaxHeightY;
BYTE ALLMineCount;
}GameInfo;
const unsigned int ADR_MINE_MEMORY = 0x01005361; // 지뢰찾기의 메모리 주소
const unsigned int ADR_MINE_ALL_COUNT = 0x010056A4; // 전체 지뢰 갯수의 주소
const unsigned int ADR_WIDTH_X = 0x1005334;
const unsigned int ADR_HEIGHT_Y = 0x1005338;
const BYTE EMPTY_VALUE = 0x0F; // 빈 박스의 메모리 값
const BYTE MINE_VALUE = 0x8F; // 지뢰가 있는 박스의 메모리 값
const wchar_t * EMPTY_BOX = L"□";
const wchar_t * MINE_BOX = L"★";
const char *GameName = "winmine.exe";
DWORD GetPID(LPCSTR gamename) { // 지뢰찾기 프로세스의 PID를 얻는 함수
char Buffer[BUFFER_SIZE] = "";
HANDLE ProcessSnapshot = INVALID_HANDLE_VALUE;
DWORD ppid = 0xFFFFFFFF; // winmine.exe의 PID 값을 담는 변수
BOOL ProcessInfo = FALSE; // 프로세스 정보를 담는 변수
PROCESSENTRY32 pe; // 프로세스 엔트리
pe.dwSize = sizeof(PROCESSENTRY32);
ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 프로세스 목록을 얻어오는 HANDLE 정의
ProcessInfo = Process32First(ProcessSnapshot, &pe); // 프로세스 엔트리의 자료를 가져와 저장
while (ProcessInfo) { // 프로세스 엔트리에 자료가 없다면 FALSE 반환 -> Break;
WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, 100, Buffer, 100, NULL, NULL); // 현재 실행중인 .exe 파일의 이름을 char형으로 변환하고 Buffer에 저장
if (!strcmp(gamename, Buffer)) { // gamename과 Buffer가 같으면 실행
ppid = pe.th32ProcessID; // ppid에 winmine.exe의 PID 넣음
break;
}
ProcessInfo = Process32Next(ProcessSnapshot, &pe); // Process32Next()루틴을 이용하여 pe의 다음 프로세스를 스냅샷에서 받아옴
}
CloseHandle(ProcessSnapshot);
return ppid; // PID 반환
}
void ReadMapInfo(HANDLE handle, GameInfo *MapInfo) { // MapInfo의 메모리를 읽어주는 함수
ReadProcessMemory(handle, (LPCVOID)ADR_WIDTH_X, &MapInfo->MaxWidthX, 4, NULL);
ReadProcessMemory(handle, (LPCVOID)ADR_HEIGHT_Y, &MapInfo->MaxHeightY, 4, NULL);
ReadProcessMemory(handle, (LPCVOID)ADR_MINE_ALL_COUNT, &MapInfo->ALLMineCount, 4, NULL);
}
void Hack(const BYTE *Map, const GameInfo MapInfo) { // 반복문을 통해 맵정보를 출력하는 함수
int i, count = 0;
for (i = 0; i < MAP_SIZE; i++) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
if (Map[i] == EMPTY_VALUE) { // 0x0F라면 빈박스 출력
wprintf(L"%ls", EMPTY_BOX);
count++;
}
else if (Map[i] == MINE_VALUE) { // 0x8F라면 별 출력
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
wprintf(L"%ls", MINE_BOX);
count++;
}
else if (0x40 <= Map[i] && Map[i] <= 0x43) { // 지뢰가 아닌 곳을 눌렀을 때 나오는 자연수 출력
wprintf(L"%2d", Map[i] - 0x40);
count++;
}
else if (Map[i] == 0x10) // 0x10이라면 개행
{
printf("\n");
while (Map[++i] != 0x10) {
continue;
}
}
else { continue; }
if (count == MapInfo.MaxWidthX * MapInfo.MaxHeightY) { // count가 맵의 넓이와 같아진다면 break
break;
}
}
}
int main() {
system("title winmine.exe MapHack!!!");
system("mode con cols=80 lines=25");
setlocale(LC_ALL, "Korean"); // 경로에 한글이 있을때 파일 입출력이 작동하지 않는 문제를 해결
HANDLE handle;
DWORD PID;
GameInfo MapInfo = { NULL, };
BYTE Map[MAP_SIZE] = { NULL, };
PID = GetPID(GameName);
if (!(handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID))) // handle에 지뢰찾기의 PID를 넣는다. 지뢰찾기의 PID의 값이 없다면 에러 메세지 출력
{
printf("※ Not open proecss! ※\n\n※ Not open proecss! ※\n\n※ Not open proecss! ※");
getch();
}
while (1) {
ReadProcessMemory(handle, (LPCVOID)ADR_MINE_MEMORY, Map, MAP_SIZE, NULL); // Map의 메모리 읽기
ReadMapInfo(handle, &MapInfo);
printf("@@ Winmain.exe MapHack!!! @@\n\n");
Hack(Map, MapInfo);
printf("\n\n");
printf("지뢰 : %d개", MapInfo.ALLMineCount);
Sleep(1000);
system("cls");
}
}
'Programming > C &C++' 카테고리의 다른 글
[C++, MFC] 소켓 통신, 시리얼 통신을 이용한 파일 전송 프로그램 개발 (0) | 2020.02.20 |
---|---|
[C++] 양방향 소켓 채팅 프로그램 개발 (0) | 2019.03.23 |
[C++, Qt] PC 카카오톡 광고 숨기기 (2) | 2018.11.09 |
[C] 회원 관리 프로그램(Linked List, 파일 입출력) (1) | 2018.04.02 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 멘토링
- Unity
- CodeEngn
- xcz.kr
- 풀이
- 안드로이드 멘토링
- C#
- Level 04
- Level 03
- HackingCamp
- unity2d
- Write-up
- Level 05
- c++
- wargame
- Reversing
- reversing.kr
- Level 02
- Advance RCE
- Programming
- Level 06
- 17th HackingCamp CTF
- hackerschool
- Basic RCE
- Android
- 유니티
- ftz
- pwnable
- Level 01
- 안드로이드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함