반응형

1. Project > Properties.

2. JRE System Library 의 앞 +를 클릭.

3. Native Library Folder Configuration을 클릭.

4. External Folder 나 Workspace를 선택하여 필요한 패스를 지정


반응형

Microsoft에서는 프로세스간의 주고 받는 메세지를 후킹할 수 있는 함수를 제공한다.
바 로 SetWindowsHookEx()함수이다. 이 함수를 통해 DLL을 특정 프로세스나 모든 프로세스에 Injection할 수 있다.그리고 User-mode(ring 3)에서 동작하는 Keylogger들 대부분이 이 함수를 사용하여 구현된다.(SetWindowsHookEx()함수를 통해 후킹(Hooking)을 할 경우 전역 후킹이 간단하므로 많이 사용한다.)

먼저 SetWindowsHookEx()함수의 원형부터 알아보자.
(MSDN에 있는 내용이다.)

HHOOK SetWindowsHookEx(
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);

첫번째 파라메터인 idHook 변수는 후킹 하고자 하는 메세지의 ID라고 할 수 있다. WH_GETMESSAGE, WH_KEYBOARD 등 다양한 메세지가 있다.(MSDN 참조)
idHook 파라메터에 지정된 값의 이벤트(메세지)가 발생할 경우 훅 프로시저(lpfb 파라메터에 설정된)가 동작하게 된다. 훅 프로시저는 Injection할 DLL(앞으로 Injected.dll이라 부르겠다)에 지정되어 있어야한다.

/* Injected.dll */
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
 /* 원하는 코드 삽입 */
 return CallNextHookEx(0, nCode, wParam, lParam);
};

마 지막에 CallNextHookEx()함수를 호출한 이유는 훅 체인에 있는 다른 훅 프로시저가 해당 메세지를 사용할 수도 있기때문이다. 예를들면 키보드메세지를 후킹하여 Keylogger를 만들었다고 하면 해당 메세지를 후킹 후 로깅을 하고 CallNextHookEx()함수를 통해 처리를 하지 않고 그냥 끝내 버린다면 들통나버릴것이다.

두번째 파라메터는 lpfn이다. 이 파라메터에는 Injected.dll에 지정된  훅 프로시저의 주소값을 지정한다.만약 IdHook에 WH_KEYBOARD를 지정하여 후킹 할경우 해당 훅 프로시저는 KeyboardProc이다. 주소 값을 지정해줘야하는데 하드코딩하여 지정해 줄 수 있지만 LoadLibrary()함수와 GetProcAddress를 이용하여 Injected.dll의 훅 프로시저의 주소를 구할 수 있다.

/* Injector.c */
HMODULE hDll;
unsigned long KeyboardProcAddr;

hDll = LoadLibrary("injected.dll");
KeyboardProcAddr = GetProcAddress(hDll, "KeyboardProc");

다음으로 세번째 파라메터인 hMod를 보자. hMod는 DLL의 핸들(Handle)을 지정해야한다.여기에선 Injected.dll의 핸들을 지정해주면 된다.
이미 Injector.c에서 LoadLibrary("Injected.dll"); 통해 핸들을 얻었으므로 hDll변수를 사용하면 된다.

네 번째 파라메터 dwThreadId는 후킹할 프로세스 즉 Injected.dll을 삽입할 스레드(Thread)의 ID이다. PID라고 하며 해당 파라메터에 0을 지정하면 모든 스레드에 훅(Hook)을 한다는 의미로 전역 훅을 할 수 있다. 특정 스레드에 Injection을 하려고 한다면 "작업관리자"를 통해 PID를 얻어 하드코딩하거나 아래와 같은 방법으로 PID를 얻어 사용할 수 있다.

/* 전역 훅 */
SetWindowsHookEx(WH_KEYBOARD, KeyboardProcAddr, hDll, 0)

/* 지역 훅*/
SetWindowsHookEx(WH_KEYBOARD, KeyboardProcAddr, hDll, GetCurrentThreadID());

dwThreadId 값을 얻기 위한 함수는 많다.

반응형

SimpleDllTest라는 이름으로 아래와 같이 프로젝트를 만든다.

 
사용자 삽입 이미지
 
사용자 삽입 이미지


사용자 삽입 이미지

해당 솔류션에 SimpleDll이란 이름으로 Dll을 생성하는 프로젝트를 아래와 같이 만듭니다.
사용자 삽입 이미지
사용자 삽입 이미지

다음과 같은 솔루션 탐색기를 확인 할 수 있습니다.
사용자 삽입 이미지



















이제 SimpleDll 프로젝트에서 다음과 같은 클래스를 추가 합니다.

Sample.h

 #pragma once

#ifdef DLLEXPORT
#define SAMPLE __declspec(dllexport)
#else
#define SAMPLE __declspec(dllimport)
#endif


class SAMPLE CSample
{
public:
 int m_i;
 CSample(void);
 ~CSample(void);
 int Test(int input);
};


Sample.cpp

 #define DLLEXPORT
#include "Sample.h"

CSample::CSample(void)
{
}

CSample::~CSample(void)
{
}

int CSample::Test(int input)
{
 return input + 1;
}

Dll이 완성 되었습니다.

SimpleDll을 컴파일하고 빌드하면 SimpleDllTest\Debug에서

SimpleDll.dll, SimpleDll.lib를 확인 할 수 있습니다.

이제 SimpleDll을 테스트하고 SimpleDll에서 변경시 바로 반영하기 위해서 프로젝트의
속성을 바꿔보도록 하겠습니다.

SimpleDll프로젝트 속성에서 빌드후 이벤트의 명령줄을 아래와 같이 입력합니다.

사용자 삽입 이미지

오른쪽 끝에 ...박스를 누르면 여러 줄을 입력할 수 있습니다.
사용자 삽입 이미지


이제 SimpleDllTest의 프로젝트 속성에서 링커/입력의 추가종석성에 SimpleDll.lib를 추가합니다.
사용자 삽입 이미지

마지막으로 프로젝트 탭의 프로젝트 종속성을 아래와 같이 변경합니다.
사용자 삽입 이미지

이제 다음과 같이 SimpleDllTest.cpp를 코딩해서 결과를 확인하면 됩니다.

 #include "stdafx.h"
#include "Sample.h"

int _tmain(int argc, _TCHAR* argv[])
{
 CSample s;

 printf("%d", s.Test(3));
 return 0;
}

정상적으로 잘 되었다면 4가 출력될 것입니다.

반응형

경고문에 XXXX.dll 이라고 뜰 경우 아래파일에서 찾아서

해당폴더에 다운받으시면 됩니다.

dll-files downloads


+ Recent posts