반응형
API Code Patch 를 통한 API Hooking 방법에 대해서 공부합니다.

또한 모든 프로세스를 후킹 하는 global hooking 방법에 대해서 살펴봅니다.

위 기법을 사용하여 특정 프로세스를 감추는 은폐(stealth) 기법에 대해 실습해 보겠습니다.



<photo : Rob Shenk on flickr>


* 은폐(Stealth) 프로세스를 리버싱 전문 용어로 루트킷(Rootkit) 이라고 합니다.
보통 루트킷이라고 하면 커널 모드 후킹을 통한 프로세스, 파일, 레지스트리 등의 은폐 기술을 지칭합니다. 루트킷은 본 포스트의 설명 범위를 벗어나기 때문에 편의상 스텔스 프로세스라고 하겠습니다. (루트킷에 대한 내용은 커널에 대한 방대한 기반 지식을 요구합니다. 향후 제 블로그에서 하나씩 살펴볼 계획입니다.)

* 본문 내용을 편하게 읽기 위해서는 아래의 배경지식이 필요합니다.
☞ DLL Injection (DLL Injection – 다른 프로세스에 침투하기
)
☞ API Hooking (API Hooking – 계산기, 한글을 배우다
)
☞ API Hooking (API Hooking - 리버싱의 '꽃')



Tech Map



<Fig. 1>

API Code Patch
기법을 위 TechMap 에서 빨간색으로 표시하였습니다.

이 기법은 API Hooking 에서 가장 널리 사용됩니다.


그 이유는 대부분의 user mode API 를 자유롭게 후킹 할 수 있기 때문입니다.

* IAT Hooking 기법은 후킹하려는 API 가 프로세스의 IAT 에 존재하지 않을 경우 후킹이 불가능한 반면에 "API Code Patch" 기법은 그러한 제약 조건이 없습니다.

덧붙여 대상 프로세스의 메모리를 자유롭게 사용하기 위해 DLL Injection 기법을 사용하였습니다. (다음 번 주제에서 DLL 파일이 아닌 Code 자체를 Injection 하는 고급 기법에 대해서 살펴볼 예정입니다.)



API Code Patch 동작 원리


API Code Patch 를 통한 API Hooking 기법의 동작 원리에 대해서 알아보겠습니다.

* IAT Hooking 방식과 비교해 살펴보시면 더 쉽게 이해 될 것입니다.
☞ API Hooking (API Hooking – 계산기, 한글을 배우다)


IAT Hooking 방식이 프로세스의 특정 IAT 값을 조작해서 후킹을 하는 방식이라면, Code Patch 방식은 실제 API 코드 시작 5 byte 값을 JMP XXXX 명령어로 변경하는 방식입니다.

후킹된 API 가 호출되면 (패치된) JMP XXXX 명령어가 실행되어 후킹 함수로 제어가 넘어옵니다.

아래 그림은 Process Explorer(procexp.exe) 프로세스에 stealth.dll 파일을 인젝션 시킨 후 ntdll!ZwQuerySystemInformation() API 를 후킹하는 방법을 설명하는 그림입니다.

먼저 후킹 되기 전의 정상적인 프로세스 메모리의 모습입니다.

<Fig. 2> 

(1) procexp.exe 의 00422CF7 주소의 CALL DWORD PTR DS:[48C69C] 명령어는 ntdll.ZwQuerySystemInformation() API 를 호출하고 있습니다. (48C69C 주소는 프로세스의 IAT 영역으로써 7C93D92E 값을 가지며, 이는 ntdll.ZwQuerySystemInformation() API 의 시작 주소입니다.)

(2) 해당 API 는 실행이 완료되면 호출 코드 다음 명령어 주소로 되돌아 갑니다.

이것은 매우 정상적인 상황의 API 호출 흐름입니다.

그럼 이제 API 가 후킹된 프로세스의 그림을 보시겠습니다.
stealth.dll 을 인젝션 하여 ntdll!ZwQuerySystemInformation() API 를 Code Patch 하였습니다.

<Fig. 3>

위 그림이 상당히 복잡하게 보입니다. 하나씩 차근차근 살펴보도록 하겠습니다.

먼저 stealth.dll 이 인젝션 되면서 ntdll!ZwQuerySystemInformation() API 를 후킹 하였습니다.

