anothel의 지식 창고

후킹 입문: 개념과 기본 원리 본문

기술 노트/Hooking

후킹 입문: 개념과 기본 원리

anothel 2022. 1. 29. 01:47

1. 개요

후킹(hooking)은 소프트웨어 개발 및 보안 분야에서 중요한 기술로, 특정 기능의 동작을 가로채거나 수정하는 방법이다. 이는 일반적으로 API 호출이나 함수 호출을 수정하여 프로그램의 동작을 변경하는 데 사용되며, 다양한 용도로 활용된다. 후킹은 보안 솔루션, 디버깅 도구 등에서 필수적인 기술로 자리 잡고 있다.

2. 후킹의 정의

후킹이란 특정 함수나 이벤트의 동작을 가로채고 그 동작을 수정하거나 다른 기능을 실행하도록 만드는 기술이다. 프로그램의 실행 흐름을 변경하는 방식으로, 후킹을 통해 개발자는 특정 기능을 확장하거나 새로운 기능을 추가할 수 있다.

3. 후킹의 원리

후킹은 프로그램의 실행 중 특정 지점을 가로채어 원하는 동작을 수행하도록 하는 기술이다. 보통 운영체제의 API, 메시지, 특정 함수 호출 등을 가로채어 동작을 제어하거나 변조한다. 후킹은 주로 보안, 디버깅, 시스템 모니터링을 위해 활용된다.

4. 후킹의 종류

후킹 기술은 여러 종류로 나뉘며, 각기 다른 방식으로 활용된다.

  • API 후킹
    • 운영체제의 API를 가로채어 애플리케이션의 기본 동작을 수정하는 기술이다. 보안 솔루션에서 자주 사용되며, 특히 Windows 환경에서는 Win32 API의 특정 함수를 가로채어 커스터마이징하는 데 사용된다. 주로 User 모드에서 이루어지며, 프로그램의 동작을 모니터링하고 제어하는 데 유용하다.
  • 메시지 후킹
    • GUI 애플리케이션의 이벤트 처리를 변경하기 위해 윈도우 시스템에서 메시지를 가로채는 방식이다. 이는 특정 이벤트를 감지하거나 제어하는 데 사용되며, GUI 애플리케이션에서 많이 활용된다.
  • 함수 후킹
    • 특정 함수 호출을 가로채어 다른 코드로 대체하는 방법이다. 이 방식은 코드 분석, 보안 및 디버깅 목적으로 사용되며, 실행 중인 코드의 동작을 자유롭게 변경할 수 있다.
  • 커널 후킹
    • 커널 후킹은 운영체제의 커널 레벨에서 이루어지는 후킹 방식이다. 커널 모드에서 동작하기 때문에 시스템의 깊숙한 부분에 직접 접근할 수 있으며, 보안 솔루션이나 고급 시스템 모니터링 도구에서 주로 사용된다. 이 방식은 시스템을 전반적으로 제어할 수 있는 강력한 방법이지만, 높은 권한이 필요하고 잘못 사용하면 시스템 안정성에 심각한 영향을 줄 수 있다는 단점이 있다.
  • 라이브러리 후킹 (DLL 인젝션)
    • 라이브러리 후킹은 특정 애플리케이션에 라이브러리를 강제로 로드하고 그 안에 포함된 함수를 호출하도록 하는 방식이다. 일반적으로 DLL 인젝션 기법과 함께 사용되며, 이를 통해 프로세스 내부에 원하는 코드를 주입해 프로그램의 동작을 변경할 수 있다. 이를 통해 외부 코드를 삽입해 기존 기능을 확장하거나 수정할 수 있다.

이 외에도 각 플랫폼과 운영체제에 맞는 다양한 후킹 방식들이 존재한다.

5. 후킹의 과정

