Skip navigation.

devloop :: blog

Blog sur la sécurité informatique, la programmation, Linux et le Web

Posts tagged with "tunneling"

Pseudo-terminaux, portes dérobées, telnet, tunneling et Marie-Antoinette

, , , ...

J'ai toujours trouvé aux réseaux un petit côté "magique", l'idée de pouvoir éditer un fichier qui se trouve à des milliers de kilomêtres de chez moi ma toujours parue fabuleuse :wizard: C'est peut-être pour cela que j'ai toujours admiré les TTYs (ouah c'est beau un terminal, surtout avec du ncurse p: ) et ils sont restés longtemps pour moi un grand mystère, au moins jusqu'à ces derniers jours, moment fatidique où j'ai décidé de me lancer dans l'épineuse aventure des TTY/PTY.

Un terminal, kezako ?
Sous Linux, un terminal est avant tout un périphérique. On en trouve dans /dev (pty*, tty*) et dans /dev/pts (terminaux esclaves).
Le terminal se charge de faire le lien entre le clavier et le programme qui recevra les commandes. Il transforme la frappe de certaines touches du clavier en un "code d'échappement" que le programme saura comment interpréter.
Ces codes d'échappements sont définis dans des standards comme le VT100.

L'utilité d'un terminal par rappel à une ligne de commande "brute" est bien évidemment de pouvoir exécuter des programmes interactifs comme Vim, Emacs, top, nethack et bien d'autres... c'est pour dire à quel point ils sont devenus indispensables ;-)
Même si la plupart des backdoors existantes n'offrent pas le support des ttys, quelques-unes le proposent avec plus ou moins de réussite.

Canonique or not canonique ?
Dans la plupart des cas, elles sont inutilisables telles quelles car il n'y a pas de client associé. L'utilisation de netcat pour s'y connecter ne permet pas de profiter du terminal côté serveur car netcat ne gère pas le tty. Notamment netcat lit les données tappées de façon canonique (attente d'une fin de ligne pour traiter les données) alors qu'un terminal les lit de façon non-canonique : les données sont traitées à chaque frappe du clavier.
Le mode non-canonique est indispensable pour les programmes cités plus tôt (par exemple pouvoir taper simplement q pour quitter top sans avoir à appuyer sur entrée).

Toi comprendre ce que moi dire ?
Vient alors un autre problème : le terminal client et le terminal serveur doivent parler la même langue. Une bonne partie des lnormes existantes sont compatibles car basées sur les codes d'échappement ANSI mais ce n'est pas toujours le cas.
Le standard utilisé est habituellement défini par la variable d'environnement TERM sous le shell.

Deux solutions sont possibles pour faire dialoguer correctement le client et le serveur :
  • Utiliser un client et un serveur utilisant le même langage
  • Utiliser un protocole permettant au client et au serveur de se mettre d'accord sur le type de terminal à utiliser

Implémentations
La première solution est celle utilisée dans sorshell.c. Le client et le serveur se voient fixer la variable d'environnement TERM à "vt100". Le client est configuré en mode non-canonique est sans échos (voir plus loin).

L'autre solution a fait son apparition il y a maintenant longtemps avec le protocole telnet. Par ce protocole, le client et le serveur négocient le type de terminal ainsi que d'autres règles de transmission.
L'implémentation de telnet dans un logiciel ne facilitant pas les choses, certains ont préférés ruser comme pour Tiny Shell qui se contente de l'envoi du type de terminal utilisé.
Il existe tout de même un code en perl où toute la couche telnet est utilisée :smile:

Terminal client
Un dehors du mode canonique (ou non), le client ne doit pas interpréter certains signaux comme un Ctrl+C afin de les traduire pour les transmettre au serveur.
Les deux parties doivent aussi se mettre d'accord sur qui renvoie les données. Quand on frappe sur une touche depuis le client, on s'attend à ce qu'elle apparaisse à l'écran. Soit elle s'affiche au moment où on appuie sur la touche, soit quand le serveur nous la renvoit (il a fait un "écho"), soit les deux en même temps (dans ce cas là, le caractère s'affiche en double).
Le serveur renvoyant généralement plus de données que le client n'en envoit, le client est habituellement passé en non-écho et les caractères s'affichent alors lorsque le serveur les renvoit au client (le client ne renvoie pas les données du serveur).
Dans une session telnet, la taille de la fenêtre de terminal sera aussi négociée (généralement 80x25 par défaut).