ntdll!ZwQuerySystemInformation() API 시작 주소(7C93D92E)의 5 byte 코드를 JMP 10001120 으로 덮어 써버린 것이죠. (5 byte 패치) 10001120 주소는 stealth!MyZwQuerySystemInformation() 함수 주소입니다.

이때 procexp.exe 코드에서 ntdll!ZwQuerySystemInformation() API 를 호출하면 코드 흐름은 아래 순서와 같습니다.

(1) 422CF7 주소에서 ntdll!ZwQuerySystemInformation() API 를 호출(7C93D92E)합니다.

(2) 7C93D92E 주소에 있는 패치된 코드 JMP 10001120 에 의해서 10001120 주소(후킹 함수)로 점프합니다. 1000116A 주소의 CALL unhook() 명령어에 의해서 ntdll!ZwQuerySystemInformation() API 시작 5 byte 는 원래대로 복원됩니다.

(3) 1000119B 주소의 CALL EAX(7C93D92E) 명령어에 의해서 원본 함수(ntdll!ZwQuerySystemInformation) 가 호출됩니다. (unhook 상태이기 때문에 정상적으로 실행됩니다.)

(4) ntdll!ZwQuerySystemInformation() 의 실행이 완료되면 7C93D93A 주소의 RETN 10 명령에 의해 stealth.dll 코드 영역(자신을 호출한 위치)으로 리턴됩니다. 그리고 10001212 주소의 CALL hook() 명령어에 의해서 ntdll!ZwQuerySystemInformation() API 를 다시 후킹합니다. (시작 5 byte 를 JMP 10001120 명령어로 패치함)

(5) stealth!MyZwQuerySystemInformation() 의 실행이 완료되면 10001233 주소의 RETN 10 명령에 의해서 procexp.exe 프로세스 코드 위치로 리턴됩니다.

처음에는 좀 어려운 듯 보여도 몇 번만 읽어보시면 금방 이해하실 수 있으실 겁니다.

Code Patch 방법의 장점은 프로세스에서 사용되는 어떤 API 라도 후킹할 수 있다는 것입니다. IAT Hooking 의 경우에는 후킹 가능한 API 가 제한 된다는 사실과 비교해 보세요. (비록 코드는 조금 더 복잡하지만 말이죠.)

Code Patch 방법에 있어서 제한 사항은 후킹하려는 API 코드의 길이가 최소 5 byte 보다 커야 한다는 것입니다만, 모든 API 의 코드 크기는 5 byte 보다 크기 때문에 사실상 제한이 없다고 보시면 됩니다.

* 주의!
코드 패치 방법은 말그대로 프로세스 메모리 공간에 매핑된 DLL 의 코드를 직접 수정하는 것입니다. 만약 프로세스의 다른 스레드에서 어떤 함수를 read 하고 있을때 코드 패치를 시도하면 어떻게 될까요? Access Violation 에러가 발생합니다. 따라서 이점을 유의 하셔야 합니다.

다음에는 스텔스 기법에 대한 원리와 실습 예제 파일을 가지고 직접 실습을 해보도록 하겠습니다.


API Hooking - '스텔스' 프로세스 (2)


ReverseCore

위 글이 도움이 되셨다면 추천(VIEW ON) 부탁 드려요~

반응형
반응형

API Hooking 에서 사용되는 각종 방법들에 대한 Tech Map 을 소개하고 간략한 설명을 하겠습니다.

API Hooking 의 기본 소개는 아래 글을 참고해주세요.

참고: API Hooking - 리버싱의 '꽃'



API Hooking Tech Map


아래 그림이 API Hooking 의 모든 기술적 범주를 포함하는 Tech Map 입니다.


<Fig. 1>

위 Tech Map 을 이용하면 그 동안 막연하게만 보였던 API 후킹이 (기술적으로) 단번에 파악됩니다.

API 후킹 작업을 할 때 상황에 맞게 위의 Tech Map 에서 적절한 기법을 골라서 적용하시면 됩니다. (가장 널리 사용되는 기법은 빨간색으로 표시하였습니다.)


[ Method – Object (what) ]

API 후킹 방식(Method)에 대한 대분류 입니다.

API 후킹 방식(Method)는 작업 대상(Object)에 따라서 크게 static 방식dynamic 방식으로 나눌 수 있습니다.

