출처: http://vbdream.tistory.com/entry/Hooking-Windows%EC%97%90%EC%84%9C-API%EB%A5%BC-%ED%9B%84%ED%82%B9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 [Hooking] Windows에서 API를 후킹하는 방법

  일단, 일반적인 Windows의 API는 대개 User-Mode 부분과 Kernel-Mode 부분이 존재하고, User-Mode 부분을 호출하면 결과적으로 Kernel-Mode 부분을 호출한다. Microsoft에서는 API Hooking 테크닉을 공식적으로 인정하고 있지 않지만, 실제 많은 보안 제품과 악성코드 프로그램들이 사용하고 있는 방법이다.

  Windows에서 특정 API가 호출되는 때를 잡으려면 보통 '후킹'이라는 방법을 사용해야한다. 그런데, 이 후킹에도 여러가지 종류가 있다. IAT Hook, EAT Hook, Detour Hook, Byte Patching, 등등...

  이 포스트는 그러한 후킹 기법들의 종류를 정리해보는 차원에서 작성한 것이다.

  ※ 혹시 새로운 후킹 기법을 아시거나 틀린점이 있다면 지적해주세요.

1) 유저 모드 후킹
  1. IAT(Import Address Table) Hooking
    일반적인 C/C++ 프로그램에서 API를 호출할 때 IAT(Import Address Table)을 사용한다. 이 IAT의 필드 값을 새로운 함수의 주소로 대체함으로써 후킹이 가능하다.

  2. EAT(Export Address Table) Hooking
    Windows API 중에서 GetProcAddress() 라는 API가 있다. 이 API는 특정 모듈의 함수 주소를 반환하는 API이다. IAT 다음으로 많이 쓰이는 호출 방법이 GetProcAddress()를 사용해 함수 포인터를 취득한 후, 호출하는 방법이다. 그러나 이 함수는 EAT(Export Address Table)을 사용하므로, 이를 조작하면 함수의 결과값도 조작할 수 있다. ( 물론 GetProcAddress() API를 IAT Hooking 해도 같은 효과를 구현할 수 있다. )

  3. Detour-Style Hooking
    후킹 대상의 함수의 첫 부분에 원하는 함수로 이동하는 Jump 명령을 삽입한 후, 손상된 부분은 트렘펄린(Trampoline)이라 불리는 영역에 보관한다. 이 트렘펄린은 후킹 함수 내에서 원래 함수를 호출하여 정상적으로 처리될 수 있도록 호출된다.

  4. Debugging
    디버거가 연결해도 후킹과 비슷한 일을 할 수 있다. 예를 들어 해당 API의 코드 부 첫부분에 INT3 Breakpoint를 걸어 중단점을 걸거나 (혹은 하드웨어 브렉포인트(DrX register)를 써도 된다.) 예외를 발생시킬만한 코드를 삽입시킨다.(Unknown opcode 같은 예외)

  5. Native API Hooking
    멋대로 지은 이름이지만, Native API(Zw*, Nt*)를 후킹할 때 주로 사용되는 방법 중 하나이다. Native API를 호출하는 Zw* 함수들은 MOV EAX, XXXXXXXX(SSDT Idx) 형태로 시작하는데 이 SSDT Idx에 새로 만든 SSDT Entry를 추가하고 그 아이디를 넣어서 후킹한다.

  6. Windows Hooks
    이 방법은 위 1~5의 방법과 달리 윈도우에서 제공하는 후킹 방법으로, SetWindowsHookEx()를 사용한다. API를 후킹하기엔 조금 부적절한 함수이긴 하지만, 여러 후킹 방법에서 자주 쓰인다.

2) 커널 모드 후킹
  1. SSDT(System Service Descriptor Table) Hooking
    Windows NT 계열에서는 Native API 주소들을 보관하고 있는 테이블(SSDT)을 가지고 있다. 이 테이블 내의 함수 주소를 바꾸거나, 혹은 테이블 자체를 프로그램 내부 메모리로 redirect 함으로써 후킹이 가능하다.

  2. IAT/EAT Hooking
    유저모드와 비슷한 방법으로 구현이 가능하다. EAT Hooking은 MmGetSystemRoutineAddress()등의 결과값을 조작하기 위해 이용할 수 있다.

  3. Debug Register Hook
    디버그 레지스터를 이용해 후킹할 수 있다. 물론 그 전에 INT1 interrupt를 가로채야한다.

  4. IDT (Interrupt Descriptor Table) Hooking
    SIDT 명령어를 사용하면 IDT table주소를 구할 수 있고, 이 IDT 테이블 내의 인터럽트 처리 주소를 바꿈으로써 특정 인터럽트를 후킹할 수 있다. 주로 INT1이나 INT3을 후킹하기 위해 사용된다.

  5. IRP Hooking
    특정 드라이버의 IRP를 후킹할 수 있다. (MajorFunction[] 테이블 주소를 바꿔서)

  6. Detour Hooking
    유저모드와 동일하다.

  7. SYSENTER 주소 변경
    IA32_SYSENTER_EIP MSR 값을 바꿔서 후킹이 가능하다. 주로 wxp 이상에서 Native API를 후킹할 때 사용한다.

  8. SIngle Byte Patching
    INT (0xCD) 명령을 이용한 후킹으로, 예를 들어 binary가 E9 37 ... 같이 시작하면 E9를 CD로 대체하여 INT 0x37이란 명령으로 바꾼 후, INT 0x37 IDT entry를 후킹하는 방법이다.

AND