윈도우 환경에서 Python을 사용하여 키보드 후킹을 하는 방법의 이해를 돕기 위한 예제 코드이다.
소스
# -*- coding: utf-8 -*-
#!/usr/bin/python
import sys
from ctypes import *
from ctypes.wintypes import MSG
from ctypes.wintypes import DWORD
user32 = windll.user32
kernel32 = windll.kernel32
WH_KEYBOARD_LL = 13
WM_KEYDOWN = 0x0100
CTRL_CODE = 162
class KeyRogue:
def __init__(self):
self.lUser32 = user32
self.hooked = None
def installHookProc(self, pointer):
self.hooked = self.lUser32.SetWindowsHookExA(
WH_KEYBOARD_LL,
pointer,
kernel32.GetModuleHandleW(None),
0
)
if not self.hooked:
return False
return True
def uninstallHookProc(self):
if self.hooked is None:
return
self.lUser32.UnhookWindowsHookEx(self.hooked)
self.hooked = None
def bytes(self, integer):
return divmod(integer, 0x10000)
def getFPTR(self, fn):
CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
return CMPFUNC(fn)
def startKeyLog(self):
msg = MSG()
user32.GetMessageA(byref(msg), 0, 0, 0)
def getKeyCode(self, lParam):
high, low = self.bytes(lParam[0])
return low
def hookProc(nCode, wParam, lParam):
if wParam is not WM_KEYDOWN:
return user32.CallNextHookEx(keyRogue.hooked, nCode, wParam, lParam)
keyCode = keyRogue.getKeyCode(lParam)
hookedKey = chr(keyCode)
print(hookedKey)
if (CTRL_CODE == keyCode):
print("ctrl pressed, call uninstallHook()")
keyRogue.uninstallHookProc()
sys.exit(-1)
return user32.CallNextHookEx(keyRogue.hooked, nCode, wParam, lParam)
keyRogue = KeyRogue()
pointer = keyRogue.getFPTR(hookProc)
if keyRogue.installHookProc(pointer):
print("install success")
keyRogue.startKeyLog()
else:
print("install failed")
문제 해결
- Python 3.7.5 64비트 버전에서 SetWindowsHookExA 호출 시에 0값이 리턴되면서 Hook 설치가 실패되는 일이 있었는데, 3.7.5 32비트 버전을 설치하니까 해결이 되었다. 그런데 3.6.5 64비트에서는 또 문제가 없고.. 잘 안될 경우는, 버전 혹은 비트 수를 변경해서 시도해볼 필요가 있다.
참고사항
<테스트 환경> - OS : Windows 10 - Python 버전 : 3.6.5(32/64bit), 3.7.5(32bit)
'1. 연구 모듈 > Python' 카테고리의 다른 글
| [Python] 키보드 후킹 - 간편화 코드 시행 착오 (0) | 2020.12.23 |
|---|---|
| [Python] 키보드 후킹 - 2. 간편화 코드 (0) | 2020.12.23 |
| [Python] .INI 파일에 설정 읽고 쓰기 - 2. 간편화 코드 (0) | 2020.12.18 |
| [Python] .INI 파일에 설정 읽고 쓰기 - 1. 예제 코드 (0) | 2020.10.16 |
| [Python] 인스턴스 메소드 vs. 정적 메소드 vs. 클래스 메소드 요약 (0) | 2020.09.21 |