static 방식은 작업 대상(Object)이 ‘파일’이며, dynamic 방식은 작업 대상이 프로세스 ‘메모리’ 입니다.
일반적으로 API 후킹이라고 하면 dynamic 방식을 말하며, 매우 특수한 상황에서 static 방식을 사용할 때도 있습니다.

각각에 대한 설명은 아래의 표에 정리하였습니다.


<Fig. 2>

* static 방식은 여러 가지 단점 때문에 일반적으로 사용하기에 어려운 부분이 많이 있습니다. 다만 특수한 경우에 사용되기도 하므로 여기서는 소개 정도만 하고 넘어갑니다.


[ Location (where) ]

대상의 어느 부분을 공략(조작)해야 하는지에 대한 내용입니다.

일반적으로 3 군데의 공략 위치가 있습니다.

1) IAT

IAT 에 있는 API 주소를 후킹 함수 주소로 변경하는 방법입니다.

장점은 가장 단순하며, 구현 방법이 가장 쉽습니다.

단점으로는 IAT 에 없는데 프로그램에서 사용되는 API 들에 대해서는 후킹할 수 없습니다. (예: DLL 을 동적으로 로딩해서 사용하는 API)

2) Code

프로세스 메모리에 매핑된 시스템 라이브러리(*.dll)에서 API 의 실제 주소를 찾아가 코드를 직접 수정해버리는 방법입니다.

참고로 이 방법이 가장 널리 사용되는 방법이며, 구현에 있어서 아래와 같은 여러 가지 다양한 옵션이 있습니다.
 
- 처음 5 byte 를 JMP XXXXXXXX 명령어로 패치하는 방법
- 함수 일부를 덮어쓰는 방법
- 필요한 부분만 일부 변경하는 방법

3) EAT

DLL 의 EAT(Export Address Table) 에 기록된 API 의 시작 주소를 후킹 함수 주소로 변경하는 방법입니다.

개념은 간단하지만 코드 구현에 있어서 위 2) 번 방법이 더 간단하고 강력하므로 EAT 수정 방법은 잘 사용되지 않습니다.


[ Technique (How) ]

후킹 대상 프로세스 메모리에 침투하여 후킹 함수를 설치하는 구체적 기법(Technique)에 대한 내용입니다.

크게 Debug 와 Injection 기법으로 나눌 수 있으며, Injection 기법은 다시 Code 와 Dll 기법으로 나뉘어 집니다.

A) Debug

대상 프로세스를 디버깅하면서 API 후킹을 하는 방법입니다.

아마 이 말이 무슨 의미인지 이해가 잘 안 되는 분들이 계실 것입니다.
“그게 디버깅이지 무슨 API 후킹이야?” 하고 말이죠.

디버거(Debugger)는 디버깅 당하는 프로세스(Debuggee)에 대한 모든 권한(실행 제어, 메모리 액세스, 기타)을 가지기 때문에, Debuggee 의 프로세스 메모리에 후킹 함수를 자유롭게 설치 할 수 있습니다.

여기서 얘기하는 Debugger 는 일반적인 OllyDbg, Windbg, IDAPro 등이 아니라, 후킹을 위하여 사용자가 직접 제작한 프로그램입니다.
즉, 프로그램 내에서 Debug API 를 이용하여 대상 프로세스에 Attach 하고 (실행이 잠깐 멈춰진 상태에서) 후킹 함수를 설치합니다. 그 후 실행을 재개시키면 완벽한 API Hooking 이 이뤄지는 것입니다. (XP 이상의 시스템에서는 Debuggee 의 종료 없이 Debugger 를 Detach 시킬 수 도 있습니다.)

물론 기존 디버거(OllyDbg, Windbg, IDAPro)에 자동화 스크립트를 사용하여 API 후킹을 자동화 시키는 방법도 있습니다. (특히 Immunity Debugger 같은 경우 강력한 전용 Python 스크립트를 지원하고 있습니다.)

이 방식의 장점은 구현만 완벽하다면 (하나의 프로세스에 대한) 가장 강력한 후킹 방법입니다. API 후킹 뿐만 아니라 필요에 따라서 실행 흐름 까지도 완벽히 제어할 수 있습니다.

따라서 API 후킹 도중이라도 사용자가 Interactive 하게 프로그램의 실행을 멈추고 API 후킹을 추가/수정/제거 등의 작업을 할 수 있습니다. (다른 방식과 가장 큰 차이점입니다.)

