발자취
악성코드 Pre-Lab1. 윈도우즈 메시지 후킹 본문
리버싱 핵심원리 교재에 있는 소스코드를 활용하여 윈도우즈 메시지 후킹 실습을 진행할 것이다.
(리버싱 핵심원리 21장)
1. 개념
Windows Message Hooking이란?
윈도우즈 시스템의 메시지 큐는 키보드를 통해 들어오는 입력을 해당 애플리케이션 메시지 큐에 전달한다.
이때, 윈도우즈 시스템 메시지 큐와 애플리케이션 메시지 큐 사이에 Hook Chain을 설정하여 윈도우즈 시스템 메시지 큐에서 애플리케이션 메시지 큐로 향하는 입력값이 전달되지 않도록 차단하는 것이 윈도우즈 메시지 후킹이다.
본 실습에서는 아래의 그림과 같이 윈도우즈 시스템 메시지 큐에서 애플리케이션 메시지 큐로 notepad 입력값이 전달되지 않도록 Hook Chain을 설정할 것이다.

본 실습에서는 SetWindowsHookEx() 함수를 이용하여 Hook Chain을 설정할 것이다
SetWindowsHookEx() 함수의 정의
HHOOK SetWindowsHookEx {
int idHook,
HOOKPROC lfpfn,
HINSTANCE hMod,
DWORD dwThreadId
};
SetWindowsHookEx() 함수에는 4가지의 인자가 존재하고,
dwThreadId 값이 0으로 설정되었을 때, 글로벌 후킹이 생기게 된다. 즉, 0으로 설정해야 후킹된다.
2. 실습
가상머신 윈도우10에서 실습 진행
1. 소스코드 다운로드
https://github.com/reversecore/book 웹사이트에서 소스코드.zip을 다운로드 받는다
2. 비주얼스튜디오에서 HookMain.exe 파일 생성

파일 > 새로 만들기 > 프로젝트 > 빈 프로젝트 > HookMain 생성하면
C:\users\사용자명\source\repos\ 경로에 HookMain 폴더가 생겼을 것이다


처음에 다운받은 소스코드\03_DLL_Injection\21_Windows_메시지_후킹 속 HookMain.cpp를 C:\users\사용자명\source\repos\HookMain\HookMain 경로에 복사한다 (*주의: HookMain 속 HookMain 폴더에!)

비주얼 스튜디오에서 소스 파일 > 추가 > 기존 항목 > (방금 추가했던) HookMain.cpp 선택

디버그 > HookMain 속성 > 일반 > 문자 집합 > '유니코드 문자 집합 사용'으로 수정

빌드 > 솔루션 빌드 하여 실행 시킴!
터미널에 '성공'이 뜨면 됨

C:\users\사용자명\source\repos\HookMain 경로에 Debug 폴더가 생긴 것을 확인할 수 있다 (*주의: HookMain 속 HookMain 폴더 아님!!!)
해당 폴더 안에 들어가보면 HookMain.exe 파일이 생긴 것을 확인할 수 있다
3. 비주얼스튜디오에서 KeyHook.dll 파일 생성

HookMain.exe 파일 생성한 방법과 같은 방식으로 KeyHook 프로젝트 생성 후, cpp 파일을 붙여넣어줌
*주의!
디버그 > KeyHook 속성 > 일반에서 변경해줘야 할 요소가 두가지임!
- 문자 집합: 유니코드 문자 집합 사용
- 구성 형식: 동적 라이브러리(.dll)
HookMain은 .exe 파일로 만들어줘야해서 그대로 뒀지만, KeyHook은 .dll 파일로 만들어주기 위해 구성 형식도 바꿔줌
그 뒤로는 마찬가지로 빌드해준다

HookMain.exe 파일과 KeyHook.dll 파일이 같은 경로에 있어야 하기 때문에, KeyHook.dll을 HookMain.exe가 있는 위치로 복붙해준다
4. Hooking 시작

메뉴 > Windows PowerShell 실행 후 HookMain.exe가 존재하는 경로로 이동 (cd ~)
ls 해보면 HookMain.exe가 존재하는 거 확인 가능함
./HookMain.exe 써서 실행 → 정상 동작하는 거 확인 가능!

메모장을 실행
키보드로 뭘 입력해도 화면에 출력되지 않음 → 후킹 성공!
KeyHook.dll이 중간에서 키보드에서 notepad로 입력값이 가는걸 차단하는 원리임
다른 프로그램 (edge, chrome 등)을 실행해서 키보드로 입력해보면 정상적으로 화면에 출력되는 것을 확인할 수 있다
KeyHook.dll은 오직 notepad의 입력값만 차단하는 것!
PowerShell에 'q'를 입력해서 HookMain.exe를 실행 종료 시킨 후, 노트패드에 입력해보면 정상적으로 화면에 출력되는 것을 확인할 수 있다!
3. 코드 분석
후킹에 사용된 코드인 HookMain.cpp와 KeyHook.cpp 코드를 분석해볼 것이다.
1. HookMain.cpp