Le rôle du terminal client consiste à lire les touches tapées sur l'entrée standard pour les restransmettre vers le serveur, le tout avec les caractéristiques citées précédemment.
Sa programmation est simple. Il faut d'abord récupérer une structure termios définissant le modèle du terminal actuel à l'aide de la fonction tcgetattr(), modifier cette structure selon nos souhaits pour enfin mettre à jour le terminal avec les nouveaux paramêtres (fonction tcsetattr()).

Le code utilisé en C dans sorshell est le suivant :
struct termios deftt,tt;

/* terminal init */
tcgetattr(0, &deftt); /* récupére les préférences du terminal */
tt = deftt; /* copie */
tt.c_oflag &= ~(OPOST);
tt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); /* pas d'écho, ne recoit pas les signaux, mode non-canonique... */
tt.c_iflag &= ~(ICRNL); /* transforme les CR en NL */
tt.c_cc[VMIN] = 1; /* lit caractère après caractère */
tt.c_cc[VTIME] = 0; /* pas de délai de lecture */
tcsetattr(0, TCSADRAIN, &tt); /* mettre à jour le terminal */
...
tcsetattr(0, TCSADRAIN, &deftt); /* restauration */

stty
Sous Linux, la commande stty permet de modifier les paramêtres d'un terminal. On peut alors utiliser un client "brut" en modifiant le terminal courant, ce qui donnerait un script dans ce style :
stty -icanon -echo -isig
netcat serveur 9999 -v
stty icanon echo isig
clear

Un shell avec terminal pour pas un rond
Petite astuce trouvée sur pentestmonkey : on peut utiliser la richesse des API Python pour associer facilement un shell avec un pseudo-terminal.
La commande pour lancer un serveur fonctionnant avec le script client précédent sera la suivante :
netcat -e "python -c 'import pty; pty.spawn(\"/bin/sh\")'" -v -l -p 9999

Terminal serveur
Du côté du serveur, le terminal doit fonctionner en sens inverse : lire les codes d'échappement reçus et les transformer en signaux, déplacement de curseur etc.
La programmation du serveur est plus compliquée et se base sur l'utilisation d'un pseudo-terminal dont le fonctionnement est proche des pipe.
On a alors un pseudo-terminal (pty) maître sur lequel on écrit les données reçues par le réseau et un pty esclave (pts) qui reçoit les données et les filtre avant de les renvoyer au shell.

La programmation suivra la procédure suivante :
  1. Ouverture du périphérique /dev/ptmx qui va chercher un pty maître disponible et retourner son descripteur de fichier
  2. Appel à la fonction grantpt() pour modifier les droits d'accès au terminal esclave (le pts)
  3. Utilisation de la fonction unlockpt() pour dévérouiller le pts
  4. ptsname() permettra ensuite de récupérer le nom du pts
  5. Ouverture du pseudo-terminal esclave

Pour terminer, le programme fait un fork(), le processus fils redirige ses entrées/sorties vers le pts avant de lancer un shell et le processus père gère les entrées réseau.
C'est ce que fait sorshell.c (mis à part qu'il le fait en bas niveau).

Tunneling à travers Jabber (GTalk)
En Python, le nombre d'étapes a été fortement réduites et côté serveur, il suffit d'appeller les fonctions openpty() et fork() du module pty.
Pour illustrer tout cela j'ai développé un petit programme permettant de faire passer un shell/tty à travers une session XMPP. Le code se base sur l'utilisation des serveurs GoogleTalk mais peu être facilement modifié. Il utilise la librairie xmpppy
Le protocole XMPP ne permettant pas de faire facilement transiter des données brutes, celles-ci sont envoyées sous leur forme hexadécimale (encodage pour le caractère 'A' sera '61'). Quelques temporisations ont dû être rajoutées car le serveur GTalk n'hésite pas à couper la communication si les envois successifs sont trop rapprochés.