단점은 Debugger 에 대한 지식(혹은 자동화 스크립트에 대한 지식)이 필요합니다. 또한 안정적인 동작을 위해서는 많은 테스트가 요구됩니다. 이와 같은 단점들 때문에 (강력함에도 불구하고) 범용적으로는 사용하기는 쉽지 않습니다.

B) Injection

Injection 기법은 해당 프로세스 메모리 영역에 침투하는 기술로써 Injection 대상에 따라 B-1) Code InjectionB-2) DLL Injection 으로 나눌 수 있습니다. 그 중에서 DLL Injection 기법이 가장 널리 사용됩니다.

DLL Injection 기법은 대상 프로세스로 하여금 강제로 사용자가 원하는 DLL file 을 로딩하게 만드는 기술입니다. (DLL Injection 에 대한 자세한 설명은 예전의 제 글을 참고하세요. DLL Injection - 다른 프로세스에 침투하기 (1))

Injection 할 DLL 에 미리 후킹 코드와 설치 코드를 만들고 DllMain() 에서 설치 코드를 호출해 주면 Injection 되는 순간에 API 후킹이 완료됩니다.

Code Injection 기법은 기존 DLL Injection 보다 좀 더 발전된 (복잡한) 기술이며, 주로 악성코드(바이러스, 쉘코드, 기타)에서 많이 사용됩니다. (DLL Injection 은 AV 제품에서 탐지가 잘 되므로, 악성 코드들은 좀 더 탐지하기 어려운 Code Injection 을 많이 시도하고 있습니다.)

Code Injection 기법의 구현방법은 상당히 까다로운 편입니다. 그 이유는 DLL Injection 처럼 완전한 형태의 PE 이미지가 아니라 실행 코드와 데이터만 Injection 된 상태에서 자신이 필요한 API 주소를 직접 구해서 사용해야 하며, 코드 내의 메모리 주소에 접근할 때 잘못된 주소를 액세스 하지 않도록 매우 주의해야 하기 때문입니다.

말로만 설명하면 어렵습니다. 나중에 코드를 보며 직접 실습을 해보도록 하겠습니다.
(직접 해보시면 왜 어렵다고 말씀 드렸는지 느낌이 팍 오실 것입니다.)

[ API ]

Tech Map 에 소개된 방법들을 실제로 구현하기 위해서 사용되는 API 들을 소개합니다.

한번씩 읽어 보시고 향후 실습할 때 사용법에 대해서 자세히 살펴보도록 하겠습니다.

참고로 위에 소개된 API 말고도 OpenProcess(), WriteProcessMemory(), ReadProcessMemory() API 들은 다른 프로세스 메모리에 접근하려고 할 때 항상 사용되는 API 들입니다.


+---+

설명이 많이 길었습니다.
다소 지루하시더라도 세부 기술 설명에 앞서 이러한 이론적인 설명은 꼭 필요합니다.

위와 같이 Tech Map 으로 전체 기술에 대해 이론적으로 잘 정리해 두면 기술에 대해서 더 잘 이해할 수 있고, 실전에서 (상황에 맞게) API Hooking 을 적용하기 쉬워집니다.

다음 번 포스트에서는 위 방법을 하나씩 실습해 보도록 하겠습니다. (static 방법에 대한 설명은 생략하겠습니다.) 각 경우에 대한 실습을 진행하면서 그때그때 필요한 설명은 자세히 추가하겠습니다.




ReverseCore


반응형
반응형

API Hooking 에 대한 강좌입니다.
User 에서 API Hooking의 다양한 기법들에 대해서 자세히 설명하도록 하겠습니다.



후킹 (Hooking)

리버싱에서 후킹은 정보를 가로채고, 실행 흐름을 변경하고, 원래와는 다른 기능을 제공하게 하는 기술입니다.

후킹의 전체 프로세스는 아래와 같습니다.

- 디스어셈블러/디버거를 이용하여 프로그램의 구조와 동작원리를 파악
- 버그 수정 또는 기능 개선에 필요한 Hook 코드를 개발 [1]
- 실행 파일과 프로세스 메모리를 자유롭게 조작하여 Hook 코드 설치

위와 같은 일련의 작업들은 그야말로 리버스 엔지니어링 기술의 핵심(Core) 이라고 할 수 있습니다.

그래서 전 후킹을 "리버싱의 꽃" 이라고 부릅니다.

여러가지 후킹 기술이 있지만 그중에서도 API 를 후킹하는 기술을 API Hooking 이라고 하고, User mode 후킹 중에서 메시지 후킹[2]과 함께 가장 널리 사용되는 기술입니다.


[1] 프로그램 소스가 있다면 대부분의 경우 후킹은 필요하지 않을 것입니다. 하지만 특수한 상황(소스 코드가 없거나, 소스 코드의 수정이 여의치 않은 상황)에서는 후킹 기술이 요긴하게 사용될 수 있습니다.

[2] 메시지 후킹(Message Hooking) 에 대한 내용은 제 글을 참고하시기 바랍니다.

- Windows Message Hooking (윈도우 메시지 후킹)



API (Application Programming Interface)


API Hooking 을 설명하려면 먼저 API(Application Programming Interface) 에 대해서 짚고 넘어가야 합니다.

Windows OS 에서는 사용자 어플리케이션이 시스템 자원(메모리, 파일, 네트워크, 비디오, 사운드, 기타)을 사용하고 싶을 때 직접 할 수 있는 방법이 없습니다. 왜냐하면 그것들은 OS 가 직접 관리하며, 여러 가지 이유(안정성, 보안, 효율, 기타)로 사용자 어플리케이션의 직접적인 접근을 막아놓았기 때문입니다.

이럴 때 사용자 어플리케이션은 시스템 커널에게 요청해야 합니다. 요청 방법이 바로 MS 에서 제공한 Win32 API 를 이용하는 것입니다. (API 는 해당 OS 제작사에서 제공합니다.)

즉, API 함수 없이는 어떤 의미 있는 프로그램을 만들어 낼 수 없습니다.

아래 그림은 32 bit Windows OS 의 프로세스 메모리를 간략히 나타낸 것입니다.


<Fig. 1>

실제 어플리케이션 코드를 실행 시키기 위해 많은 시스템 라이브러리(DLL) 들이 로딩됩니다. [3] 모든 프로세스에는 기본적으로 kernel32.dll 이 로딩되구요, kernel32.dll 은 ntdll.dll 을 로딩합니다. (참고로 GUI 어플리케이션에서는 user32.dll 과 gdi32.dll 또한 필수 라이브러리 입니다.)

ntdll.dll 의 역할이 바로 유저 모드 어플리케이션의 코드에서 발생하는 시스템 자원에 대한 접근을 커널 모드에게 요청 하는 것입니다.


간단한 를 들어보겠습니다.
notepad.exe 에서 c:\abc.txt 라는 파일을 열고자 합니다.
코드에서는 msvcrt!fopen() API 를 호출합니다. 그 이후의 API 호출 흐름을 보면 아래와 같습니다.

msvcrt!fopen()
 
kernel32!CreateFileW()
    ntdll!ZwCreateFile()
      ntdll!KiFastSystemCall()
        SYSENTER                     // Intel IA-32 Op Code
          => 커널 모드 진입


일반적인 시스템 자원을 사용하는 API 는 kernel32.dll 과 ntdll.dll 을 타고 가다가 결국 SYSENTER 명령을 통해 커널 모드로 진입하게 됩니다.


[3] 'DLL 로딩(loading)' 이라는 용어보다는 'DLL 매핑(mapping)' 이라는 용어가 더 정확한 표현입니다. Windows 운영체제는 DLL 을 최초 한번만 메모리에 적재(loading) 하고, 그 이후부터는 프로세스에게 매핑(mapping) 시켜주는 메커니즘을 사용합니다.



API Hooking


API Hooking 이란 Win32 API 호출을 중간에서 가로채서 제어권을 얻어내는 것입니다.

API Hooking 의 이점은 다음과 같습니다.

- API 호출 전/후에 사용자의 훅 코드(Hook Code)를 실행시킬 수 있습니다.
- API 에 넘어온 파라미터 혹은 API 함수의 리턴값을 엿보거나 조작 할 수 있습니다.
- API 호출 자체를 취소시키거나 사용자 코드로 실행 흐름을 변경시킬 수 있습니다.

이해를 돕기 위해 아래 그림을 봐주시기 바랍니다.

먼저 정상적인 API 호출입니다.


<Fig. 2>

코드 영역 주소에서 CreateFile() API 를 호출하였습니다. [4]

