동방프로젝트(이하 동프)를 분석하고 오토봄을 만들어 보자!

(코딩편) - 피탄을 감지 하자!


0. 동방프로세스를 읽어온다.

1. readprocessmemory를 통해 0x477834에 있는 ebp값을 받아온다.

2. readprocessmemory를 통해 ebp+478에 있는 값을 실시간으로 받아온다.

3. 읽어온 값이 02면 'x'키를 입력하여 봄을 사용하게 한다.

4. 1부터 반복

저번에 이야기 했던 코딩 계획입니다.

이번에는 0~2까지만 하겠습니다.


#include "stdio.h"
#include "windows.h"
#include "tlhelp32.h"
#include "stdlib.h"

#pragma warning(disable : 4996)
#define DEF_PROC_NAME ("th10.exe")

DWORD FindProcessID(LPCTSTR szProcessName);
BOOL hack_start(DWORD dwPID);

int main(int argc, char* argv[])
{
	for (;;) {
		int a;
		printf("풍신록 오토봄 프로그램입니다. 풍신록을 실행 후 '1'을 입력해 주세요. ");
		scanf("%d",&a);
		if (a == 1)break;
		else printf("잘못된 값 입니다.");
	}
	DWORD dwPID = 0xFFFFFFFF;

	// find process
	dwPID = FindProcessID(DEF_PROC_NAME);
	if (dwPID == 0xFFFFFFFF)
	{
		printf("풍신록 감지 실패\n");
		system("pause");
		return 1;
	}
	
	if (!hack_start(dwPID))printf("메모리 구하기 실패\n");
	system("pause");
	return 0;
}

DWORD FindProcessID(LPCTSTR szProcessName)
{
	DWORD dwPID = 0xFFFFFFFF;
	HANDLE hSnapShot = INVALID_HANDLE_VALUE;
	PROCESSENTRY32 pe;

	// Get the snapshot of the system
	pe.dwSize = sizeof(PROCESSENTRY32);
	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

	// find process
	Process32First(hSnapShot, &pe);
	do
	{
		if (!_stricmp(szProcessName, pe.szExeFile))
		{
			dwPID = pe.th32ProcessID;
			break;
		}
	} while (Process32Next(hSnapShot, &pe));

	CloseHandle(hSnapShot);

	return dwPID;
}

BOOL hack_start(DWORD dwPID)
{
	HANDLE hProcess;

	// #1. dwPID 를 이용하여 대상 프로세스(th10.exe)의 HANDLE을 구함
	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
		return FALSE;
	
	for (;;) {
		DWORD address = { 0x477834 };
		DWORD buffer = 0;
		bool uak = false;
		//메모리에 저장된 EBP값 읽어옴
		ReadProcessMemory(hProcess, (LPVOID)address, &buffer, 16, NULL);
		
		//메모리에 저장된 피탄 후 프레임 카운트를 받음
		address = { buffer + 0x478 };
		//프레임 카운트 읽어옴
		ReadProcessMemory(hProcess, (LPVOID)address, &buffer, 16, NULL);
		if (buffer == 0&&!uak) {
			printf("피탄감지!\n");

			uak = true;
			
			//SendMessage((HWND)hProcess, WM_KEYDOWN, 0x50, 0);
			continue;
		}
		if (buffer != 2 && uak) {
			uak = false;
			//SendMessage((HWND)hProcess, WM_KEYUP, 0x50, 0);
		}

	}
	return TRUE;
}


미완성 소스지만 이번 글을 쓰기에는 충분 한 소스입니다.



일단 사용한 주요함수부터 알아 봅시다.

1. ReadProcessMemory : 말 그대로 입니다. 지정된 프로세스의 메모리를 읽어 오는 함수 입니다.


2. FindProcessID : http://reversecore.com/40에서 가져온 함수 입니다. 프로세스의 PID를 찾아주는 역할을 합니다



각 파트별로 설명하겠습니다.


	DWORD dwPID = 0xFFFFFFFF;

	// find process
	dwPID = FindProcessID(DEF_PROC_NAME);
	if (dwPID == 0xFFFFFFFF)
	{
		printf("풍신록 감지 실패\n");
		system("pause");
		return 1;
	}

풍신록이 실행 중인지 확인 합니다. 


DWORD FindProcessID(LPCTSTR szProcessName)
{
	DWORD dwPID = 0xFFFFFFFF;
	HANDLE hSnapShot = INVALID_HANDLE_VALUE;
	PROCESSENTRY32 pe;

	// Get the snapshot of the system
	pe.dwSize = sizeof(PROCESSENTRY32);
	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

	// find process
	Process32First(hSnapShot, &pe);
	do
	{
		if (!_stricmp(szProcessName, pe.szExeFile))
		{
			dwPID = pe.th32ProcessID;
			break;
		}
	} while (Process32Next(hSnapShot, &pe));

	CloseHandle(hSnapShot);

	return dwPID;
}

프로세스 목록을 확인 한 뒤 제가 찾는 프로세스(th10.exe)를 찾아 PID를 가져옵니다.


BOOL hack_start(DWORD dwPID)
{
	HANDLE hProcess;

	// #1. dwPID 를 이용하여 대상 프로세스(th10.exe)의 HANDLE을 구함
	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
		return FALSE;
	
	for (;;) {
		DWORD address = { 0x477834 };
		DWORD buffer = 0;
		bool uak = false;
		//메모리에 저장된 EBP값 읽어옴
		ReadProcessMemory(hProcess, (LPVOID)address, &buffer, 16, NULL);
		
		//메모리에 저장된 피탄 후 프레임 카운트를 받음
		address = { buffer + 0x478 };
		//프레임 카운트 읽어옴
		ReadProcessMemory(hProcess, (LPVOID)address, &buffer, 16, NULL);
		if (buffer == 0&&!uak) {
			printf("피탄감지!\n");

			uak = true;
			
			//SendMessage((HWND)hProcess, WM_KEYDOWN, 0x50, 0);
			continue;
		}
		if (buffer != 2 && uak) {
			uak = false;
			//SendMessage((HWND)hProcess, WM_KEYUP, 0x50, 0);
		}

	}
	return TRUE;
}

피탄을 감지하고 x키를 누르는 부분입니다(아직 키를 누르는 곳은 구현 되지않음)

자세한 내용을 원하실 경우 댓글로 질문 해주세요.


WRITTEN BY
Dukup11ch1
무근본, 실력 0, 아는척하기위한 블로그. 저는 귀엽습니다

,

동방프로젝트(이하 동프)를 분석하고 오토봄을 만들어 보자!

(분석편) - 현재 몇프레임이 지났는지 알려주는 메모리를 찾자!


8프레임의 대기시간을 재는 곳은 찾았지만 오토봄을 코딩하려면 그 프레임이 저장되는 메모리 위치를 알아야 됩니다. 한 번 찾아 봅시다.


분명 같은 곳인데 실행 할 때마다 ebp가 변해서 위치도 계속 변합니다 ㅠㅠ

하지만 ebp같은 cpu 레지스터는 접근하기 어려워요 그래서 포기할까 하던중에....

한 분에게 질문을 했습니다. 그랫더니 레지스터까지 받는 것보단 메모리에서 승부를 보는 것이 좋을 것 같다고 하셧습니다. 그 말을 듣고 디버거를 다시 봤습니다.

ECX와 EBP가 같다는 것을 발견했습니다. 컴파일러 중에는 레지스터끼리 값을 옮길때 메모리를 거쳐서 옮기는 경우도 있으므로 메모리에서 찾아 보았습니다. 

코드를 조금만 내려 볼까요?

esi에 어떤 0x4776ec에 있는 값을 넣는 군요 어떤 값일까요?


메모리 주소를 저장 하네요.


덤프로 따라가 봅시다.

오오 뭔진 모르겠지만 메모리 주소들을 저장하고 있군요.

하지만 ebp주소인 0x7188b08은 보이지 않습니다.


하지만 이 주변 어딘가에 또 메모리주소를 저장하는 곳이 있을 겁니다. 스크롤을 내려보죠.


오 ebp와 값이 같은 것을 찾았습니다.

저 위치는 0x477834에요.







이제 코딩을 위한 계획을 짜 보도록 하죠


0. 동방프로세스를 읽어온다.

1. readprocessmemory를 통해 0x477834에 있는 ebp값을 받아온다.

2. readprocessmemory를 통해 ebp+478에 있는 값을 실시간으로 받아온다.

