게임해킹/커널 게임 해킹

[게임 해킹] 드라이버 통신 방법 data ptr hook 설명 (안티치트 우회)

cp_good: 2022. 6. 28. 21:41
반응형

안티치트 우회에 필요한 드라이버와 유저 프로그램과 통신방법 중 하나인 data ptr hook입니다.
원본 소스코드입니다.
 
설명을 위해 소스코드 수정했습니다.
기본적인 C문법은 알고 있어야 합니다.
DbgPrintEx는 의미 없어서 주석 설명 안 했습니다.

INT64(__fastcall* Qword_ptrOriginal)(PVOID, PVOID, PVOID, PVOID, PVOID);//원본 함수 포인터입니다

INT64 __fastcall Qword_ptrHooked(PVOID a1, PVOID a2, PVOID a3, PVOID a4, PVOID a5) 
{
	DbgPrintEx(0, 0, "후킹 함수 진입!\n");
	DbgPrintEx(0, 0, "a3: 0x%p\n", a3);
	
	//여기서 내 프로그램에서 보냈는지 체크하기 위해 체크를 해줍니다
	if(a3 == 0x787878) //뭐 이런 식으로 체크
	{
		return 0; //내 프로그램이면 작업 후 정상적으로 리턴 시켜줍니다
	}
	
	return Qword_ptrOriginal(a1, a2, a3, a4, a5); //내 프로그램이 아니면 원래 함수로 리턴 시킵니다
}

NTSTATUS DriverEntry(PVOID lpBaseAddress, DWORD32 dwSize) { //드라이버 진입점입니다
	UNREFERENCED_PARAMETER(lpBaseAddress); //사용 안 하는 파라미터 처리 해주는 거임
	UNREFERENCED_PARAMETER(dwSize);        //사용 안 하는 파라미터 처리 해주는 거임
	
	//"get_module_base"이 함수는 따로 작성해야 합니다
	// 시스템 모듈 베이스주소를 구해주는 함수입니다
	PVOID KernelBase = (PVOID)get_module_base("\\SystemRoot\\System32\\win32kbase.sys"); 
	if (!KernelBase) { // 구했는지 체크
		DbgPrintEx(0, 0, "베이스 주소 찾지 못했음!\n");
		return 1;
	}
	DbgPrintEx(0, 0, "베이스 주소: 0x%p\n", KernelBase);

	//"FindPatternImage"이 함수도 따로 작성해야 합니다
	//모듈 PE헤더를 이용해서 패턴을 찾아 주소를 구하는 함수입니다
	//"ApiSetEditionGetUserObjectInformationEntryPoint" 함수의 data ptr 패턴을 찾는 겁니다
	PVOID qword_ptr = FindPatternImage((PCHAR)KernelBase, "\x74\x20\x48\x8B\x44\x24\x00\x44", "xxxxxx?x");
	if (!qword_ptr) {
		DbgPrintEx(0, 0, "qword_ptr 찾지 못함!\n");
		return 1;
	}
	DbgPrintEx(0, 0, "Qword_ptr: 0x%p\n", qword_ptr);

	//밑에 상세 설명 있습니다
	//패턴 스캔으로 찾은 주소에서 0xA 만큼 빼기 
	UINT64 qword_ptr_derf = (UINT64)(qword_ptr)-0xA;

	//그리고 주소에 3을 더하고 참조해서 4바이트만큼 저장하고 7을 더함
	qword_ptr_derf = (UINT64)qword_ptr_derf + *(PINT)((PBYTE)qword_ptr_derf + 3) + 7;

	//InterlockedExchangePointer 함수로 주소 바꿔치기(후킹 완료)
	*(PVOID*)&Qword_ptrOriginal = InterlockedExchangePointer((PVOID*)qword_ptr_derf, (PVOID)Qword_ptrHooked);
	
	DbgPrintEx(0, 0, "드라이버 로드 완료!\n");
	return 0;
}

 
봐도 이해 안 되는 부분이 있었는데요.

UINT64 qword_ptr_derf = (UINT64)(qword_ptr)-0xA;

0xA를 빼주는 이유는 패턴 스캔으로 찾은 주소는 0x1C0092F5F인데
진짜 찾아야 하는 곳은 0x1C0092F55이기 때문입니다.
계산기로 주소를 빼보면 0x1C0092F5F - 0x1C0092F55 = 0xA입니다.

 

IDA로 살펴봤습니다
박스 쳐진 곳과 위 그림의 패턴과 비교해보세요. 00은 무시한다는 뜻입니다

 
0x1C0092F55 주소를 찾았으니
"cs:qword_1C0251E20" 이곳에 올라오는 data ptr 주소를 찾는 게 다음 목적입니다.

qword_ptr_derf = (UINT64)qword_ptr_derf + *(PINT)((PBYTE)qword_ptr_derf + 3) + 7;

사진을 보면 0xFFFF9B9973692F55가 0xA를 뺀 주소입니다.

 

박스 친 곳 참고

 
0x3을 더하는 이유는 data ptr 주소를 찾기 위한 오프셋을 구하기 위함입니다.
0xFFFF9B9973692F55 + 0x3을 더하고 4바이트만 참조하면 오프셋 0x1BEEC4이 나옵니다.

 

치트엔진으로 확인했습니다 001BEEC4

 
이 오프셋에 0x7을 더해주는 이유는 0x7을 더해야 정확한 주소가 나옵니다.
안 더했을 경우 : 0xFFFF9B9973851E19
더했을 경우 : 0xFFFF9B9973851E20
 

 
0x1BEECB 을 만들고 0xFFFF9B9973692F55와 더해주면
0xFFFF9B9973851E20 주소가 나옵니다.
치트엔진으로 살펴본 주소와 똑같습니다.

 

치트엔진으로 살펴본 data ptr 주소입니다

 
이 주소는 무슨 테이블 같은 곳으로 연결되는 것 같은데
테이블의 주소를 내 드라이버 주소와 바꿔치기하는 것입니다.

 

테이블 같은곳

 
후킹을 하니 변하는 주소

 

변하는 주소

 
저 함수 말고 다른 함수를 후킹 하고 싶으면
후킹함수 찾는 법을 읽어보세요.
https://cpgood.tistory.com/4

[게임 해킹] data ptr hook 후킹 할 함수 찾는 방법 (안티치트 우회)

드라이버와 유저 모드 통신방법 중 하나인 data ptr hook의 후킹 할 함수를 찾는 법 알아보겠습니다. 이 글이랑 보면 좋습니다! 게임해킹(안티치트 우회)에 활용됩니다. 후킹 할 함수를 찾는 이유는

cpgood.tistory.com

 
data ptr hook이라고 알려진 기술을 살펴봤는데
이렇게 후킹 했을 경우 탐지할 수 있는 방법은
0xFFFF9B9973851E20에 있는 포인터가 이상 없는 모듈을 가리키면 정상이고 아니면 후킹 된 거겠죠
그래서 포인터에 포인터를 후킹 하면 안전하다고 하는 거 같습니다.
머리 아프니 이제 그만 알아봅시다.
 
이 코드는 작동하지만 템플릿입니다.
게임에 사용하려면 커널에서 베이스 주소 가져오기,
커널에서 메모리 읽기 쓰기를 구현해야 사용할 수 있습니다.


디스코드 : cpgood#0780
메일 : qmffhrm@protonmail.com

반응형