CreateFile() API 는 kernel32.dll 에서 서비스(export) 하므로 kernel32.dll 영역의 CreateFile() API 가 실행되고 정상적으로 리턴합니다.

[4] 실제 kernel32 에서 서비스되는 API 이름은 CreateFileA() 와 CreateFileW() 입니다. 프로그래밍할 때 CreateFile() 만 써주면 컴파일 시에 적절히 CreateFileA()/CreateFileW() 중에서 결정됩니다. 여기서는 설명의 편의상 CreateFile() 로 하였습니다.


다음은 kernel32!CreateFile() 가 후킹된 경우입니다.


<Fig. 3>

사용자가 DLL Injection 기술로 hook.dll 을 프로세스 메모리 공간에 침투 시킵니다. 그리고 kernel32!CreateFile() 를 hook!MyCreateFile() 로 후킹하였습니다. (후킹 함수 설치 방법은 DLL Injection 말고도 더 있습니다.)

이제부터 해당 프로세스에서 CreateFile() API 가 호출 될 때마다 kernel32!CreateFile() 이 호출 되는 것이 아니라, hook!MyCreateFile() 이 호출 됩니다.

후킹 함수(MyCreateFile)와 원본 함수(CreateFile)의 호출 순서는 경우에 따라 달라집니다.
입력된 파라미터를 조작하고 싶을 때는 후킹 함수가 먼저 실행되고 나중에 원본 함수가 실행됩니다. 또한 API 리턴값을 조작하고 싶을 때는 원본 함수가 먼저 실행된 후 후킹 함수가 나중에 실행됩니다.

이 외에도 후킹 목적에 따라서 원본 함수 호출 전/후에 후킹 함수를 실행시키거나 원본 함수를 아예 호출하지 않는 등의 여러 가지 변형이 가능합니다. 따라서 후킹 목적과 상황에 따라서 적절히 사용해 주시면 되겠습니다.

이것이 바로 API Hooking 의 기본 개념입니다.

API Hooking 을 구현하는 방법은 다양합니다. 하지만 후킹의 기본 개념은 변하지 않습니다.

위의 개념을 잘 이해하시면 이후에 설명 드리는 구현 방법에 대해서도 쉽게 이해하실 수 있습니다.


+---+

다음 포스트로 이어집니다.

API Hooking - Tech Map


ReverseCore

반응형
반응형

DLL Injection 에 대해서 자세히 알아보겠습니다.

DLL Injection 기법은 다른 프로세스에 침투하는 가장 쉽고 강력한 방법입니다.



DLL Injection 이란?


다른 프로세스에 특정 DLL 파일을 강제로 삽입시키는 것입니다.

더 정확히 표현하면 다른 프로세스에게 LoadLibrary() API 를 호출하도록 명령하여 내가 원하는 DLL 을 loading 시키는 것입니다.

따라서 DLL Injection 이 일반적인 DLL loading 과 다른점은 loading 대상이 되는 프로세스가 내 자신이냐 아니면 다른 프로세스냐 하는 것입니다.

아래 그림을 봐주세요.


<Fig. 1>

notepad 프로세스에 myhack.dll 을 강제로 삽입시켰습니다.
(원래 notepad 는 myhack.dll 을 로딩하지 않습니다.)

notepad 프로세스에 로딩된 myhack.dll 은 notepad 프로세스 메모리에 대한 (정당한) 접근권한이 생겼기 때문에 사용자가 원하는 어떤 일이라도 수행할 수 있습니다. (예: notepad 에 통신기능을 추가하여 메신저나 텍스트 웹브라우저 등으로 바꿔버릴 수도 있습니다.)



DLL Injection 사용 목적


LoadLibrary() API 를 이용해서 어떤 DLL 을 로딩시키면 해당 DLL 의 DllMain() 함수가 실행됩니다.

DLL Injection 의 동작원리는 외부에서 다른 프로세스로 하여금 LoadLibrary() API 를 호출하도록 만드는 것이기 때문에 (일반적인 DLL loading 과 마찬가지로) 강제 삽입된 DLL 의 DllMain() 함수가 실행됩니다.

또한 삽입된 DLL 은 해당 프로세스의 메모리에 대한 접근권한을 갖기 때문에 사용자가 원하는 다양한 일(버그 패치, 기능 추가, 기타)을 수행 할 수 있습니다.