후킹은 프로그램의 내부 구조와 동작 원리를 이해하고, 특정 기능을 추가하거나 수정하는 데 활용되는 기술이다. 후킹을 진행하는 일반적인 과정은 다음과 같다.

  • 디스어셈블러와 디버거 활용
    • 프로그램을 분석하기 위해 디스어셈블러와 디버거를 사용한다. 디스어셈블러는 프로그램의 실행 파일을 어셈블리 코드 형태로 변환해 내부 구조를 분석하는 도구이며, 디버거는 실행 중인 프로그램을 중지하거나 단계별로 진행하면서 변수나 메모리 값을 확인하는 데 유용하다. 이를 통해 프로그램이 어떤 방식으로 작동하는지, 어떤 부분을 후킹해야 할지를 파악할 수 있다.
  • 후크 코드 개발
    • 필요한 정보를 바탕으로, 특정 기능을 수정하거나 추가할 훅(Hook) 코드를 작성한다. 훅 코드는 프로그램의 동작을 변경하거나 확장하기 위한 명령어 집합으로, 원래의 함수 호출을 가로채어 원하는 기능을 수행하도록 한다. 이 과정에서 기능 개선이나 버그 수정, 데이터 수집 등의 목적에 맞게 코드를 설계한다.
  • 프로세스 메모리 조작을 통한 훅 코드 설치
    • 작성한 훅 코드를 실행 파일의 메모리 공간에 설치한다. 이를 위해 실행 파일과 프로세스 메모리를 자유롭게 조작할 수 있어야 하며, 주로 프로세스의 특정 위치에 있는 함수 주소를 변경하거나 원하는 위치에 새로운 코드를 삽입해 실행 흐름을 변경한다.

6. 후킹의 용도

후킹 기술은 다양한 분야에서 활용된다. 주요 용도는 다음과 같다.

  • 디버깅
    • 애플리케이션의 동작을 분석하고 문제를 해결하기 위해 후킹이 사용된다. 개발자는 특정 함수를 후킹하여 상태를 추적하고 문제를 해결할 수 있다.
  • 보안
    • 악성코드 탐지 및 방지 솔루션에서 후킹 기술을 활용하여 악성 행위를 감지한다. 이를 통해 시스템의 안전성을 높인다.
  • 기능 확장
    • 기존 소프트웨어의 기능을 추가하거나 수정하는 데 후킹이 사용된다. 예를 들어, 새로운 기능을 추가하거나 기존 기능을 개선하는 경우가 있다.

7. 후킹의 장단점

후킹 기술은 많은 장점을 가지고 있지만, 그에 따른 단점도 존재한다.

  • 장점
    • 후킹은 유연성과 확장성을 제공하여 기존 소프트웨어의 기능을 개선할 수 있다. 이를 통해 사용자는 더 나은 경험을 할 수 있다.
  • 단점
    • 잘못 사용될 경우 보안 취약점을 유발할 수 있으며, 애플리케이션의 안정성을 저해할 수 있다. 따라서 신중하게 사용해야 한다.

8. 후킹 구현 방법

후킹을 구현하는 방법은 다양하며, 사용되는 프로그래밍 언어나 플랫폼에 따라 다를 수 있다. 일반적으로 C/C++ 언어를 사용하여 윈도우 API를 후킹하는 방법이 많이 사용된다. 후킹 구현 시에는 각 후킹 기법에 따라 적절한 API나 라이브러리를 선택해야 한다.

9. 후킹 방지 방법

9.1. 래퍼 라이브러리 활용

  • 함수 호출 제어
    • 래퍼 라이브러리를 사용하면, 원본 라이브러리의 함수 호출을 직접 제어할 수 있다. 즉, 응용 프로그램이 원본 라이브러리의 함수를 호출할 때, 이 호출이 래퍼 라이브러리를 통해 이루어지므로, 래퍼 라이브러리에서 특정 기능이나 호출을 차단하거나 변경할 수 있다. 이를 통해 악성 후킹 시도를 예방할 수 있다.
  • 기능 검증
    • 래퍼 라이브러리 내에서 원본 라이브러리의 함수가 호출되기 전에 검증 로직을 추가할 수 있다. 호출된 함수가 안전한지 확인하고, 허용된 호출만 수행하도록 제한할 수 있다. 이를 통해 악의적인 후킹이 수행되기 전에 차단할 수 있다.
  • 안전한 대체 기능 제공
    • 래퍼 라이브러리는 원본 라이브러리의 기능을 대체하거나 새로운 로직을 추가하여 후킹된 원본 함수 대신 안전한 대체 기능을 제공할 수 있다. 이렇게 하면 후킹이 발생하더라도, 실제로 호출되는 기능은 원본의 비정상적인 동작이 아니라 안전하게 설계된 로직으로 대체된다.
  • 추적 및 로깅
    • 래퍼 라이브러리에서 모든 함수 호출을 로깅하거나 추적하는 기능을 추가하면, 후킹 시도를 감지하고 이를 분석할 수 있는 기반이 된다. 이를 통해 악성 후킹이 발생했을 경우 신속하게 대응할 수 있다.