3. 읽어온 값이 02면 'x'키를 입력하여 봄을 사용하게 한다.

4. 1부터 반복


그럼 다음에 봐요~


WRITTEN BY
Dukup11ch1
무근본, 실력 0, 아는척하기위한 블로그. 저는 귀엽습니다

,

동방프로젝트(이하 동프)를 분석하고 오토봄을 만들어 보자!

(분석편) - 피탄 후 8프레임의 대기 시간을 찾자!


저번에 잔기가 줄어드는 부분을 찾았으니 이번에는 8프레임의 대기시간을 재는 곳을 찾아봅시다.



이 사진을 보면 가장 위에 $가 보일 겁니다.

저것이 의미 하는 것은 저부분이 함수의 시작부분이라는 것이고 그말은 즉슨 당연히 이 부분을 호출하는 곳이 있겠죠? 이런건 다 디버거가 알려준답니다.


sub_425AA3+1에서 호출 했다고 하네요. 이쪽으로 가볼까요?


찾았습니다! 하지만 이쪽에 오면 무조건 잔기가 줄게 되겠군요.

그러므로 피탄후 8프레임의 대기시간을 세는 곳은 이것보다 앞에 있을 겁니다.



스크롤을 조금만 올려보면...


찾았네요! 오토봄을 만드려면 저부분에 오는 순간 x키를 누르게 프로그램을 만들면 될겁니다. 그것에 대한 포스팅은 다음번에 하도록 하죠


WRITTEN BY
Dukup11ch1
무근본, 실력 0, 아는척하기위한 블로그. 저는 귀엽습니다

,

동방프로젝트(이하 동프)를 분석하고 오토봄을 만들어 보자!

(분석편) - 잔기가 줄어드는 곳을 찾자



동프는 게임내 값을 숨기거나 암호화를 하지 않습니다. 

그렇기 때문에 Cheat Engine을 통해 쉽게 잔기가 있는 메모리주소를 찾을 수 있습니다.



동프를 창모드로 켜줍시다.


그리고 Cheat Engine을 실행해서 동프를 선택해 줍시다.


당연히 플레이를 해야겠죠?


하지만 플레이 전에 해야 될이 있습니다.



현재 잔기가 2개죠?



Cheat Engine에서 2를 검색 해 줍시다.


그리고 열심히 플레이 하시다가....

.

맞아버려서 잔기가 달게 되면 일시정지를 하시고


잔기를 검색 해주시면 됩니다.


잔기가 있는 메모리위치를 찾았군요


이제 디버거에서 저 위치에 breakpoint를 걸어 줍시다

 

하드웨어 breakpoint로 걸어 줍시다.

이 상태에서 게임을 게속하다 잔기개수가 줄어들면 한 곳에서 멈추게 됩니다.



여기서 멈추게 되죠


각 코드별 설명은 사진에 주석을 달아 두었습니다.



일단 잔기가 다는 곳을 찾았으니 잠깐 쉬고 갑시다





WRITTEN BY
Dukup11ch1
무근본, 실력 0, 아는척하기위한 블로그. 저는 귀엽습니다

,

동방프로젝트(이하 동프)를 분석하고 오토봄을 만들어 보자!

(개념편)

17년11월08일 현재 오토봄 코딩 중



이 포스팅에서 다룰 개념은 총 2가지 입니다.

1. 피탄봄

2. 오토봄



피탄봄은 캐릭터가 탄막에 맞은 직후 8프레임(0.133초)안에 봄을 사용 함으로써 잔기(목숨)이 달지 않고 계속 진행하는 것을 의미 합니다. 


위 사진은 탄막에 맞은 직후 입니다. 저 상태에서 폭탄을 사용하면 잔기가 달지 않고 게임진행이 가능합니다.



하지만 피탄봄 사용가능 시간이 말이 8프레임이지 0.133초안에 눌러야 하는 것이므로 사실상 사람이 한다는 것은 탈인간들은 제외하곤 아주 힘들죠

이걸 자동으로 하는 것을 오토봄이라 합니다. 일종의 '핵'이죠



이번 글은 여기서 마치고 오토봄 만들기(2)에서 다시 만나요~




WRITTEN BY
Dukup11ch1
무근본, 실력 0, 아는척하기위한 블로그. 저는 귀엽습니다

,