(리버싱 핵심원리)윈도우 메시지-후킹 코드 정밀 분석

2021. 5. 4. 23:31리버싱/리버싱 핵심원리

*(혹시나 코드를 이해하는데 있어, 어려움을 겪는 사람을 위해 따로 만든 글입니다.

물론 저도 잘하진 않지만 그래도 제가 이해한 대로 쉽게 설명할려고 합니다.)

 

먼저 윈도우 메시지 후킹으로 무엇을 할려 했는지는 전 시간에 했기때문에 아실겁니다.

바로 메모장을 주 타겟으로 하고, 운영체제와 프로세스 간에 메시지를 후킹하여 보내지 않도록 하여 입력할수 없도록 만들었습니다.

 

실습은 하지 않고 코드 분석만 할겁니다.

 

헤더파일을 불러옵니다. 근데 conio.h는 본적이 없죠? 무슨 헤더파일인지 알아봅시다.

이 헤더파일(conio.h)는 입력을 받고 출력하는 그런 헤더파일입니다. 좀 있다가 나옵니다.

#define을 사용해서 상수값으로 설정해 줍니다. 변하지 않는 수? 입니다. 한마디로 저건 절대 저희가 대입을 하거나 수정을 할수 없습니다. 그냥 정해져 있는 값이죠. 일일이 적는 불편함을 없애기 위해 한 것입니다.

문자열 이름만 봐도 무슨 역할인지 아실거라고 봅니다.

자 이 코드는 포인터로 된 함수를 정의 하는건데요. 근데 저 초록색 PFN는 뭘까,,?

그냥 이름입니다. 별 다른 그런게 아닙니다.

 

메인함수 처음부분입니다. 먼저 HMODULE는 뭘까,? 코드 영역에 대한 핸들입니다.

그리고 HookStart변수 타입이 아까 말한 함수 포인터형식입니다

먼저 LoadLibraryA이 함수는 아까 정의한 상수를 가져와서 KeyHook.dll이라는 dll파일을 가져옵니다.

근데 만약 NULL값(아무 값이 없다면) 오류를 출력하도록 합니다.

그 다음 아까 이미 hdll의 저희가 인젝션할 dll이름을 적어줬습니다. 아마도 HookStart변수에다가 hdll로부터 가져온것을 DEF_HOOKSTART로 넘겨준게 아닐까 싶습니다. 이게 좀 해석하기 나름인데 저는 이렇게 말하겠습니다. 

간단하게 후킹 시작 > q누르면 > 후킹 종료 > dll해제 입니다.

지금까지 한것을 정리하면?

1. 인젝션할 dll파일 로딩

2. 인젝션할 dll로 부터 함수주소 얻기

3. 후킹시작

4. 후킹종료

가 되겠습니다.

 

이제 본격적인 아주 중요한 내부인, dll파일을 정밀 분석해 보겠습니다.

처음에 먼저 상수로 notepad.exe라는 인젝션할 타겟을 선언합니다.

그 다음에 어떠한 타입으로 변수를 만드는데, 저 각각 어떤 타입인지 알아보겠습니다.

HINSTANCE = 운영체제에서 실행되는 프로그램 ID구별하기 위한 자료형

HHOOK = 전역훅 자료형입니다. 메시지를 중간에 Hook하는 자료형이랍니다.

HWND = 파일에 접근할려면 파일핸들이 필요하듯이 운영체제에 접근할려면 핸들이 필요한데 그것이 바로 이것이다.

 

그 전에도 말했지만 dll이 실행될때 DllMain이 실행된다고 말했다. 그 특성을 이용하여 dll이 인젝션되고 내가 원하는 일을 수행할수 있다. 처음부번 어테치에서 원하는 코드 실행이 가능하다.

 

먼저 DllMain인자 하나씩 보겠다 첫번째 인자는 DLL 모듈에 대한 핸들의 대한 인자이다. 즉 프로세스 ID를 구별, DLL 모듈에 대한 핸들? 아마도 DLL를 찿는다는 의미? DLL를 모듈에 대한 권한? 일것이다.(추측)

두번째 인자는 함수 호출을 하는 이유인데, 뭔 소린지는 모르겠다.

세번째 인자는 예약석? 세번째 인자는 지금 여기선 몰라도 된다.

이제 우리가 원하는 작업을 수행하는 구간입니다.

여기서도 인자를 받게 되는데 무슨 의미인지 하나씩 봅시다.

첫번째 인자는 메시지를 처리방법을 결정하는 코드라네요.

한마디로 0이상일 경우 후킹을 하게 만들고, 0 미만이면 후킹을 시도하지 않도록 판단을 하게 할수있습니다

두번째 인자는 가상키 코드입니다.

가상 키보드는 매우 많아요

특정한 키가 눌러졌는지? 확인하는 플래그 같습니다

여기서 왜 0x800000000...인지 궁금했는데 그냥 32비트는 8바이트이고. 눌러져 있으면 플래그가 0이 되고, 아니면은 1이니깐 저렇게 했다고 생각한다

GetModuleFileNameA API는 지정된 모듈을 포함하는 파일의 정규화 된 경로를 검색합니다. 현재 실행파일 프로세스 주소를 검색합니다.

첫번째 인자가 NULL이면 실행파일 프로세스 주소를 검색, 두번째 인자는 경로를 받는 버퍼크기입니다. , 세번째 인자는 버퍼크기? 라네요.

strrchr 함수는 가장 마지막을 나타나는 문자를 찿는다. 그리고 포인터로 받는다,

아까 저걸 왜 하는지 알게하는 부분이다. 현재 프로세스 실행된 주소가 만약 notepad.exe라면 후킹을 시도한다.

만약 내가 notepad.exe를 실행하면 그 경로를 전부 얻어오고 비교를한다.

notepad.exe가 아니라면 말을 바꾸듯이 원래대로 진행한다.

해당 함수는 가로챈 훅을 다시 프로세스에게 보내는 역할을 한다.

 

이제 마지막 부분인데,,흠 이상한 구조로 되어 있다. 일단 #ifdef는 뭐고, __cplusplus가 뭔지부터 알아내자.

근데 저 구문을 왜 쓰는걸까? 바로  C언어 구문을 추가하라는 뜻입니다. 왜냐면 C++에서는 C언어 자체를 쓸수 없기 때문이죠.

#ifedf는 일종의 헤더 겹침을 막기위한 용도입니다. #ifdef 헤더명 으로 헤더파일을 불러올수 있습니다.

만약 이전에 이미 선언되어 있다면 #endif로 점프합니다.

이건 도데체 뭘까요? 바로 DLL파일에서 함수를 내보낼수가 있습니다. 그걸 exe에서는 받은 후

아까 이것을 실현시킬수가 있습니다.

일단 HookStart내용은 위 사진과 같습니다.

먼저 g_hHook이라는 변수입니다.

위 함수는 훅을 설치하는 함수입니다(SetWindowsHookEx)

매개변수의 대한 설명을 하자면

 

MSDN에서는 이와 같이 정의하였습니다.

그 다음 이 코드는 만약 후킹중이라면 언훅, 즉 후킹을 멈춰라 라는 말이 되겠습니다.

이렇게 해서 메시지 후킹 예제 코드를 정밀 분석해봤습니다.