수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1689691
  • Today | 153
  • Yesterday | 540

1 Articles, Search for 'Hooking'

  1. 2007/01/25 Low-Level 키보드 입력 후킹
Programming/C#2007/01/25 17:47

Low-Level 키보드 입력 후킹

고수닷넷 - Kenial님

Just hook!

첨부된 파일을 먼저 확인하시라. 컴파일을 수행하고 Hook! 버튼을 누르면 해당 폼에서뿐만 아니라 전체 윈도우에서 delete, tab, esc 키 등이 입력되지 않는 것을 확인할 수 있다. (alt + tab 등도 tab키가 입력되는 조합이므로 입력되지 않는다)


실제 코드를 살펴보자. (Form1.cs 참조) KeyboardHooker의 사용 방법은 실로 간단한데, 단순히 KeyboardHooker.HookedKeyboardUserEventHandler 딜리게이트를 처리할 수 있는 이벤트를 만들고, 이벤트 핸들러를 KeyboardHooker.HookedKeyboardUserEventHandler에 등록하면 된다.


private void Form1_Load(object sender, System.EventArgs e) {

   this.HookedKeyboardNofity += new KeyboardHooker.HookedKeyboardUserEventHandler(Form1_HookedKeyboardNofity);

}


event KeyboardHooker.HookedKeyboardUserEventHandler HookedKeyboardNofity;

   이벤트 핸들러를 등록


그리고 이벤트 핸들러를 구현하자. 지금 구현된 이벤트 핸들러는 tab, delete, esc 키의 입력을 막고 있으나, 사용하기에 따라서는 조합키(ctrl + a같은)의 입력을 핸들링하는데 사용하거나, KeyLogger의 용도로써도 사용할 수 있다. 이벤트 핸들러의 구현은 다음과 같다 :


private long Form1_HookedKeyboardNofity(

   bool bIsKeyDown, bool bAlt, bool bCtrl, bool bShift, bool bWindowKey, int vkCode ) {

long lResult = 0;


//  입력을 막고 싶은 키가 있을 경우, 해당 키가 입력되었을 때

//  0이 아닌 값을 리턴하면 다른 프로세스가 해당 키보드 메시지를 받지 못하게 된다.

//  지금의 예처럼 코딩하면 Tab,Delete,Esc 키의 입력을 막게 된다.

if(

   (vkCode == (int)System.Windows.Forms.Keys.Tab) ||

   (vkCode == (int)System.Windows.Forms.Keys.Delete) ||

   (vkCode == (int)System.Windows.Forms.Keys.Escape)) {

   lResult = -1;

}


return lResult;

}

   이벤트 핸들러 구현


실제 후킹을 시작/중지하는 코드는 다음과 같다 :


private void button2_Click(object sender, System.EventArgs e) {

   //  후킹 여부 검사

   if(KeyboardHooker.Hooked)

       // 후킹 중지

       KeyboardHooker.UnHook();

   else

       // 후킹 시작(이벤트를 넘겨줘서, KeyboardHooker에서 해당 이벤트를 이벤트 핸들)

       KeyboardHooker.Hook(HookedKeyboardNofity);

   

   if(KeyboardHooker.Hooked)

       this.button2.Text = "Unhook";

   else

       this.button2.Text = "Hook!";

   this.textBox1.Focus();

}

    후킹 시작/중지



KeyboardHooker.Hook() 메서드


KeyboardHooker 클래스에서 가장 핵심적인 부분이라고 할 수 있다. 일단 소스를 보면 다음과 같다 :


public static bool Hook(HookedKeyboardUserEventHandler callBackEventHandler)

{

   bool bResult = true;

   m_hDllKbdHook = SetWindowsHookEx(

       (int)WH_KEYBOARD_LL,

       m_LlKbEh,

       Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(),

       0);

   

   if(m_hDllKbdHook == 0)

   {

       bResult = false;

   }

   // 외부에서 KeyboardHooker의 이벤트를 받을 수 있도록 이벤트 핸들러를 할당함

   KeyboardHooker.m_fpCallbkProc = callBackEventHandler;

   m_Hooked = bResult;

   return bResult;

}


이 중 실제로 hook chain에 hook procedure (소스에서는 HookKeyboardProc() 메서드)를 등록하는 함수인 SetWindowsHookEx()의 원형은 MSDN을 참고하면 다음과 같다 :


HHOOK SetWindowsHookEx(

   int idHook,     HOOKPROC lpfn,     HINSTANCE hMod,     DWORD dwThreadId );


WH_KEYBOARD_LL은 상수로써, 저수준(low-level)의 키보드 입력 메시지를 후킹하게 되는 것을 나타낸다.


Km_LlKbEh는 HookedKeyboardEventHandler 딜리게이트로써, HookKeyboardProc() 함수를 이벤트 핸들러로 등록하고 있음을 알 수 있다. Kenial도 WinAPI를 호출할 경우 콜백 함수를 어떤 식으로 등록해야 하는지 몰라서 헤맸던 경험이 있는데, 이와 같이 해당 함수를 이벤트 핸들러로 갖는 딜리게이트를 선언한 후에 해당 딜리게이트의 인스턴스를 콜백 함수 인자로 넘겨주면, 닷넷 프레임워크(아마도 System.Runtime.InteropServices)에서 해당 딜리게이트 인스턴스를 변환, 콜백 함수 주소를 넘겨주는 것으로 보인다.


Marshal.GetHINSTANCE() 함수는 현재 모듈의 인스턴스 핸들을 얻는 함수이다.


마지막 0은 hook procedure가 적용될 쓰레드의 id를 나타내는 인자인데, KeyboardHooker는 윈도우 내 모든 프로그램의 키 입력을 후킹하기 위해 만들어졌으므로 0으로 설정한다.


callBackEventHandler는 KeyboardHooker 객체에 이벤트 핸들러를 등록하게 함으로써, 키 입력이 있을 때 Hook() 메서드를 호출한 어플리케이션에 해당 이벤트를 넘겨주기 위해서 등록하는 것이다.


후킹 기능을 제공하는 클래스는 어차피 여러 개의 인스턴스가 생성될 필요는 없다고 판단해서, Kenial은 이 클래스를 전체가 정적 메서드로 구성된 클래스로 만들었다. 하지만 event는 정적 필드(static)로 사용할 수 없으므로, 이처럼 Form에서 event를 선언해서 유저용 이벤트 핸들러를 KeyboardHooker의 정적 필드 이벤트 핸들러에 등록할 수 있는 형태로 만들게 되었다.



KeyboardHooker.HookedKeyboardProc() 메서드


이 메서드는 실제로 low-level 키보드 메시지를 처리하는 프로시저로써 hook chain에 등록된다. (hook chain에 대해서는 msdn의 win32 hooks, about hooks 항목을 읽어보기 바란다)


C# 언어의 (WinAPI 프로그래밍을 하기 위해서) 중요한 키워드 중 하나인 unsafe가 나온다. unsafe 키워드를 처음 접한다면, 여기에서는 단지 포인터를 사용하기 위해서 필요한 것이라고 이해하시고 넘어가면 되겠다.(CopyMemory로 lParam으로 넘어온 KBDLLHOOKSTRUCT의 주소에 접근해 해당 객체를 m_KbDllHs로 복사하고 있다.


그 다음 Hook()에서 등록한 이벤트 핸들러인 m_fpCallbkProc으로 키보드 메시지를 넘겨주게 되어 콜백 함수를 호출하는 것과 같은 형태의 코드가 되었다.


그리고 CallNextHookEx()은 hook chain에 등록된 다른 hook procedure를 호출하는 명령인데, msdn에는 다음과 같이 설명되어 있다 :


If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.

If nCode is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_KEYBOARD_LL hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the rest of the hook chain or the target window procedure.


nCode가 HC_ACTION이 아닐 때, (low level 키보드 메시지가 아닌 다른 후킹된 메시지일 때) 다음 hook procedure로 해당 메시지를 넘겨줌으로써 hook chain이 제대로 동작할 수 있도록 하는 코드이다.



참고


GotDotNet User Sample : Low Level Keyboard Capture

http://www.gotdotnet.com/community/user ··· ed45f251

Key Support, Keyboard Scan Codes, and Windows

http://www.microsoft.com/whdc/device/in ··· ode.mspx



정리


간략하게 쓰고 싶었습니다만, 쉽지 않군요.


여기서 설명되지 않은 부분은, msdn을 참고하시면서 보시면 쉽게 이해하실 수 있는 내용이라고 생각합니다. hooks에 전혀 관심이 없으시다면 할 수 없지만.. 이 아티클을 통해 한 번 접근해보실 수 있는 기회가 됐으면 좋겠습니다.


그럼 : )

"C#" 카테고리의 다른 글
  • ListView 의 항목들을 Excel 파일로 저장하기 (0)2007/01/25
  • 움직이는 Text 그래픽을 만들어보자. (0)2007/01/25
  • Low-Level 키보드 입력 후킹 (0)2007/01/25
  • 인터넷 웹 브라우저를 만들어보자. (0)2007/01/23
  • 프로퍼티 그리드 컨트롤을 다루어 보자. (0)2007/01/23
2007/01/25 17:47 2007/01/25 17:47
Posted by webdizen
Tags C#, Hooking
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/2594

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • Web Mining
  • vibebs
  • 최후의 결전
  • 건축물
  • 회사
  • XML 인덱싱
  • 경연대회
  • 세면도구
  • 빠에야
  • 스킨스쿠버
  • 통합
  • Samsung
  • WinAPI
  • SDA
  • 미디어
  • Filtering
  • Wikia Search
  • Profile
  • Gimp
  • Photograph

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • Lots of students know techn....
    Bobbi35Shannon 02/25
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08
  • 재밌네요~ 첫번째꺼는 요즘....
    Hybrid 2009

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  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      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Rodman®
      • ■ Feel So Good~! ■
      • 까만 나비
      • 나를 가꾸는 시간.
      • 나만의 즐거움~~!
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.