게임 매크로 Inventory A+ 분석

2012/02/15 21:17

1. 기능 소개


사용자 삽입 이미지

[그림 1] Warcraft III 에서의 인벤토리


Inventory A+는 Blizzard 사의 Warcraft III 의 인벤토리 단축키를 변경하는 매크로입니다. 원래 인벤토리의 아이템을 사용하기 위한 단축키는 숫자패드의 7, 8, 4, 5, 1, 2 이지만, Inventory A+ 를 실행하면 인벤토리 단축키가 [그림 2]와 같이 변경됩니다. 실제로 이 매크로는 DotA 용으로 제작된 것입니다.


사용자 삽입 이미지

[그림 2] Inventory A+ 실행 후

 

2. 분석

Inventory A+는 AutoHotKey 기반으로 제작되었습니다. 프로그램 내에 AutoHotKey 의 문자열들과 실행되지 않는 코드의 흔적들이 남아 있지요. 그리고 메뉴, 뮤텍스, 윈도우의 이름도 AutoHotKey 의 것들을 그대로 사용하고 있습니다.

 

2.1. Warcraft III: Frozen Throne 설치 확인 (_GetInstallPath)


사용자 삽입 이미지

[그림 3] 레지스트리에서 Frozen Throne 의 설치 경로를 읽는다


Inventory A+ 는 Warcraft III: Frozen Throne 의 설치 경로를 다음의 레지스트리에서 읽어서 확인합니다.


Key = “HKEY_CURRENT_USER\Software\Blizzard Entertainment\Warcraft III”
SubKey = “ProgramX”


그리고 Frozen Throne 의 실행 파일에서 아이콘을 Inventory A+ 자신의 아이콘으로 사용합니다.


사용자 삽입 이미지

[그림 4] Inventory A+의 아이콘

 

2.2. 후킹 프로시저 설치 (_InstallHookProc)

 
사용자 삽입 이미지
[그림 5] 키보드 후킹 프로시저 설치
 
Inventory A+ 는 후킹 프로시저를 설치하는 스레드를 생성합니다. 스레드 함수에서는 [그림 5]와 같이 SetWindowsHookEx API 를 호출합니다. 인자로는 WH_KEYBOARD_LL 와 후킹 프로시저의 주소가 쓰이고, 전역적으로 후킹하기 위해서 스레드 ID 에 0 을 넣습니다.
 
WH_KEYBOARD_LL 은 저수준의 키보드 입력 내용을 모니터링하기 위한 식별값입니다. 후킹 프로시저의 형태는 다음과 같습니다.
 
_HotKeyHookProc (int code, WPARAM wParam, LPARAM, lParam);

 
WH_KEYBOARD_LL 후킹에서 wParam 은 키보드 메시지의 식별자입니다. WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP 등이 wParam 의 값들입니다..
 
그리고 lParam 은 KBDLLHOOKSTRUCT 구조체의 포인터이며, 구조는 다음과 같습니다.
 
typedef struct tagKBDLLHOOKSTRUCT {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT, *LPKBDLLHOOKSTRUCT;

 
vkCode 가 메시지를 발생시킨 가상 키 코드이고, flags 값으로 ALT 키가 같이 눌러졌는지 알 수 있습니다. ALT 키가 같이 눌려졌으면 flags 의 값은 LLKHF_ALTDOWN 입니다.
 

2.3. 키보드 후킹 프로시저 (_HotKeyHookProc)

키보드 메시지가 발생할 때마다 _HotKeyHookProc 함수가 전역적으로 호출됩니다.


사용자 삽입 이미지
[그림 6] 키보드 이벤트가 KEYUP 인지 KEYDOWN 인지 검사한다

 
사용자 삽입 이미지
[그림 7] 키보드 후킹 프로시저
 
[그림 6]처럼 wParam 을 검사하여서 키가 눌러진 것이라면 플래그를 설정하고 _HookHotKey 함수를 호출합니다. _HookHotKey 함수 안에서 k->vkCode 가 'Q', 'W', 'A', 'S', 'Z', 'X' 중의 하나인지, k->flags 의 LLKHF_ALTDOWN 비트가 세팅되었는지를 검사하는 것 같은데, 정확한 루틴이 어디 있는지는 찾지 못 했습니다.
 
원하는 키가 아니라면, CallNextHookEx API 를 호출한 후 리턴하여서 다음 훅으로 넘깁니다.
 
사용자 삽입 이미지
[그림 8] ALT+q 에 대하여 NUMPAD7 의 KEYDOWN 이벤트 발생
 
사용자 삽입 이미지
[그림 9] ALT+q 에 대하여 NUMPAD7 의 KEYUP 이벤트 발생
 
입력된 키가 ALT+q, ALT+w, ALT+a ALT+s, ALT+z, ALT+x 중의 하나라면, keybd_event API 를 KEYDOWN 인자로 호출하고 KEYUP 인자로 다시 호출합니다. 이렇게 하면 맵핑되는 숫자패드의 키에 대한 이벤트가 발생됩니다. keybd_event API 의 세 번째 인자가 0 이면 KEYDOWN 이벤트입니다. 그리고 0 이 아닌 정수를 리턴하여 키 입력을 무시합니다.
 

3. POC 코드


#include <windows.h>

LRESULT CALLBACK
HotKeyHookProc (int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0)
{
UINT hotkey = 0;
PKBDLLHOOKSTRUCT k = (PKBDLLHOOKSTRUCT)lParam;

BOOL f_AltDown = (LLKHF_ALTDOWN & k->flags) ? TRUE : FALSE;

switch (k->vkCode)
{
case 'Q':
hotkey = VK_NUMPAD7;
break;
case 'W':
hotkey = VK_NUMPAD8;
break;
case 'A':
hotkey = VK_NUMPAD4;
break;
case 'S':
hotkey = VK_NUMPAD5;
break;
case 'Z':
hotkey = VK_NUMPAD1;
break;
case 'X':
hotkey = VK_NUMPAD2;
break;
default:
break;
}

if ((hotkey != 0) && (f_AltDown == TRUE))
{
Sleep (1000);
keybd_event (hotkey, MapVirtualKey (hotkey, 0), 0, 0);
Sleep (100);
keybd_event (hotkey, MapVirtualKey (hotkey, 0), KEYEVENTF_KEYUP, 0);
return 1;
}
}

return CallNextHookEx (NULL, code, wParam, lParam);
}

int WINAPI
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HHOOK hhk = SetWindowsHookEx (WH_KEYBOARD_LL, HotKeyHookProc, hInstance, 0);

MessageBoxA (NULL, "Click \"Ok\" to terminate this hooking", "HotKeyHook", MB_OK);

UnhookWindowsHookEx (hhk);
return (0);
}

크리에이티브 커먼즈 라이센스
Creative Commons License

6l4ck3y3 0x02 Windows RCE , , , ,

Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. 재밌는 글 잘 보고 가요 :)

  2. Blog Icon
    6l4ck3y3

    고맙습니다 (_ _)

  3. 재밌게 잘 보고 있습니다.. 아이디가 눈에 익숙하군요 ^^

  4. Blog Icon
    6l4ck3y3

    고맙습니다 (_ _)

  5. 고맙습니다. ㅎ : D