Windows Message Hooking ( 키보드입력 후킹 실습 )

2018. 5. 10. 23:53악성코드 분석


* 메모장에서 키보드 입력하려는 것을 후킹하여 메모장에서 키보드 입력이 먹히지 않도록 하는 실습


[ KeyHook Code ]

KeyHook.cpp 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "stdio.h"
#include "windows.h"
 
#define DEF_PROCESS_NAME        "notepad.exe"
 
HINSTANCE g_hInstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
    switch( dwReason )
    {
        case DLL_PROCESS_ATTACH:
            g_hInstance = hinstDLL;
            break;
 
        case DLL_PROCESS_DETACH:
            break;    
    }
 
    return TRUE;
}
 
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    char szPath[MAX_PATH] = {0,};
    char *= NULL;
 
    if( nCode >= 0 )
    {
        // bit 31 : 0 => press, 1 => release
        if!(lParam & 0x80000000) )
        {
            GetModuleFileNameA(NULL, szPath, MAX_PATH);
            p = strrchr(szPath, '\\');
 
            // 현재 프로세스 이름을 비교해서 만약 notepad.exe 라면 0 아닌 값을 리턴함
            // => 0 아닌 값을 리턴하면 메시지는 다음으로 전달되지 않음
            if!_stricmp(p + 1, DEF_PROCESS_NAME) )
                return 1;
        }
    }
    // 일반적인 경우에는 CallNextHookEx() 를 호출하여
    //   응용프로그램 (혹은 다음 훅) 으로 메시지를 전달함
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
 
#ifdef __cplusplus
extern "C" {
#endif
    __declspec(dllexportvoid HookStart()
    {
        g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
    }
 
    __declspec(dllexportvoid HookStop()
    {
        if( g_hHook )
        {
            UnhookWindowsHookEx(g_hHook);
            g_hHook = NULL;
        }
    }
#ifdef __cplusplus
}
#endif
cs



HookMain.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "stdio.h"
#include "conio.h"
#include "windows.h"
 
#define    DEF_DLL_NAME        "KeyHook.dll"
#define    DEF_HOOKSTART        "HookStart"
#define    DEF_HOOKSTOP        "HookStop"
 
typedef void (*PFN_HOOKSTART)();
typedef void (*PFN_HOOKSTOP)();
 
void main()
{
    HMODULE            hDll = NULL;
    PFN_HOOKSTART    HookStart = NULL;
    PFN_HOOKSTOP    HookStop = NULL;
    char            ch = 0;
 
    // KeyHook.dll 로딩
    hDll = LoadLibraryA(DEF_DLL_NAME);
    if( hDll == NULL )
    {
        printf("LoadLibrary(%s) failed!!! [%d]", DEF_DLL_NAME, GetLastError());
        return;
    }
 
    // export 함수 주소 얻기
    HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);
    HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);
 
    // 후킹 시작
    HookStart();
 
    // 사용자가 'q' 를 입력할 때까지 대기
    printf("press 'q' to quit!\n");
    while( _getch() != 'q' );
 
    // 후킹 종료
    HookStop();
    
    // KeyHook.dll 언로딩
    FreeLibrary(hDll);
}
cs


LoadLibrary()함수를 통해서 KeyHook.dll을 로드한다

( =DLL Injection & DLL실행 )


SetWindowHookEx 

윈도우즈에서 후킹을 설치하는 함수

Installs an application-defined hook procedure into a hook chain.


SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0) - 키보드의 입력을 훔쳐온다



[ 요약 ]

* 악성 DLL과 해당 DLL을 로드 & 실행하는 코드를 작성

* 실행파일로 변환한다

* 실행파일을 실행시키면 해당 DLL을 로드하고 DLL이 실행되어 악의적인 행위를 수행한다



[ 실습 ]

[1] dll파일을 로드하고 실행시키는 메인함수를 가진 파일 작성


[2] 실제 악성행위를 수행하는 dll파일을 생성


[3] main에서 dll을 임포트하기 때문에 파일명을 일치시켜서 작성


[4] "Release" -> 실행가능한 파일 생성


[5] 생성된 파일들


[6] 실행 결과

- q를 통해 hooking파일을 종료하지 않으면 메모장의 키보드 입력은 계속해서 후킹된 상태로, 아무것도 입력할 수 없다