HookMain.cpp는 HookMain.exe를 만드는 소스코드이다.
[5] DEF_DLL_NAME은 강제 인젝션되는 KeyHook.dll이다.
[6][7] DEF_HOOKSTART, DEF_HOOKSTOP은 실질적으로 후킹을 시작하고 끝내는 파일이다.
[14] HMODULE은 dll을 나타내는 모듈이다
[20] LoadLibraryA() 라는 함수를 가지고 exe 파일 안에서 KeyHook.dll을 로드한다. LoadLibraryA() 함수는 원래라면 정상적인 dll 파일을 로드하는데 사용하겠지만, 지금 여기서는 악성 행위를 하는 dll을 로드하고 있다.
즉, HookMain.exe라는 악성코드에서 KeyHook.dll을 로드하는 것! 이 두 파일이 결합되어 하나의 악성행위를 하는 것이다.
이렇게 별도의 dll로 만든 이유는, 글로벌하게 모든 exe 파일에 들어갈 수 있게 만들기 위해서다. 활용성을 높이고 효율적으로 dll 파일을 사용하기 위한 것이다.

이와 같이 LoadLibraryA() 함수가 KeyHook.dll을 HookMain.exe의 메모리 공간에 가져다 넣어준다.
[21] hDll이 null이면 제대로 로드되지 않은 경우이다.
[28] GetProcAddress() 함수가 DEF_HOOKSTART 함수의 주소를 가져온다. 함수의 주소를 알아야 호출할 수 있기 때문에 이 함수를 통해 호출하고자 하는 함수의 주소를 가져오는 것이다.
[32] 후킹을 시작한다.
[35] ‘q’ 키를 누르기 전까지 프로그램이 계속 돌아간다.
[42] FreeLibrary() 함수를 통해 KeyHook.dll을 언로드한다. HookMain.exe 가상 메모리 공간에 들어가 있던 KeyHook.dll을 빼주는 것이다. (더이상 필요없기 때문)
2. KeyHook.cpp
KeyHook.cpp는 길이가 좀 길기 때문에 나눠서 분석하도록 하겠다

[4] DEF_PROCESS_NAME에 후킹하고자 하는 대상인 “notepad.exe”를 정의했다.
[6] HINSTANCE는 객체를 참조해줄 때 사용되는 데이터 타입이다
[7] HHOOK는 hook과 관련된 자료형
[8] HWND는 윈도우와 관련된 자료형
[10] DllMain(): 맨처음에 dll이 호출됐을 때 실행되는 함수이다
[14] ATTACH: dll 자체를 호출해서 실행하겠다! 해당 메인 프로세스에 연결해줌

KeyboardProc 함수는 실제로 후킹해주는 절차이다. 노트패드에는 키보드 입력값이 전달되지 않고, 노트패드가 아닌 애플리케이션에만 전달해준다.
[25] CALLBACK: 특정 이벤트가 발생했을 때 호출해달라고 지정해주는 키워드. 키보드 이벤트가 발생하면(=키보드가 눌리면) 이 함수를 호출한다.
[33] 0x80000000: 이러한 파라미터들은 내부에서 키보드가 입력될 때 알아서 들어가게 된다. 우리가 입력해주는 사항이 아님
키 값이 눌렸는지 안 눌렸는지에 따라 비트가 달라진다.
!param과 파라미터(위는 16진수로 표현되었으나 계산시 2진수로 계산됨)를 and 연산하는데, 이때 32번째 비트가 0인지, 1인지에 따라 키보드가 눌렸는지 안눌렸는지를 알 수 있게 되는 것이다. 0이면 키보드가 눌린 것!
[35] GetModuleFileNameA(): 특정 모듈을 포함하는 파일 경로를 획득해주는 함수이다. 즉, 현재 동작중인 프로세스의 경로 (예를 들어 노트패드가 실행되고 있다면, 노트패드의 경로를 획득해준다.) 첫번째 인자가 null이면 szPath에 그 경로 정보가 들어가게 된다.
[40] 현재 실행중인 프로세스의 이름이 노트패드인지 아닌지를 확인하는 함수이다. 이 if문이 true라면 notepad가 맞다는 뜻이므로 return 1을 해서 종료한다. 일반적인 경우에는 [47]라인대로 CallNextHookEx를 return 해준다.
strrchr(): szPath 안에서 \\가 나타나는 마지막 위치를 검색해준다.
여기서 구한 p값을 통해 현재 실행되고 있는 파일의 이름에 액세스가 가능해진다.
만약 C:\\notepad.exe라면 p는 \\일 것이고, p+1은 notepad.exe이 된다.

[53][58] dllexport는 외부로 호출한다는 의미의 키워드
HookStart()와 HookStop()은 외부로 수출해주는 함수로 정의되어 있다.
[55] SetWindowsHookEx(): 글로벌 후킹이 가능하게 해주는 함수. 네 가지의 인자가 들어간다.
1. 훅의 타입 (훅: 연결 / 어떤 식으로 후킹할지를 정해주는 인자)
2. 훅의 절차, 프로시저 (어떤 식의 후킹 절차를 밟을지)
3. 후킹 프로시저와 연결되어 있는 dll 모드 (어떤 프로시저를 사용해 후킹하는지)
4. dwThreadID: 이 4번째 인자가 0일 때 후킹이 적용됨(=두번째 인자가 적용됨)
코드의 인자를 보면..
1. 키보드 관련한 후킹을 하겠다. (키보드 입력을 중간에서 가로채는 공격)
2. 실제 후킹 작업을 해주는 프로시저가 KeyboardProc이다
3. dll 모드의 이름이 g_hInstance이다
4. 생각해보기
1. SetWindowsHookEx() 함수의 dwThreadID 파라미터를 0으로 설정하여 공격용 Hook을 설정했을 때 공격자가 취할 수 있는 장점은 무엇인가?
dwThreadID가 0으로 설정되었다는 것은 ‘글로벌 후킹’을 의미한다.
그렇다면, 글로벌 후킹을 했을 때 공격자가 취할 수 있는 장점은?
기본적으로 글로벌 후킹은 특정 프로세스만이 아닌 현재 실행되고 있는 모든 프로세스에게 후킹하는 것이기 때문에 공격의 범위 자체를 넓힐 수 있다. 따라서 최대한 많은 수의 프로세스들에게 공격을 할 수 있다는 장점이 있다.
위 실습에서는 notepad에만 공격을 했지만 다른 프로세스에도 공격할 수 있기 때문에 확장성이 있는 공격이라고 할 수 있다!
또한, 위 실습에서는 입력된 키값을 화면에 안보이게 하고 있지만, 화면엔 보이게 하면서 입력된 키값을 탈취하는 식의 공격도 할 수 있다.
이런 식으로 글로벌 후킹을 활용해서 추가적인 작업을 할 수 있다. 공격 범위를 확장할 수 있다!
2. 공격자가 SetWindowsHookEx() 함수를 이용하여 악성 DLL 파일을 정상적인 프로세스에 주입하였을 때, 탐지할 수 있는 방법은 무엇이 있는지 서술하시오. 정상적인 DLL 파일도 같은 방식으로 정상적인 프로세스에 주입될 수 있다고 할 때 False Positive의 비율을 낮추면서 탐지율을 향상시킬 수 있는 방법은 무엇이 있는지 서술하시오.
*False Positive(오탐): 잘못 탐지하는 것. 정상을 악성으로 보는 케이스
*False Negative(미탐): 탐지 실패. 악성을 정상으로 보는 케이스
→ 둘다 에러의 표현 방법이다. 둘다 값이 낮게 나올수록 좋은 것!
악성 DLL 파일이 글로벌 후킹을 통해 정상적인 프로세스에 주입된다면?
글로벌 후킹을 통해서 주입되기 때문에 특정 dll 파일이 갑자기 여러 프로세스에 동시에 나타날 수 있다.
이렇게 동시에 여러 프로세스에서 나타난 dll 파일이 있다면 해당 파일을 의심하면 된다.
하나의 프로세스에 주입된다고 하면 정상적인 dll로 볼 수 있겠지만, "동시에 많은 여러 프로세스에" 주입되면 의심해야 한다.
얼마나 많은 프로세스에 한번에 주입되는지를 체크해서 글로벌 후킹을 의심해야 하는 것!
글로벌 후킹인지를 알기 위해서는 dll 파일을 분석해야 한다. 근데 아무 dll이나 분석할 수 없으니까 한번에 여러 군데에서 나타난 의심되는 파일을 찾아서 분석하는 방식을 사용해야 하는 것이다!
'3-2 > 악성코드' 카테고리의 다른 글
| 악성코드 Pre-Lab3. PE 패치를 이용한 DLL 로딩 (0) | 2023.12.16 |
|---|---|
| 악성코드 Pre-Lab2. DLL Injection, DLL Ejection (0) | 2023.10.13 |
| 악성코드 05. Anti-역공학 2 (0) | 2023.09.29 |
| 악성코드 04. Anti-역공학 1 (0) | 2023.09.18 |
| 악성코드 03. 데이터 인코딩 (0) | 2023.09.18 |