그런데 문제는 대부분 악의적인 용도로 사용된다는 것입니다.

- 악성 코드

정상적인 프로세스(winlogon.exe, services.exe, svchost.exe, explorer.exe, etc)에 몰래 숨어들어가 악의적인 짓들을 합니다. 다른 악성 파일을 다운받거나, 몰래 백도어를 열어두고 외부에서 접속하거나, 키로깅 등의 나쁜짓을 하는 것이죠.

정상 프로세스 내부에서 벌어지는 일이라서 일반적인 PC 사용자들은 눈치채기 어렵습니다.
만약 explorer.exe 가 80 포트로 어떤 사이트에 접속시도를 한다고 생각해보세요.
일반인들은 그냥 정상 프로세스의 정상적인 동작으로 생각하기 쉽습니다.

- 유해 프로그램, 사이트 차단 프로그램

부모님들께서 아이들의 건전한 PC 사용을 위해 설치하는 '프로세스 차단 프로그램' 등이 있습니다.
주로 게임 프로그램과 성인 사이트 접속 등을 방지하는 역할을 하지요.

아이들 입장에서야 원수(?)같은 프로그램이라서 미친듯이 해당 프로세스를 종료하려 듭니다.
DLL Injection 기법으로 정상 프로세스에 살짝 숨어들어간다면 들키지도 않고, 프로세스 강제 종료에도 안전하게 됩니다. (Windows 핵심 프로세스를 종료하면 시스템이 같이 종료되기 때문에 결국 '차단' 하려는 목적을 달성하는 셈이지요.)

- 기능 개선 및 (버그) 패치 

만약 어떤 프로그램의 소스 코드가 없거나 수정이 여의치 않을 때 DLL Injection 을 사용하여 전혀 새로운 기능을 추가하거나 (PlugIn 개념) 문제가 있는 코드, 데이타를 수정할 수 있습니다.
일단 프로세스 메모리에 침투한 DLL 은 해당 프로세스의 메모리에 자유롭게 접근 할 수 있기 때문에 코드, 데이타를 고칠 수 있습니다.
저도 예전에 인터넷에서 다운받은 헥사 에디터에 버그가 있길래 DLL Injection 기법을 이용해서 해당 버그 코드를 간단히 패치해서 사용한 적이 있습니다. (그냥 다른 헥사 에디터를 다운 받아도 써도 되지만 고쳐 쓰고 싶은 마음에... ^^)

- API Hooking

다음번에 설명드릴 주제인데요, API Hooking 에 DLL Injection 기법이 많이 사용됩니다.
정상적인 API 호출을 중간에서 후킹하여 제가 원하는 기능을 추가 (혹은 기존 기능을 제거)하는 목적으로 사용됩니다.

이 역시 삽입된 DLL 은 해당 프로세스의 메모리에 대한 접근 권한을 가지고 있다는 특성을 잘 활용한 것입니다.



DLL Injection 간단 실습


notepad.exe 프로세스에 myhack.dll 을 injection 시키도록 하겠습니다.
=> myhack.dll 은 www.naver.com/index.html 을 다운받도록 프로그래밍 하였습니다.

myhack.dll

InjectDll.exe


1) InjectDll.exe 와 myhack.dll 을 다운받아 C:\ 에 복사합니다.
2) 메모장(notepad.exe) 을 실행합니다.
3) InjectDll.exe 를 실행합니다.

Process Explorer 를 이용하여 notepad.exe 프로세스에 Injection 된 myhack.dll 을 확인해 보겠습니다.


<Fig. 2>

notepad.exe 프로세스 메모리 공간에 myhack.dll 이 들어와 있는게 보이시죠?

C:\index.html (네이버 초기화면 html) 파일이 정상적으로 생겼는지 볼까요?


<Fig. 3>

index.html 파일을 메모장으로 열어보겠습니다.


<Fig. 4>

정상적으로 notepad.exe 프로세스에 myhack.dll 이 Injection 되어 http://www.naver.com/index.html 파일을 받아왔습니다.

이와 같이 다른 프로세스에 침투하여 원하는 동작을 마음껏 수행할 수 있는 Dll Injection 기법의 원리와 구현 방법에 대해서 알아보겠습니다.


Dll Injection - 다른 프로세스에 침투하기 (2)


ReverseCore

반응형

+ Recent posts