9.2. 파일 입출력 기능의 래퍼 라이브러리 예시

1. 원본 라이브러리 함수

먼저, 원본 라이브러리의 ReadFile 및 WriteFile 함수가 어떻게 정의되는지를 살펴보자. 이 함수들은 파일을 읽고 쓰는 데 사용된다.

#include <windows.h>

BOOL OriginalReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
    // 원본 ReadFile 함수 구현
    // 파일에서 데이터를 읽는 작업 수행
}

BOOL OriginalWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
    // 원본 WriteFile 함수 구현
    // 파일에 데이터를 쓰는 작업 수행
}

2. 래퍼 라이브러리 구현

이제 래퍼 라이브러리를 구현하여 원본 함수의 호출을 감싸고, 추가적인 검증을 수행하겠다.

#include <windows.h>
#include <stdio.h>

BOOL WrapperReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
    // 파일 접근을 검증하는 로직
    if (hFile == NULL || lpBuffer == NULL) {
        printf("유효하지 않은 파일 핸들 또는 버퍼\n");
        return FALSE; // 유효하지 않은 경우 호출을 차단
    }

    // 로그 기록
    printf("ReadFile 호출됨: 핸들 = %p, 바이트 수 = %lu\n", hFile, nNumberOfBytesToRead);

    // 원본 ReadFile 함수 호출
    return OriginalReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}

BOOL WrapperWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
    // 파일 접근을 검증하는 로직
    if (hFile == NULL || lpBuffer == NULL) {
        printf("유효하지 않은 파일 핸들 또는 버퍼\n");
        return FALSE; // 유효하지 않은 경우 호출을 차단
    }

    // 로그 기록
    printf("WriteFile 호출됨: 핸들 = %p, 바이트 수 = %lu\n", hFile, nNumberOfBytesToWrite);

    // 원본 WriteFile 함수 호출
    return OriginalWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
}

3. 사용 예시

응용 프로그램에서 래퍼 라이브러리를 사용하여 파일 작업을 수행할 때는 다음과 같은 방식으로 진행한다.

int main() {
    HANDLE hFile = CreateFile("example.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("파일 열기 실패\n");
        return 1;
    }

    // 래퍼 함수를 사용하여 파일에 쓰기
    DWORD bytesWritten;
    char data[] = "Hello, World!";
    WrapperWriteFile(hFile, data, sizeof(data), &bytesWritten, NULL);

    // 래퍼 함수를 사용하여 파일에서 읽기
    char buffer[100];
    DWORD bytesRead;
    WrapperReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL);

    CloseHandle(hFile);
    return 0;
}

위의 예시에서 래퍼 라이브러리는 원본 라이브러리의 ReadFile 및 WriteFile 함수 호출을 감싸고, 접근을 검증하는 로직을 추가하여 후킹으로부터 보호하는 역할을 한다. 이를 통해 악의적인 후킹 시도를 예방하고, 모든 호출을 기록하여 어떤 함수가 언제 호출되었는지를 추적할 수 있다. 이러한 방식으로 래퍼 라이브러리를 활용하면 소프트웨어의 안전성을 높이는 데 기여할 수 있다.

10. 결론

후킹은 소프트웨어 개발 및 보안에서 매우 유용한 기술이다. 올바르게 활용하면 프로그램의 기능을 확장하고 개선할 수 있지만, 잘못 사용될 경우 보안 취약점을 초래할 수 있다. 따라서 후킹 기술을 사용할 때는 그 사용 목적과 방법을 충분히 이해하고 적용해야 한다.

 

 

728x90