정현진Jeong Hyeonjin

← 기록 목록

리버싱

메시지 훅과 DLL 인젝션: SetWindowsHookEx와 CreateRemoteThread는 무엇이 다른가

키보드 메시지를 응용 프로그램보다 먼저 보는 방법과, 다른 프로세스에 DLL을 강제로 넣는 세 가지 방법을 정리했습니다.

발행
2025. 12. 29.
분량
2분
조회
1회

Windows에서 다른 프로그램의 입력을 엿보거나, 다른 프로세스 안에서 내 코드를 실행하려면 어떻게 해야 하는지 정리했습니다.
"리버싱 핵심원리" 21장(메시지 후킹)과 23장(DLL 인젝션)을 공부하면서 쓴 내용입니다.

훅이란

  • 훅을 건다: 오가는 정보를 중간에서 엿보거나 가로채기 위한 준비
  • 후킹한다: 실제로 그 정보를 엿보고 조작하는 행위

메시지가 응용 프로그램에 도착하는 과정

Windows의 GUI는 이벤트 방식으로 동작합니다. 키보드·마우스 입력, 창 이동이나 크기 변경 같은 일이 생기면 OS가 미리 정해진 메시지를 해당 프로그램에 보내고, 프로그램은 그 메시지를 보고 필요한 일을 합니다.

키보드를 누르면 이렇게 흘러갑니다.

  1. WM_KEYDOWN 메시지가 OS 메시지 큐에 들어갑니다.
  2. OS가 어느 프로그램에서 일어난 이벤트인지 판단해, 그 프로그램의 응용 프로그램 메시지 큐로 옮깁니다.
  3. 프로그램은 자기 큐를 보고 있다가 메시지를 발견하면 이벤트 핸들러를 부릅니다.

메시지 훅이 설치돼 있으면, OS 큐와 응용 프로그램 큐 사이의 훅 체인에 있는 훅들이 프로그램보다 먼저 메시지를 봅니다. 훅 함수 안에서는 메시지를 엿보는 것뿐 아니라 바꾸거나 가로채서 막는 것도 가능합니다.

SetWindowsHookEx()

메시지 훅은 SetWindowsHookEx()로 설치합니다. 인자는 네 개입니다.

인자 의미
1 훅 종류 (예: 키보드)
2 훅 프로시저 — OS가 대신 불러주는 콜백 함수
3 그 훅 프로시저가 들어 있는 DLL의 핸들
4 훅을 걸 스레드의 ID

훅을 설치하면, 어떤 프로세스에서 해당 이벤트가 생겼을 때 OS가 그 DLL을 그 프로세스에 강제로 넣고 훅 프로시저를 호출합니다. 즉 메시지 훅은 그 자체로 DLL 인젝션의 한 형태입니다.

DLL 인젝션

DLL 인젝션은 실행 중인 다른 프로세스에 특정 DLL을 강제로 넣는 것입니다. 핵심은 다른 프로세스가 LoadLibrary()를 스스로 호출하게 만드는 것입니다.

일반적인 DLL 로딩과의 차이는 하나입니다. 로딩하는 대상이 자기 자신이냐, 다른 프로세스냐.

DLL이 로딩되면 그 DLL의 DllMain()이 실행되고, 들어간 DLL은 그 프로세스의 메모리에 접근할 수 있습니다. 그래서 할 수 있는 일이 많습니다.

넣는 방법 세 가지

방법 쓰는 것 누가 넣나
원격 스레드 생성 CreateRemoteThread() 내가 직접
레지스트리 AppInit_DLLs 값 시스템이 로딩 시
메시지 후킹 SetWindowsHookEx() OS가 이벤트 발생 시

CreateRemoteThread()로 넣는 순서

  1. PID로 대상 프로세스의 핸들을 얻습니다 (OpenProcess).
  2. 대상 프로세스 메모리에 DLL 경로를 담을 공간을 할당합니다.
  3. 그 공간에 DLL 경로를 씁니다.
  4. kernel32.dll에 있는 LoadLibrary의 주소를 구합니다.
  5. CreateRemoteThread로 대상 프로세스 안에서 LoadLibrary(DLL 경로)를 실행하는 스레드를 만듭니다.

왜 하필 LoadLibrary를 원격으로 실행할까요? DllMain은 OS가 부르는데, 그걸 부르게 만드는 표준 진입점이 LoadLibrary이기 때문입니다. 그래서 메모장(대상 프로세스)에서 LoadLibrary의 위치를 찾아 원격으로 실행시켜야 합니다.

직접 코드를 짜면서 정리한 용어

책을 바탕으로 직접 DLL과 인젝터 코드를 짜면서 처음 본 것들입니다.

  • main / wmain / _tmain: _tmain은 유니코드가 정의되지 않으면 main, 정의되면 wmain이 됩니다.
  • HMODULE: 프로세스 주소 공간에 올라간 모듈(실행 코드 파일 단위)의 베이스 주소를 가리키는 핸들
  • HANDLE hProcess: 특정 프로세스를 조작하기 위한 핸들. OpenProcess(권한, FALSE, pid)로 얻습니다.
  • LPVOID: 어떤 타입이든 가리킬 수 있는 포인터
  • LPTHREAD_START_ROUTINE: 스레드 함수 포인터 타입
  • WINAPI: 함수 호출 규약을 나타내는 매크로

어디에 쓰이나: 공격자 관점 포함

용도 내용
기능 개선·버그 패치 소스가 없는 프로그램에 기능(플러그인)을 넣거나 문제 코드를 고침
API 후킹 후킹 함수를 DLL로 만들어 대상 프로세스에 넣기만 하면 됨
감시·관리 프로그램 PC 사용을 감시·관리하는 프로그램에서 사용
우회 게임·주식 거래 등 실행을 막아 둔 환경에서 정상 프로세스 안에 숨어 실행
악성코드 정상 프로세스에 숨어 백도어 포트를 열거나, 키로깅으로 개인정보를 훔침

공격자가 기대는 가정은 **"정상 프로세스 안에서 도는 코드는 정상으로 보인다"**는 점입니다. 프로세스 목록만 보는 방식으로는 인젝션된 DLL이 드러나지 않습니다.

정리

  • 메시지 훅은 OS 큐와 응용 프로그램 큐 사이에서 메시지를 먼저 보고, 바꾸거나 막을 수 있습니다.
  • DLL 인젝션은 대상 프로세스가 LoadLibrary를 스스로 부르게 만드는 것이고, 메시지 훅도 그 한 형태입니다.
  • 참고: "리버싱 핵심원리" 21장, 23장

단어 582글자 1,906연결 0