Click here to Skip to main content
Click here to Skip to main content

How to make keyloggers life difficult

, 20 Jan 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
This secure textbox deceptive keyloggers

Introduction  

If you usually typing a password in a desktop application, it may be that a keylogger spies out your secrets. This is obviously not good. Screen keyboards might be a good solution, but again, there could be a screen capture program which watches effortlessly your passwords. Furthermore, screen keyboards are relative unhandily.

The following article presents a relatively simple principle, which prevents the keylogger to write down passwords entered. Basically, the used system is surprisingly easy and can therefore be transferred to other programming / operating systems / platforms, although under a small limitation.

Background 

The first question is: How can a program hide keystrokes? Perhaps there are some difficult ways to do this, but most probable this is not possible. We create an assumption: Entered characters necessarily mean the keylogger sees them. And that's what we use against the keylogger.

The second question is: How can a program generate keystrokes? This is normally possible. For example, we use in C# the class SendKeys, which provides methods for sending keystrokes. By the way, there can be the mentioned limitation because a website has not the authorization to produce keystrokes.

The third question is: How can we combine these two statements? At every time when the user types a character, the program generates some keytrokes more. The keylogger write down all characters both from user and program, but only the user and the program know the entire password. Unauthorized third parties see only letter salad and they can not decrypt the main password.

The fourth question is: Is this main system 100 % secure? Surprisingly and unfortunately no. The prinziple has many weak points, but there are also many solutions to close these gaps. I advise every developer to think about it before they add this concept to their code. Let me explain you the vulnerabilities and the solutions:

  1. Creating random keystrokes after every character allows attackers to reproduce the typed password. Therefore the program must create identical keystrokes. Then again the produced keystrokes should not be identical for all passwords. In summary, we need a algorithm, which produces for every character always the same keystrokes. In addition to this, the length of the generated keystrokes should vary.

  2. For all that, an attacker can create a table with all characters and their hash result either by reverse engineering or by testing. Using this table, he can decrypt the password relatively easy. To prevent this, the generated keystrokes should depend on a password identity, such as account name, account number, e-mail or computer specification. Unfortunately, this is only an obstacle, but no blockage for attackers.

Using the code

At first, the create a new component SecureTextBox with some properties:

public class SecureTextBox : TextBox
{
     /// <summary>
     /// Gets the typed password.
     /// </summary>
     public string Password
     {
          get;
          private set;
     }
 
     /// <summary>
     /// Sets or gets the password ID.
     /// </summary>
     public string ID
     {
          get;
          set;
     }
}

The next step is to implement a constructor for initializing important events:

public SecureTextBox()
{
     this.TextChanged += new EventHandler(SecureTextBox_TextChanged);
     this.KeyDown += new KeyEventHandler(SecureTextBox_KeyDown);
     this.KeyUp += new KeyEventHandler(SecureTextBox_KeyUp);
}    

The methods SecureTextBox_KeyDown and SecureTextBox_KeyUp should ensure that no key is pressed, otherwise characters are inserted incorrectly or even not.  The boolean variable IsTriggering declares if the user entered a character while he is holding another key.

private int KeysPressed = 0;
private bool IsTriggering = false;
 
void SecureTextBox_KeyDown(object sender, KeyEventArgs e)
{
     KeysPressed++;
}
 
void SecureTextBox_KeyUp(object sender, KeyEventArgs e)
{
     KeysPressed--;
     if (KeysPressed == 0 & IsTriggering)
          this.SecureTextBox_TextChanged(null, null);
}

Now consider the random functions. For this example, I used Random combined with a given seed. The seed is created from the ID and the last entered character from user.

Random _NextSaltLength, _NextSaltChar;
// TODO: Extend the CharContent with all important characters!
string CharContent = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
 
private int NextSaltLength(bool CreateNew)
{
	// TODO: Replace this code with your own function!
	if (CreateNew)
		_NextSaltLength = new Random(ID.GetHashCode() - Password[Password.Length - 1].GetHashCode());
	return _NextSaltLength.Next(1, 4);
}
 