Ca fonctionne plutôt bien, si ce n'est que c'est assez lent. J'ai réussi à éditer avec VIM, naviguer dans une page de manuel etc. Par contre il faut faire attention avec les commandes qui envoient continuellement des données à l'écran (c'est le cas de top) qui risquent de faire bloquer le programme dans une boucle (avec un top -n <nombre d'affichages> ça passe).

Télécharger jabbertunnel.tar.bz2

Références :
www.iakovlev.org
sorshell.c
emse.fr : Saisies de données au clavier
win.py (Terminal Emulator)
Python Library Reference : termios
Python Library Reference : pty

Derniers logiciels testés

, , , ...

Je vais vous parler brièvement des derniers logiciels que j'ai installé sous Linux.

J'ai voulu essayer KTouch, un logiciel de dactylographie, pour apprendre à tapper avec tous mes doigts... Après plusieurs essais j'ai toujours pas compris comment ça marche... On a une image d'un clavier avec des touches de différentes couleurs et une phrase à tapper et retapper le plus vite possible. A part ça je n'ai rien vu qui explique clairement comment placer ses doigts sur le clavier... je cherche toujours...

KID3 est un éditeur de tag pour les fichiers MP3. Il supporte le format ID3v1 et le ID3v2. Très simple d'utilisation et très pratique... surtout que XMMS ne semble gérer qu'un seul format. Il n'y a que l'interface qui n'est pas très belle mais le logiciel marche très bien.

Gqcam est un des logiciels que j'ai testé pour ma webcam. Le seul défaut est que le logiciel a tendance à oublier les préférences que l'on a fixé lors de la dernière utilisation... Donc à chaque lancement il faut activer la correction RBG -> GBR (sinon les images sont bleues) et désactiver l'autoréglage de la luminosité (qui tourne en boucle).
Le logiciel permet de faire des captures au format jpg ou png. L'interface est ultra-simple à utiliser... c'est pour l'instant le logiciel que j'utilise le plus avec la webcam.

Camorama est un autre logiciel pour webcam... Chez moi la définition est plus petite qu'avec Gqcam mais Camorama permet d'appliquer différents effets à l'image tel que le mode noir et blanc, le mode négatif, un flou ou encore les algorithmes de Laplace, Sobel, Wacky... On peut assez facilement se faire une image plus ou moins dans un style matrix ou terminator p:
Mais la petite taille des images générées gache un peu :frown:

Corkscrew est un logiciel de tunneling HTTP. Il utilise la méthode CONNECT du protocole. Pour ceux qui n'y connaissent rien le tunneling est une encapsulation d'un flux de données dans un protocole... à ne pas confondre avec les canaux cachés où on injecte les données dans le protocole lui-même.
Corkscrew prend quatre arguments : ip du proxy, port du proxy, ip de la machine destination et port de la machine destination. Le logiciel marche sous la forme d'un netcat, c'est à dire que ce que l'on tappe dans la console est envoyé sur le réseau... Ca limite donc l'utilisation du logiciel... on aurait préféré une redirection des communications de façon transparente et surtout permettant d'utiliser Corkscrew avec les logiciels standards (clients FTP, IRC etc)
D'ailleurs je vais peut-être coder une petite tool de tunneling HTTP en Python un de ces jours :wink:

Pour terminer j'ai testé deux programmes : Code2HTML et Source-highlight. Ils permettent, à partir d'un fichier source, de générer une belle page HTML avec le code en couleur (coloration syntaxique). Bref deux programmes qui se rendent indispendables si on souhaite publier une étude de code etc. Les deux outils supportent un nombre de langages impréssionnant (allez voir sur leurs sites respectifs) ainsi qu'une plétore d'options pour personnaliser la page HTML générée.

Fin de la transmission :cool: