Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

Looking for efficient key-logger script.


  • Please log in to reply
14 replies to this topic
Matt324523453
  • Guests
  • Last active:
  • Joined: --
I know this is a difficult topic here, but I would really love to have a good key logger. From reading old discussions, I know that clever scripts are around, so I don't want to hack together something ugly myself.

My motivation: I write a lot and although I usually save documents every 5 minutes with new file names, I constantly find myself trying to remember some sentence I came up with a while ago. Also, everybody knows the feeling of utter terror when one clicks "back" accidentally after entering a 1000 word message into an online form. A keylogger would be a simple and universal solution.

I don't want to sniff passwords. In fact, I'd prefer an implementation that ignores letter case and perhaps even special characters, punctuation and long digit series (credit card numbers) so that my own passwords are not all over the backup file.

The data should ideally be saved in a txt file at a user-defined location. For increased legibility, it would be nice if the name of the currently active window were saved, too. Finally, a hotkey for switching the logger on/off would be great.

If a script with these properties is available, I'd be very thankful for getting it. Otherwise, a general tip on the most efficient implementation of keyloggers in AutoHotkey would be a start (should I use the input command? etc.).

Feel free to delete/close this thread if it's absolutely inacceptable to discuss the topic...

Thanks,
Matt

dmg
  • Members
  • 2346 posts
  • Last active: Yesterday, 04:30 AM
  • Joined: 19 Nov 2010
Because of the potential for misuse the subject of keyloggers is indeed somewhat of a taboo on this forum. However I too have found it useful to have a backup of recently typed text. The link in my signature is to my site, on which you will find an application called Key Catcher. It does not entirely meet your preferences but it is written in AHk and the source is included so you can modify it to your hearts content. The main advantage of key Catcher is that it attempts to record whole sentences at a time, rather than individual characters. It really makes it easier to read the log file. :?

Please take note of the usage agreement. Do not misuse it! :twisted:

Matt3245234532
  • Guests
  • Last active:
  • Joined: --

Because of the potential for misuse the subject of keyloggers is indeed somewhat of a taboo on this forum. However I too have found it useful to have a backup of recently typed text. The link in my signature is to my site, on which you will find an application called Key Catcher. It does not entirely meet your preferences but it is written in AHk and the source is included so you can modify it to your hearts content. The main advantage of key Catcher is that it attempts to record whole sentences at a time, rather than individual characters. It really makes it easier to read the log file. :?

Please take note of the usage agreement. Do not misuse it! :twisted:


Great, thanks a lot, I'll try it!

Matt3245234532
  • Guests
  • Last active:
  • Joined: --
Thanks again, works like a charm and the code is very clean. The idea of only storing sentences is awesome.

I added the current window name and removed all the hotkeys because I don't need such key presses to be logged. Same with the mouse logger.

I also tried to add comma to the matchlist but failed (despite trying , or ,, or ,,, or even ,,,, after reading the help for input). Any idea? I added it to the endkeys as a workaround.

By the way, there's a way to simplify the parsing of the endkey-names:

stringtrimleft, key, errorlevel, 7
key={%key%}

I also failed at adding a hotkey for toggling pausing of the script but it's not very important because it can be done via the try icon.

dmg
  • Members
  • 2346 posts
  • Last active: Yesterday, 04:30 AM
  • Joined: 19 Nov 2010

Thanks again, works like a charm and the code is very clean. The idea of only storing sentences is awesome.

I added the current window name and removed all the hotkeys because I don't need such key presses to be logged. Same with the mouse logger.

I also tried to add comma to the matchlist but failed (despite trying , or ,, or ,,, or even ,,,, after reading the help for input). Any idea? I added it to the endkeys as a workaround.

By the way, there's a way to simplify the parsing of the endkey-names:

stringtrimleft, key, errorlevel, 7
key={%key%}

I also failed at adding a hotkey for toggling pausing of the script but it's not very important because it can be done via the try icon.

Glad to hear it will work for you. :D

Key Catcher was a very early project so I am sure there are any number of ways it could be improved. To be honest it has been so long since I did anything with it that I don't really remember how most of it works at this point. :oops: I will probably go through the source and re write it some day.