private string NextSaltChar(bool CreateNew)
{
	// TODO: Replace this code with your own function!
	if (CreateNew)
		_NextSaltChar = new Random(ID.GetHashCode() + Password[Password.Length - 1].GetHashCode());
	return CharContent[_NextSaltChar.Next(CharContent.Length)].ToString();
}

Finally, we can create the main method which manage the generation of the keystrokes:

private int RemainingSaltChars = 0;
private int LastTextLength = 0;
 
void SecureTextBox_TextChanged(object sender, EventArgs e)
{
     if (KeysPressed > 0)
     {
          IsTriggering = true;
          return;
     }
     IsTriggering = false;
     if (LastTextLength < this.TextLength)
     {
          LastTextLength = this.TextLength;
          if (RemainingSaltChars > 0)
          {
               if (RemainingSaltChars > 1)
                    SendKeys.Send(this.NextSaltChar(false));
               RemainingSaltChars--;
          }
          else
          {
               this.Password += this.Text[this.TextLength - 1];
               RemainingSaltChars = this.NextSaltLength(true);
               SendKeys.Send(this.NextSaltChar(true));
          }
     }
     else
     {
          this.ResetText();
          LastTextLength = 0;
     }
}

Here is a short description of the implementation: If no keys are pressed and the user entered a character in the TextBox, the char is saved, the quantity of the next generated characters are randomly calculated and the first character is send through SendKeys.Send(). Now the program is in a complicated loop and generates the specified keystrokes. This state is interrupted, if RemainingSaltChars is zero. Just as a footnote, if the user presses Delete or Backspace, the text will be reset because otherwise this would mix up the algorithm.

public override void ResetText()
{
     base.ResetText();
     this.Password = String.Empty;
}

Points of Interest 

Originally I have this prinziple from a software, which polls for a password at startup. At first I wondered why more masked characters apperared in the textbox than typed until I figured it out. I implemented my thoughts and experimented with my code using a keylogger. I was very surprised about the effectivity. Then I wanted to analyse how good the other application works while using a keylogger. But the program produced no keystrokes. Unbelievable! I found this very amusing.

In the introduction I said that this prinziple could not be implemented by a website. A solution for this would be a extra Add-On for the browser, which could take on this task. 

History 

Published on 19 January 2013.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

M. Hudak
Student Kaiserslautern University of Technology
Germany Germany
No Biography provided

Comments and Discussions

 
QuestionWouldn't be simpler... PinmemberCristian Amarie26-Dec-13 10:13 
GeneralMy vote of 5 PinmemberMonjurul Habib2-Feb-13 8:04 
GeneralMy vote of 5 PinmemberSergio Andrés Gutiérrez Rojas29-Jan-13 17:14 
GeneralMy vote of 5 PinmemberEdo Tzumer29-Jan-13 4:23 
GeneralMy vote of 5 PinmvpMichael Haephrati מיכאל האפרתי24-Jan-13 8:42 
AnswerRe: My vote of 5 PinmemberMichael Hudak (Aregeion)24-Jan-13 12:43 
GeneralRe: My vote of 5 PinmvpMichael Haephrati מיכאל האפרתי25-Jan-13 0:41 
AnswerRe: My vote of 5 PinmemberMichael Hudak (Aregeion)25-Jan-13 9:28 
Questionclose...i think PinmemberMember 322138523-Jan-13 6:00 
AnswerRe: close...i think PinmemberMichael Hudak (Aregeion)24-Jan-13 12:33 
GeneralMy vote of 5 PinmemberJH6421-Jan-13 12:33 
QuestionDon't think it will work PinmemberHaBiX20-Jan-13 22:42 
AnswerRe: Don't think it will work PinmemberMichael Hudak (Aregeion)22-Jan-13 0:54 
GeneralRe: Don't think it will work [modified] PinmemberHaBiX22-Jan-13 1:06 
GeneralMy vote of 5 PinmemberFaithcz20-Jan-13 22:39 
QuestionInteresting: need a keylogger now PinmemberBruno Tabbia20-Jan-13 21:48 
AnswerRe: Interesting: need a keylogger now PinmvpEddy Vluggen9-Feb-13 2:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 20 Jan 2013
Article Copyright 2013 by M. Hudak
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid