There are several methods to implement Keyboard capturing and many issues to be aware of, so besides the historical value that some people may find in this product, I hope to bring some technical value as well... I have also brought to you other sources for Keyboard Capturing.
Introduction
This article is the fourth in a series about the Target Eye Monitoring System, developed from 2000 till 2010. The first article was about Target Eye's Auto Update mechanism, and how it is capable of checking for updates, downloading them when there are, installing them and running them instead of the old version currently running, all of the above, with no end-user intervention. The second article was about the Target Eye's screen capturing mechanism, and how compact JPG files are created combining a reasonable image quality and a small footprint. The third article was about the Shopping List mechanism. The fifth article is about the Cover Story mechanism and the sixth one explains how files are hidden and when, along with exposing how to reveal these hidden files. Well, the next significant component of the Target Eye system is Keyboard Capturing. There are several methods to implement it and many issues to be aware of, so besides the historical value that some people may find in this product, I hope to bring some technical value as well...
While writing this article, I also tried to bring you other sources for Keyboard Capturing, among them articles at Code Project and external sources.
What is Target Eye
In the image above, the Target Eye US patent application
Target Eye Monitoring System, which I have developed in the year of 2000, was one of the first surveillance and monitoring tools for capturing activity of remote computers. Unlike hacking tools, Target Eye is a monitoring tool which was built as a product aimed to be used by Law Enforcement agencies, and specifically by people with no actual knowledge of hacking. The product is focused on the information, how to collect it, structure it, summarize and prepare it to be used as part of an ongoing investigation. Target Eye was built to run months and years without crashing, which is a very important requirement from such products as user being investigated is not supposed to do anything the entire time the software runs on his / her computer. This requirement creates a need to implement functionalities such as installation upgrades and reporting without any end user intervention whatsoever, so stability is a key factor here. QA of such products requires thousands of testing hours and to be honest, bugs always occurs and to avoid most of them, it takes time, so only a mature product which was used for years can be trusted for that matter.
Target Eye Monitoring System has several building blocks:
- Target Eye Secret Agent - the covert part of the product that runs on the monitored computer
- Target Eye Operator - the authority that operates the Secret Agent (for example: a Law Enforcement agency)
- A Mission - a request to perform an action. There are many possible actions (for example, capturing the screen, as described in another article of mine or searching and finding files, as described in this article).
- Target Eye Compiler - The tool that is used by the Target Eye Operator to customize a Secret Agent for performing specific tasks.
Keyboard Capturing takes place by the Target Eye Secret Agent and is configured by the Target Eye Compiler.
What is Keyboard Capturing
According to Oxford Dictionary, Key Logging (as know as Keyboard Capturing) is "a computer program that records every keystroke made by a computer user, especially in order to gain fraudulent access to passwords and other confidential information".
Needless to mention, there are many lawful reasons to record keystrokes (especially if you record and monitor your own PC...), from Parental Control to uses by Law Enforcement, military and Intelligence agencies against cyber crime and terror. Target Eye was invented mostly for these markets. Further, there is a difference between products that record keystrokes, referred to as "Key Loggers" and surveillance products such as Target Eye which record keystrokes among other things.
When I write a new article, I check first what was already written about the topic I'm writing about, so in this case, there is an article named Basic Keystroke Mining by Alexander Kent, which brings code sample in C#. Another article about Mouse and Keyboard Hook, by Adam Roderick J which brings the traditional approach of using Global Hooks which requires a DLL (source code is in C++ and the sample application is not common to key loggers because it works like a recorder - player system. You record your events - mouse and keyboard activity and then it plays it back to you). To the best of my knowledge, the first demonstration of such idea was introduced by a friend of mine, a programmer who is now famous in the film industry, Oren Peli who programmed such an application when he was 16 years old and had an Amiga computer... Another interesting article I have read is about Keyboard Hooking in Kernel by Günter Bergmann. You may also find the following article: Background Applications listening for Keyboard Activity with source code in VB.
Additional two sources I have found are: Kid Logger and SpyTool.
Kid Logger is a commercial product (a Parental Control system) by Rohos, a start-up company in Moldova which collects data about user activity on Windows based computers along with Mac or mobile phones, and creates detailed time tracking and productivity reports available online, I am mentioning this product because full source code is included. To get the source code, you need to download the trial version and install it. You will find the source code folder inside the installation folder. The source code is not the most up to date version but contains a perfect example of using Global Hooks in a DLL. Rohos, whom I work with for many years, has done amazing things in many areas related to Information Security, and obviously their source code, even though it is outdated is a state of the art when it comes to coding standards.
SpyTool is a spyware which can not only capture the keyboard but also capture the web cam if one is attached to the monitored computer. It was developed by a college of mine, Gregory Stein, who has a full time job at Intel, and therefore has very little time to update his project. Greg was kind enough to give me permission to check the possibility of adopting some parts of his source code, especially the web cam capturing code, to be used in the current and future versions of Target Eye.
In the image above - how Keyboard Capturing is turned on and off (2), and how Hot Words are defined (2)
How Target Eye Has Evolved
I started developing Target Eye on 2000 starting with the visual (UI) part which will be described in future articles. This part was used to display data (mostly screen capturing images) from multiple sources in a "Video Wall" style layout. The first POC was developed under Visual Basic 6.0 and here is a sample from the very first version. GetText
returns the title text of a given window.
Function GetText(hWnd) As String
Dim GetString As String
Dim TrimSpace$
Dim GetTrim
GetTrim = Sendmessagebynum(hWnd, 14, 0&, 0&)
TrimSpace$ = Space$(GetTrim)
GetString = SendMessageByString(hWnd, 13, GetTrim + 1, TrimSpace$)
GetText = TrimSpace$
End Function
Few weeks later came the C++ version (Visual C++ 6.0)...
In the image above, Target Eye 2000 display 6 "agents" monitored at the same time
I then started working on the "Secret Agent" part which was the actual engine that was transplant in the monitored computer and collected the information. Part of this agent was capturing the keyboard. From checking earlier versions, JournalLogProc has changed over the years. In 2000-2004, it handled text using ToAscii() and saved each character typed immediately to the data file, which caused slowing down the monitored PC.
BYTE kbuf[256];
WORD ch;
int chcount;
GetKeyboardState(kbuf);
chcount=ToAscii(vKey,nScan,kbuf,&ch,0);
if(chcount>0)
{
int IsHotWord=CheckHotWords(ch);
WriteFile(g_hCapFile,&ch,chcount,&dwBytes,NULL);
The 2005 was a bit different as ToAsciiEx() was used. Data was first captured to a buffer to enhance speed. GetKeyboardLayout() was used as well.
DWORD dwCount;
char svBuffer[256];
int vKey,nScan;
DWORD idT = GetWindowThreadProcessId(destWnd, NULL);
KL = GetKeyboardLayout(idT);
GetKeyboardState(kbuf);
chcount=ToAsciiEx(vKey,nScan,kbuf,&ch,0,KL);
if(chcount>0)
{
AddText(ch,FALSE);
...
Apart of these evolves, Target Eye kept providing Keyboard Capturing without using an external DLL.
Handling Special Keys
A proper Keyboard Capturing engine should handle special keys and convert such keys or combination of keys into a user friendly data file entry. A good example would be reflecting deleted text. When text is deleted, the actual key captured will be either BACKSPACE or DEL. Target Eye displays these as [XXX] and [---], so if the data file shows:
"I have corrected my mistac[XXX]ke" it means that while typing the "c" was deleted and replaced with "k".
Other special keys are:
- VK_SPACE (or the SPACE key) - In more recent versions, Target Eye saved captured data into a buffer and purged the buffer into the data file whenever the SPACE or ENTER keys were captured.
- RETURN / ENTER - These special keys are handled the same and converted to a new line ( '\n').
- Arrow keys - These can be helpful in understanding where exactly editing takes place (along with an indication of where the cursor is placed using the mouse).
- Function Keys - These are converted into their name. F1 will appear as "F1" and so on....
Here is part of the source code where some of the special keys are interpreted:
case VK_TAB:
api_lpsz = _T("[TAB]");
break;
case VK_LEFT:
api_lpsz = _T("[LEFT]");
break;
case VK_RIGHT:
api_lpsz = _T("[RIGHT]");
break;
case VK_UP:
api_lpsz = _T("[UP]");
break;
case VK_DOWN:
api_lpsz = _T("[DOWN]");
break;
case VK_PRIOR:
api_lpsz = _T("[PAGE UP]");
break;
case VK_NEXT:
api_lpsz = _T("[PAGE DOWN]");
break;
case VK_END:
api_lpsz = _T("[END]");
break;
case VK_HOME:
api_lpsz = _T("[HOME]");
break;
Handling Hot Words
Another functionality which is usually part of Keyboard Capturing is handling Hot words. Hot words are phrases that are targeted to alert and cause another action when they are typed. For example, the operator of Target Eye might request that whenever the phrases "murder" or "kill" will be typed, a screenshot will be taken and an email alert will be sent to the operator.
First, the array of Hot Words is initialized. In the commercial product, the list of Hot Words is obtained from the encrypted segment of the application which is attached to it by the Compiler. In this code sample, we just add 2 entries:
void InitHotWords()
{
HotWords.RemoveAll();
HotWords.Add("kill");
HotWords.Add("murder");
}
Next, there is the part where captured text is analyzed and checked against this list.
CheckHotWords()
returns the index of the hot word found in the current buffer, or -1
if none.
inline int CheckHotWords()
{
int i,result=-1;
for(i=0;i<=HotWords.GetUpperBound();i++)
{
int Len=HotWords[i].GetLength();
if(CaptureString.GetLength()>=Len)
{
if(CaptureString.Right(Len)==HotWords[i])
{
result=i;
break;
}
}
}
return(result);
}
The method used by Target Eye ensures that no matter where and how the hot word is typed, it is captured. For that matter, you can go to Google, type "ki", then switch to Notepad and type "ll" and the word "kill" will be captured. Of course, that can be changed and customized.
Methods Used for Keyboard Capturing
There are several requirements from Keyboard Capturing. Typing consumes CPU, especially when typing fast. A background thread which is used to capture the text being typed consumes even more CPU which can cause slowing down the PC being monitored and slowing the response of the typing, which can be annoying to the user being monitored. Another possible problem could be keys getting lost. When it comes to a tool used for Law Enforcement and forensic purposes, losing even one keystroke is not something you can live with. Further, the data file which is created and updated along the monitoring session must be up to date and accurate at any given moment, even if for example, while typing, the PC is suddenly turned off (for example, a power failure). Keyboard Capturing must reflect the current active application and window and relate each key stroke to the correct window and application. Screenshots, which I have described in this article, should also relate to any text typed while this screen was captured.
There are several methods that can be used to record the keyboard:
SetWindowsHookEx
The common method uses is a Global Hook created using a separate DLL. See this link.
HHOOK WINAPI SetWindowsHookEx(
_In_ int idHook,
_In_ HOOKPROC lpfn,
_In_ HINSTANCE hMod,
_In_ DWORD dwThreadId
);
I have encountered several problems with this method, especially when it comes to most recent versions of Windows (i.e., Windows 7) where keystrokes get lost especially when there is high CPU activity.
RegisterRawInputDevices
A method which is less known - using Raw Input directly from the keyboard.
BOOL WINAPI RegisterRawInputDevices(
_In_ PCRAWINPUTDEVICE pRawInputDevices,
_In_ UINT uiNumDevices,
_In_ UINT cbSize
;
WH_JOURNALRECORD
I have chosen to use Journal hooks for Target Eye, and very few changes were made since the first release of Target Eye (on 2000) and later releases of the product. Journal Hooks are system wide hooks used mostly for recording and playing back keyboard and mouse events, however for the purpose of a surveillance system, we only need the recording mechanism, which leads to a data file where all text is stored.
That approach worked excellent these days (at least until 2007) but wouldn't work today without some adjustments which are required as since Windows Vista, WH_JOURNALRECORD
type of hook requires Admin privileges, code signing along with other limitations and requirements. See this link.
Handling Date and Time Stamps
When you build a monitoring product that is supposed to be operated in various countries and remote controlled in others, you must take into consideration the time zone and not only the local time.
Target Eye used CTime class (available at MFC , ATL and WTL).
GetGmtTm() is used to get the universal date and time which will be identical regardless of the time zone.
In addition, the actual time zone can be displayed in the data file (Target Eye does that only for screen capturing files).
Handling International Characters
Text is captured regardless of the active application, and for that matter, you can just hit the keyboard while no application is active and the text will yet be fully recorded. Target Eye, like other similar products, keeps track of the active window at the time text was typed, which helps the operator determine the context of the text captured.
Many key logging systems works fast and efficient but when you type another language, you still get the same Latin text in the captured text file. That is because from the point of view of the hooking mechanism, the captured keys are the same regardless of the selected language. Many PC users have a multiple (usually two) language system, which they switch using ALT+SHIFT. A good monitoring system should be able to detect the active language (keymap) selected and translate the key code of the pressed key into the correct character. For example, when a Hebrew-English system is used, pressing the "A" key on the keyboard, if English selected, "a" or "A" should be captured (cased on whether SHIFT is pressed), and when Hebrew is selected, the character "ש" should be captured. The way to do so is by calling ToUnicodeEx()
right after obtaining the current language selected which is done by calling GetKeyboardState()
.
GetKeyboardState()
copies the status of the 256 virtual keys to the specified buffer.
BOOL WINAPI GetKeyboardState(_Out_ PBYTE lpKeyState);
ToUnicodeEx()
translates the specified virtual-key code and keyboard state to the corresponding Unicode character or characters.
int WINAPI ToUnicodeEx(
_In_ UINT wVirtKey,
_In_ UINT wScanCode,
_In_ const BYTE *lpKeyState,
_Out_ LPWSTR pwszBuff,
_In_ int cchBuff,
_In_ UINT wFlags,
_In_opt_ HKL dwhkl
);
and the entire code for handling multiple languages is:
DWORD dwMsg = p->scanCode << 16;
BYTE keyState[256];
GetKeyboardState(keyState);
key[0]=key[1]=key[2]=0;
ToUnicodeEx(p->vkCode, p->scanCode, keyState, key, 1, p->flags,layout);
Handling Data Files
When it comes to handling the data file generated and updated by Target Eye, unlike screen capturing which generate a separate file per each screen shot, Keyboard Capturing text is kept in a continuous file which is updated constantly. This file can become huge, and usually is reset after being sent to the operator, either via Email or by uploading it to an FTP server.
Here is how the data file is created or updated (in case it already exists):
void CreateKBCFile()
{
HANDLE g_hCapFile;
CTime theTime=CTime::GetCurrentTime();
CString TempFileName;
DWORD dwBytes;
g_hCapFile=CreateFile(POC_LOGFILENAME,GENERIC_WRITE,FILE_SHARE_WRITE,
NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,NULL);
if(g_hCapFile==INVALID_HANDLE_VALUE)
{
TRACE("Can't open log file %s\n",POC_LOGFILENAME);
return;
}
SetFilePointer(g_hCapFile,0,NULL,FILE_END);
if(!(WriteFile(g_hCapFile,CaptureString.Mid(12),
CaptureString.GetLength()-12,&dwBytes,NULL)))
{
TRACE("KB Capturing: Can't write to log file %s\n",POC_LOGFILENAME);
}
CloseHandle(g_hCapFile);
return;
}
A Typical Data File
A typical data file is shown in the example below (the various parts were highlighted):
The are several parts that are part of the data file:
- Active window
- Text typed
- Time / Date stamp
- Deletion of text
- File name that is used to indicate operation case ID, subject ID, etc.
Then, when such file is analyzed, it is sometimes quite easy to determine user names, passwords, logon details, etc. In fact, if you self monitor your own PC, which is what I did while preparing this article, you can find out lost passwords in case you need them...
Summary
This article was written to provide another angle of the Target Eye system, and in the case of Keyboard Capturing, there was no point providing the source code used by the older versions of this product for the reasons I mentioned.
History
- 12th June, 2014: Initial version
Michael Haephrati , CodeProject MVP 2013
©2000-2010 Target Eye LTD (UK)
All materials contained on this article are protected by International copyright law and may not be used, reproduced, distributed, transmitted, displayed, published or broadcast without the prior written permission given by Target Eye LTD (UK). You may not alter or remove any trademark, copyright or other notice from copies of the content.