You say you added the ability to record the current window name? I would be very interested to see the changes you made. :D

Matt123
  • Members
  • 6 posts
  • Last active: Feb 12 2012 02:10 PM
  • Joined: 22 Nov 2011
(I'm Matt3245234532, figured it was time to register.)

Here's my current version. I apologise for brutally deleting everything I didn't need, don't take it personally ;)

My comments in the code start with MM

This is what I changed:
- added window title logging
- added black list of windows in which no input should be logged
- added most non-alphanumeric keys as "endkeys"
- effectively added mouseclicks as endkeys, too
- simplified the parsing and writing of logged info a little
- changed logging format to "date"-tab-"text"-tab-"key" so that it could be imported into excel etc. easily if the need arises
- also, i'm using "tab" rather than "space" for indentations in the code, so I changed that, in case you were wondering

;Copyright 2010-2011 Daniel Green, v1.00.3b modified 1/14/11 3:28am

;Key Catcher is free for both business and personal use. It can be freely modified and redistributed providing that, 1. all notices remain intact, 2. you acknowledge where it originally came from, 3. it is only used for legal and ethical purposes, 4. no profit is derived from its distribution.

#noenv
#singleinstance, ignore
setbatchlines, -1
setworkingdir, %a_scriptdir%
process, priority, ,high
coordmode, tooltip, screen

menu, tray, Icon, icons\main.ico, , 1
menu, tray, nostandard
menu, tray, tip, Logging Active
menu, tray, add, View Log, view
menu, tray, add, Delete Log, delete
menu, tray, add, About, about
menu, tray, add
menu, tray, add, Disable, suspend
menu, tray, add
menu, tray, add, Exit, exit

settimer, mem, 1200000, 0

blank=
endkey=,{enter}{tab}{LControl}{RControl}{LAlt}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause}
match=.,?,!

;MM Input in windows containing these strings will not be logged
windowblacklist=onenote,excel
loop
{
	key=
	emptymem()
	
characters.
	WinGetActiveTitle, wintitle
	if wintitle not contains %windowblacklist%
	{
		input, text, i m v *, %endkey%, %match%
	
		if errorlevel=Match
		{
			key=%blank%
		}
		
		else if errorlevel=NewInput
		{
			key={Click}
		}
		
		else
		{
			stringtrimleft, key, errorlevel, 7
			key={%key%}
		}
		
		key=%key%
		text=%text%
		
		StringLen, length, text
		if length > 2
		{
			WinGetActiveTitle, wintitle
			
			if wintitle not contains %windowblacklist%
			{
				ifnotequal wintitle, %wintitleold%
				{
					fileappend, `n%wintitle%`n, log.txt
					wintitleold = %wintitle%
				}
				
				stringreplace, text, text, , %blank%
				time=%a_dd%/%a_mm%/%a_yyyy% %a_hour%:%a_min%:%a_sec%
				fileappend, %time%%A_Tab%%text%%A_Tab%%key%`n, log.txt
			}
		}
	}
}

;MM Terminate input when mouse is used:
~LButton::
~RButton::
~MButton::
Input
return

write:
{
	time=%a_dd%/%a_mm%/%a_yyyy% %a_hour%:%a_min%:%a_sec%
	fileappend, %time% - %content%`n, log.txt
	emptymem()
}
return

view:
{
	fileinstall, log.txt, log.txt, 0
	runwait, log.txt
	emptymem()
}
return

delete:
{
	ifexist, log.txt
	{
		msgbox, 33, Confirm Delete, Delete log?

		ifmsgbox, ok
		{
			filerecycle, log.txt
			msgbox, 64, Log Deleted, The log file has been sent to the Recycle Bin., 5
			emptymem()
			return
		}
		else
		{
			emptymem()
			return
		}
	}

	ifnotexist, log.txt
	{
		msgbox, 64, Cannot Delete Log, Cannot delete log file because it does not exist., 5
		emptymem()
		return
	}
}
return

about:
{
	fileinstall, readme.txt, readme.txt, 0
	runwait, readme.txt
	emptymem()
}
return

suspend:
{
	if a_issuspended = 0
	{
		menu, tray, tip, Logging Suspended
		menu, tray, rename, Disable, Enable
		menu, tray, icon, icons\suspend.ico, , 1
		ToolTip, Logging Suspended, 2000, 750
		suspend, on
		pause, on
		emptymem()
	}
	else
	{
		menu, tray, tip, Logging Active
		suspend, off
		pause, off
		ToolTip
		menu, tray, rename, Enable, Disable
		menu, tray, icon, icons\main.ico, , 1
		emptymem()
	}
}
return

exit:
{
	exitapp
}
return

mem:
{
	emptymem()
}
return

emptymem()
{
	return, dllcall("psapi.dll\EmptyWorkingSet", "UInt", -1)
}

Ultimately, my plan is to turn the key-logger into a universal command-execution tool: Once all input is registered, it should be easy to look for keywords and execute commands in response (e.g., want to be able to type some search query and then the keyword for "google", to jump from any window to the browser...etc). But I don't have time to implement that at the moment.

Maybe, it would also be smart to implement some sort of parsing of the input text to take corrections made with backspace into account...i've realised that I get most of what I write wrong the first time!

Anyway, thanks again for providing the code.

dmg
  • Members
  • 2346 posts
  • Last active: Yesterday, 04:30 AM
  • Joined: 19 Nov 2010

Ultimately, my plan is to turn the key-logger into a universal command-execution tool: Once all input is registered, it should be easy to look for keywords and execute commands in response (e.g., want to be able to type some search query and then the keyword for "google", to jump from any window to the browser...etc). But I don't have time to implement that at the moment.

Maybe, it would also be smart to implement some sort of parsing of the input text to take corrections made with backspace into account...i've realised that I get most of what I write wrong the first time!

Anyway, thanks again for providing the code.

Interesting. Thank you for posting your changes. At one point I had considered adding the current window to the log but I had not thought of having an exclusion list. Very nice!

You say you want a text based command execution system? Have you seen this app?:

<!-- m -->http://sector-seven....ware/controlpad<!-- m -->

It is also written in AHk but the source is not available.

I tried to write a simplified version when I was first learning AHk but I did not get very far. I will try again eventually.

Very glad I could be of assistance. :D

Cruncher1
  • Members
  • 104 posts
  • Last active: Oct 16 2014 10:09 PM
  • Joined: 21 Feb 2012

Since the original request was for an "efficient" keylogger... Well, not sure I should post these, but what the hey. Look, I am no hacker, but I like a good challenge and one day I challenged myself to make the shortest keylogger possible.So, I have pasted it below. BTW I also do use "spyware" on employee computers. All employees are notified that their computers have monitoring software for the purpose of diagnosing problems and preventing misuse. So, no one is spyed on secretly. They know that the office computers are monitored. 

 

The first one is just 4 lines long and works quite well but has limited functionality:

Loop {  ;  Smallest keylogger I can come up with. Key strokes are saved to key.log, opens in notepad.
	Input, key, V T5,
	FileAppend, %key%, key.log
}

 

 

This version has just 9 lines of code but adds the page title and the time of page viewing which adds context to the captured text. It also works quite well:

Loop {                                              ; Keylogger that also records page title and time.
  Input, k , V T5
  FormatTime, t ,, MM-dd-yyyy  hh:mm:ss tt
  WinGetActiveTitle , pt
  pttk = `n`n`n****************`n%pt%`n%t%`n`n%k%   ;    Defines variable pttk: page title, time, keys logged
  k:=pt!=pt2 ? pttk :k                              ;    Sets value of k to either pttk or k. 
  FileAppend, %k% , key.log
  pt2 := pt
}

 

I would like to also capture the actual URL, but do not know how to do that. 

I would also like to capture screenshots but doing so is more complicated than it might initially appear.

From what I have seen there is no way using AHK alone to save screenshots discreetly in the background. I wish that there was a way to just use a Send {PrintScreen} and then save the value of ClipboardAll. Even if not as an image file initially. But as a value that could be sent back to the clipboard later and then pasted into a 3rd party program for viewing. Is this possible?



Linear Spoon
  • Members
  • 780 posts
  • Last active: Today, 10:45 PM
  • Joined: 29 Oct 2011

@drrchrds, taking screenshots in the background is very possible.

 

Get gdip.ahk from here.

#include gdip.ahk
pToken := Gdip_Startup()
SetTimer,CaptureScreen, 5000  ;5000ms = every 5 seconds it will capture the screen, configure as needed.
OnExit, shutdown
return

CaptureScreen:
  pBitmap := Gdip_BitmapFromScreen()
  ;Save the screenshot to the current directory with the current date and time as the default filename
  ;You can just create a screenshots folder in an obscure directory to save to and look at later.
  Gdip_SaveBitmapToFile(pBitmap, A_MM "-" A_DD "-" A_YYYY " " A_Hour "." A_Min "." A_Sec ".png")
  Gdip_DisposeImage(pBitmap)
return

shutdown:
  Gdip_Shutdown(pToken)
  Exitapp
return

 

Edit: My submission for keylogger with the fewest lines...

Not very readable code but 3 lines, captures most printable characters as well as space and enter =/

Loop, 94
  hotkey, % (A_Index > 33 && A_Index < 60 ? "~+" : "~") chr(A_Index + 31), ~Enter
~Enter::FileAppend, % (A_ThisHotkey = "~Enter" ? "`n" : SubStr(A_ThisHotkey, 0)), key.log

Double edit: Just found out this thread is years old >.>



Cruncher1
  • Members
  • 104 posts
  • Last active: Oct 16 2014 10:09 PM
  • Joined: 21 Feb 2012

@Linear Spoon Thanks, I am going to check that out (Gdip). happy.png

 

Interesting results from a test of the keyloggers, check this out. Now, I use a lot of hotkeys for medical records and this is the basis for this comparison. Using the following hotkeys:

::pr::The patient reports

::lbp::low back pain

::radg::radiating into the

::lle::left lower extremity

::r::on the right

 

When I type the following:  "pr lbp radg lle r."

This is what your code captures: "prlbpradgller"

This is what my code captured: "pThe patient reports llow back pain rradiating into the lleft lower extremity ron the right."

 

Yours gets the actual typed chars minus the spaces, mine gets the first char of the hotkey followed by the hotkey result.

It is interesting that they differ so much.



Cruncher1
  • Members
  • 104 posts
  • Last active: Oct 16 2014 10:09 PM
  • Joined: 21 Feb 2012

@Linear Spoon  Thanks for pointing me to Gdip.ahk That works! Very coo! cool.png 
At first the script wouldn't run (or wouldn't keep running).
I added:
 
 

#Persistent 
 

 
at line 1 and that did the trick.



bob92132
  • Members
  • 1 posts
  • Last active: Apr 28 2013 07:27 AM
  • Joined: 20 Mar 2013

Great script. Thanks.



DrightJKayorent
  • Members
  • 1 posts
  • Last active: Apr 12 2013 11:49 AM
  • Joined: 05 Apr 2013

This topic has been a great help to me. When I was looking around for keyloggers I kept running into child monitoring software, malware, and a general opinion that there isn't any reputable use for a keylogger.


From this topic I've been able to start creating a script to record which keys I press the most during a game of Starcraft 2 in order to fine-tune my hotkey setup.

 

I've set it up as a hotstring that responds to the opening pleasantries at the beginning of a game, and ends when I declare gg.

::gl hf::
loop 
{
	FileAppend, `n, key.log
	Input, key, V B, {enter}
	if key = gg
	{
		FileAppend, `n***End of Game***, key.log
		return
	}
	FileAppend, %key%, key.log
} 

But now I need to figure out how to count the keys pressed, and perhaps also how to record combinations with ctrl, alt, and shift.



DataLife
  • Members
  • 993 posts
  • Last active: Yesterday, 09:30 PM
  • Joined: 27 Apr 2008

I would like to also capture the actual URL, but do not know how to do that.

Thanks to Sean, code found here http://www.autohotke...gh-dde-message/
;functions by Sean from http://www.autohotkey.com/board/topic/17633-retrieve-addressbar-of-firefox-through-dde-message/
;retrieve URL in iexplore, firefox and opera - 

;Chrome uses ControlGetText

^space::
URL = 
WinGetClass,class, A

If (Class = "Chrome_WidgetWin_0" or Class = "Chrome_WidgetWin_1")
 {
  WinGetTitle, title, A
  ControlGetText, url, Chrome_OmniboxView1, %title%
  MsgBox % URL
  return
 }

if Class = IEFrame
 sServer := "Iexplore"
 
If Class =  OperaWindowClass 
 sServer := "Opera"   
 
If ( Class = "MozillaUIWindowClass" or Class = "MozillaWindowClass" ) 
 sServer := "FireFox"

gosub GetURL  ;used for IE, Opera and Firefox
 
MsgBox % URL
return


;Seans code below
GetURL: 
sTopic  := "WWW_GetWindowInfo"
sItem   := "0xFFFFFFFF"
idInst  := DdeInitialize()
hServer := DdeCreateStringHandle(idInst, sServer)
hTopic  := DdeCreateStringHandle(idInst, sTopic )
hItem   := DdeCreateStringHandle(idInst, sItem  )
hConv := DdeConnect(idInst, hServer, hTopic)
hData := DdeClientTransaction(0x20B0, hConv, hItem)   ; XTYP_REQUEST
sData := DdeAccessData(hData)
DdeFreeStringHandle(idInst, hServer)
DdeFreeStringHandle(idInst, hTopic )
DdeFreeStringHandle(idInst, hItem  )
DdeUnaccessData(hData)
DdeFreeDataHandle(hData)
DdeDisconnect(hConv)
DdeUninitialize(idInst)
Loop,	Parse,	sData, CSV
If	A_Index = 1
 URL	:= A_LoopField
return
DdeInitialize(pCallback = 0, nFlags = 0){
   DllCall("DdeInitialize", "UintP", idInst, "Uint", pCallback, "Uint", nFlags, "Uint", 0)
   Return idInst
}
DdeUninitialize(idInst){
   Return DllCall("DdeUninitialize", "Uint", idInst)
}
DdeConnect(idInst, hServer, hTopic, pCC = 0){
   Return DllCall("DdeConnect", "Uint", idInst, "Uint", hServer, "Uint", hTopic, "Uint", pCC)
}
DdeDisconnect(hConv){
   Return DllCall("DdeDisconnect", "Uint", hConv)
}
DdeAccessData(hData){
   Return DllCall("DdeAccessData", "Uint", hData, "Uint", 0, "str")
}
DdeUnaccessData(hData){
   Return DllCall("DdeUnaccessData", "Uint", hData)
}
DdeFreeDataHandle(hData){
   Return DllCall("DdeFreeDataHandle", "Uint", hData)
}
DdeCreateStringHandle(idInst, sString, nCodePage = 1004){    
   Return DllCall("DdeCreateStringHandle", "Uint", idInst, "Uint", &sString, "int", nCodePage)
}
DdeFreeStringHandle(idInst, hString){
   Return DllCall("DdeFreeStringHandle", "Uint", idInst, "Uint", hString)
}
DdeClientTransaction(nType, hConv, hItem, sData = "", nFormat = 1, nTimeOut = 10000){
   Return DllCall("DdeClientTransaction", "Uint", sData = "" ? 0 : &sData, "Uint", sData = "" ? 0 : StrLen(sData)+1, "Uint", hConv, "Uint", hItem, "Uint", nFormat, "Uint", nType, "Uint", nTimeOut, "UintP", nResult)
}


millerbell
  • Members
  • 1 posts
  • Last active: Nov 13 2013 09:00 AM
  • Joined: 12 Nov 2013

A software keylogger would probably record keystrokes from an O/S soft keyboard like Microsoft, depending on where exactly it hooks into the operating system.


Edited by Seidenweber, 15 November 2013 - 09:48 AM.
inappropriate quote deleted