2020년 10월 24일 토요일

Detour library를 이용하여 가상함수 후킹하기 (with c)

목차

1. Detour library (MS 제공 후킹 라이브러리) 의 후킹 원리 (방식, 시점 등)

2. 일반 함수 후킹과 가상 함수 후킹의 차이

3. C언어 프로젝트에서 Detour library 를 이용하여 가상 함수 후킹 구현하기

4. 출처

——————————————————————

1. Detour library (MS 제공 후킹 라이브러리) 의 후킹 원리 (방식, 시점 등)

(1) 함수 후킹이란?

MS사의 Windows 운영체제에서 동작하는 모든 실행 프로그램은 MS 에서 제공되는 API 를 통해 구현됩니다 실행 프로그램 개발자가 프로그램을 개발할 때 직/간접적으로 호출하는 모든 API 는 최종적으로 MS 가 제공하는 Win32 API 호출을 통해 동작합니다 Windows 운영 체제에서 동작하는 악성 프로그램도 예외없이 Win32 API 를 호출하게 됩니다

따라서, 많은 보안 프로그램에서는 악성 프로그램의 동작을 감시하기 위한 방법으로 함수 후킹을 사용합니다 예를 들어 악성 프로그램이 악의적인 목적으로 악성 서버에 접속하는 동작을 할 때 네트워크 접속에 관련된 API 를 호출하게 되는데 해당 API 가 호출되는 "시점"<when>에 미리 설치해 둔 "후킹 핸들러"<where>에서 함수 호출 시 전달된 "인자나 호출자에 대한 정보(리턴 어드레스, 호출 스택 등)"<how>를 악성 여부를 판단하는데 활용하게 됩니다

(2) Detour library 소개

실제로 함수 후킹을 구현하는 방법은 5-6 가지 정도 되지만 (다양한 후킹 방법에 대한 정보는 다음에 마음이 내키고 기회가 된다면 포스팅 할 예정) MS 사에서 제공되는 후킹용 라이브러리를 통하면 함수 후킹을 구현할 수 있다

현재, Detour 라이브러리는 4.0 버전까지 나왔으며 모두 오픈소스로 라이센스는 필요 없다 (https://www.microsoft.com/en-us/research/project/detours)

(3) Detour library 후킹 원리 (방식, 시점)

Detour 라이브러리는 원본 함수의 도입부에  "jmp 후킹핸들러의 시작 주소"를 덮어씀으로써 후킹핸들러를 설치한다

원본함수가 호출되면 함수 호출 초반에 수행되는 어셈블리에 따라 후킹핸들러 쪽으로 콜 흐름이 변경된다 후킹핸들러에서 악성코드의 감시 동작을 수행한 뒤에 악성 코드가 아니라고 판단될 경우 원본 함수를 호출해 주어야 하는데 이를 위해 Detour 라이브러리는 "트램펄린" 함수를 이용한다 트램펄린 함수는 원본 함수가 후킹된 상태로 변형되었기 때문에 다시 후킹되지 않고 원본 함수를 호출해주기 위해 Detour 라이브러리가 재구성해주는 함수다

아래 그림을 보면 이해가 쉽다

각각, 타겟 함수는 원본 함수를, Detour 함수는 후킹 핸들러를, 트램펄린 함수는 후킹 핸들러에서 원본 함수의 호출을 위해 호출하는 함수를 의미한다

Detour 라이브러리에서는 그림에서처럼 타겟 함수의 도입부에 jmp DetourFunction (총 5byte) 를 덮어쓴다 그럼 타겟 함수의 도입부 어셈블리 코드는 jmp DetourFunction 명령어로 덮어씌워지고 타겟 함수 시작주소 + 5바이트 위치의 명령어부터는 원본과 동일하다 즉, Detour 라이브러리는 원본 함수가 위치한 DLL 내용 자체를 변경함으로써 후킹 핸들러를 설치한다

다음으로, 후킹 핸들러에서 함수 호출을 감시하는 일련의 동작을 한 후엔 원본 함수를 호출해야하는데 이미 원본 함수는 후킹을 위해 도입부에 후킹 핸들러로 이동하는 명령어가 씌어지는 등 변형된 상태이다 따라서 원본 호출을 위해 Detour 라이브러리는 원본 함수를 재구성하여 트램펄린 함수를 구현한다 트램펄린 함수의 모습은 그림 오른쪽 아래와 같다 원본 함수를 호출한 호출자가 함수 호출 시 넘겨준 인자값과 리턴 어드레스 등과 같은 정보가 현재 레지스터에 저장되어 있으므로 원본 함수에 그대로 넘겨주기 위해 기본적인 함수 도입부의 기계어 코드 구성을 구현한다 그리고 제일중요한 원본 함수의 호출은 원래 원본 함수 주소 + 5바이트 위치로 jmp 함으로써 구현한다 단순히 원본 함수의 주소로 이동하게 되면 원본 함수 도입부에 후킹 핸들러로 이동하는 명령어가 실행되어 또다시 후킹되므로 이를 막는 것이다

이로써 특정 함수의 호출 흐름은 아래와 같이 변경된다

a. 호출자가 후킹 대상이 되는 특정 함수를 호출한다 원본 함수의 도입부의 jmp DetoruFunction 명령으로 인해 후킹 핸들러로 콜 흐름이 변경된다

b. 후킹 핸들러에서 함수 인자, 호출자 정보 등에 대해 일련의 감시 동작을 수행한 뒤에 악성 여부 판단에 따라 원본을 호출하지 않을수도 있지만 대부분의 경우 악성이 없다고 판단되어 원본 함수를 호출해야 한다 이때, 단순히 원본 함수의 주소로 이동하면 1의 흐름이 다시 반복되므로 jmp DetourFunction 명령을 덮어쓰기 전에 원본 함수 도입부에 위치한 일반적인 함수의 도입부 기계어 코드(prologue)를 구성한다 또 현재 원본 함수의 도입부는 후킹을 위해 시작 5 바이트가 변형된 상태이므로 원본 함수 시작주소 + 5 바이트의 위치로 jmp(이동)하는 코드까지 구성하여 트램펄린 함수를 구현한다

c. 트램펄린 함수내 원본 함수 호출을 통해 원본 함수가 호출되고 함수 수행을 마치면 후킹 핸들러로 리턴값이 반환된다

d. 최종적으로 호출자 쪽으로 원본 함수 리턴값이 반환되고 함수 호출 흐름이 종료된다

2. 일반 함수 후킹과 가상 함수 후킹의 차이
(1) 여러가지 함수 호출 규약과 각각의 특징 - 함수 프롤로그와 에필로그, 스택 프레임, 스택 정리 책임, 인수 전달 방법 등 —> soen.kr 참고
(2) 가상 함수의 호출 규약
거의 대부분의 Win32 API는 __stdcall 호출 규약을 따른다 (__stdcall 호출 규약의 특징 : 마지막 인자부터 전달, 스택을 정리하는 주체는 함수) 클래스의 멤버함수는 __stdcall 이 아닌 __thiscall 호출 규약을 따른다 이 호출 규약은 키워드로 존재하지 않아 사용자가 지정해줄 수 없고 컴파일러가 클래스의 맴버함수이면 자동으로 __thiscall 호출 규약을 적용해준다 __thiscall 의 __stdcall 과의 가장 큰 차이점은 객체의 포인터가 ecx 레지스터로 전달된다는 것이다 해당 함수가 호출되었을 때, 가장 마지막 인자부터 스택에 전달되는 것은 동일하지만 맨 마지막 순서로 (그러니깐 첫번째 인자로) 객체의 포인터 (this)가 ecx 레지스터로 전달되는 차이가 있다
(3) c 언어로 가상 함수(cpp 이상 개념) 후킹 하기 위해 추가해야 할 인터페이스
가상 함수는 클래스의 멤버 함수의 한 종류로 __thiscall 호출 규약을 따른다는 점을 염두에 두고, 일단 후킹하고자 하는 클래스 라이브러리를 프로젝트에 추가한다 그런데 라이브러리에서 제공되는 헤더를 그대로 사용하는 것만으로는 후킹을 위한 작업으로 부족한 부분이 있다 가상 함수도 클래스의 멤버 함수인 만큼 __thiscall 호출 규약을 따르므로 this 라는 개념이 존재하는 c++에서는 문제가 없지만 this 개념이 없는 c 컴파일러에게는 이 개념을 납득시키기 위한 노력이 필요하다 앞서, this 의 전달이 함수 인자 전달 후 맨 마지막에 이뤄진다고 했으므로 this 를 첫번째 인자로 재정의 한 함수 선언이 필요하다 또 c에는 c++의 클래스 개념이 없으므로 이 대신 구조체 정의를 통해 클래스의 멤버 함수들을 구조체 멤버로 포팅하는 작업이 필요하다 (ms 에서 기본적으로 제공되는 라이브러리 헤더에 cplusplus 스타일과 c 스타일 인터페이스 정의가 제공될 수 있지만 없는 경우라도 이런 형식으로 c 스타일 인터페이스를 추가해주면 된다) 예를 들면, usgfw2_h.h 와 같은 라이브러리 헤더에도 BEGIN_INTERFACE ~ END_INTERFACE 의 매크로 사이에서 처럼 클래스의 멤버 함수인 가상 함수에 대해 c 스타일 인터페이스를 재정의하여 제공해주고 있다

https://titanwolf.org/Network/Articles/Article?AID=3721267f-38a0-4367-af34-ea11e236d6a8#gsc.tab=0

https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/huntusenixnt99.pdf


댓글 없음:

댓글 쓰기