Tuesday, June 13, 2006

PyHook

Az utobbi egy honapban 2x kellett kicserelni a ramot a desk gepben, es meg mindig nem jo valami mert idonkent ugy random BSODzik vmitol. Eleg idegesito gepeles kozben ha elszall es kezheti elorol (legalabbis legutobbi mentestol) az ember. Ugyhogy elhataroztam h amig ez a problema fennall, rakok egy keyloggert sajat gepre. Vagyis, inkabb irni jobb lenne. Regebben csinaltam keyboard hook alapjan mukodo progit cpp/winapival de most inkabb a konnyebb utat valasztottam. A PyHook egy thirdparty lib pythonhoz amivel meglehetosen egyszeruen hookolhatjuk az egeret/billentyuzetet. Egy hookmanagert kell letrehozni, beallitani egy eventet, es aktivalni a hookot. 3sor. A callbackben pedig szepen megkapjuk a lenyomott bill kodjat, a forras ablak handlejet, titlejet, a leutes idejet.. stb. Persze az egesz win alatt muxik mert nativ win32apis hivasokat (SetWindowsHook) wrappel. De hat nekem pont ez kell.


>>> import pyHook, pythoncom
>>> def kbproc( evt ): print evt.Ascii
...
>>> hm = pyHook.HookManager()
>>> hm.KeyDown = kbproc
>>> hm.HookKeyboard()
>>> pythoncom.PumpMessages()


Egy olyasmit akarok ami kategoriazalja a logot a forras app-tol fuggoen. Szoval kulon logolja azt amit a bongeszobe irok, kulon azt amit az editor, es mondjuk nem logolja azt amit az irckliensbe.
Mivel az eventbol kiolvashato az ablak handleje ami eppen aktiv volt a billentyuzet leutes pillanataban ez eleg egyszeruen megoldhato. A handle alapjan az hozza tartozo app pid-jet kell meghatarozni, az alapjan pedig le lehet kerdezni a program nevet. (GetModuleFileName)

Ime a prototipus:


def getProcNameByPID( pid ):
h = None
try:
h = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, pid)
return os.path.basename( win32process.GetModuleFileNameEx( h, 0 ) )
finally:
if h: h.Close()


Ja, es a pidet az ablak handle-bol pedig igy kaptam meg:


win32process.GetWindowThreadProcessId( evt.Window )[1]


A keyboard proc pedig a kovetkezo:


def keyBoardProc( evt ):
if evt.Key == 'F12':
hm.KeyDown = None
hm.UnhookKeyboard()
return
if evt.Ascii:
fname = '%s.log' % ( getProcNameByPID( win32process.GetWindowThreadProcessId( evt.Window )[1] ) )
open( fname, 'a' ).write( "%c" % (evt.Ascii) )


Lathato hogy F12-re probaltam meg unhookolni viszont, ilyenkor a lib egy AV-vel elszall, ugyhogy ez a feature nemigazan mukodik. Ha valaki tudja miert plz irja meg.
Mindenesetre a szelektalas jol mukodik, konnyen beallithato kulonbozo filter, hogy pl ircklienst vagy jatekot ne logolja mert az egyik ugyis logol maganak, a masiknal meg tok felesleges.

Majd ha lesz vmi vegleges verzio, esetleg kozzeteszem :)

0 comments: