-[ BFi - version française ]-------------------------------------------------- BFi est une e-zine écritte par la communauté hacker italienne. Les codes sources complets et la version originale en italien sont disponible içi: http://bfi.freaknet.org/dev/BFi11-dev-13.tar.gz http://www.s0ftpj.org/bfi/dev/BFi11-dev-13.tar.gz Version française traduite par tleil4X ------------------------------------------------------------------------------ ============================================================================== -------------------[ BFi11-dev - fichier 13 - 02/11/2002 ]-------------------- ============================================================================== -[ DiSCLAiMER ]--------------------------------------------------------------- Tout le matériel contenu dans BFi a but esclusivement informatif et éducatif. Les auteurs de BFi ne se chargent d'aucune responsabilité pour des éventuel dommages à choses ainsi que à personnes, dus à l'emploi de code, programmes, informations, techniques contenus dans la revue. BFi est un libre et autonome moyen d'éxpression; comme nous auteurs nous sommes libres d'écrire BFi, tu est libre de continuer dans ta lecture ou alors de t'arreter içi. Par conséquent, si tu te sens outragé par les thèmes traités et/ou par la façon dont ils sont traités, * interrompt immédiatement ta lecture et éfface ces fichiers de ton ordinateur *. En continuant, toi lecteur, tu te prends toute la responsabilité de l'emploi que tu feras des indications contenus dans BFi. Il est interdit de publier BFi sur les newsgroup et la diffusion de *parties* de la revue: vous pouvez distribuer BFi tout entier et dans ça forme originale. ------------------------------------------------------------------------------ -[ HACKiNG ]------------------------------------------------------------------ ---[ PTRACE(2) F0R FUN AND PR0FiT -----[ xenion Author: xenion ptrace(2) for fun and profit ------------------------------------------------------------------------ 0x0 ptrace(2), first steps 0x1 Reading and writing child memory 0x2 read(2)/write(2) reference 0x3 Logging the contents of inbound/outbound telnet/ssh sessions 0x4 Injecting commands on a ptraced telnet/ssh session 0x5 Bindshell, the last stage of delirium 0x6 References 0x0 ptrace(2), first steps ------------------------------------------------------------------------ ptrace(2) est une syscall qui offre fonctionnalité de debugging/tracing: Elle permet d'observer et de contoller l'exécution d'un processus, d'en modifier et d'en lire l'image dans la mémoire vive et les registres. Voici le prototipe de la fonction à l'userspace: long int ptrace(enum __ptrace_request request, pid_t pid, void * addr, void * data) J'évite d'expliquer ce qui est déjà clairement dit dans les pages de Man, sur la fin je ferai des traduction approximatives et inutiles :) Par contre, on va voir comment utilizer la ptrace(2) avec un example bref: nous voulons voir quelle syscall sont employé en runtime par n'importe quel exécutable: . Nous sommes maintenant capables de: - accroché un processus - garder le contrôle en survelliant les log - des syscall appelé - de l'état des registres 0x1 Reading and writing child memory ------------------------------------------------------------------------ Grâce à des demandes comme PTRACE_PEEKTEXT et PTRACE_POKETEXT nous pouvons respectivement lire ou écrire une parole (4 byte sur un systéme Linux à 32-bit). C'est peut pratique... voyons comment implémenter deux fonctions qui nous permettes les mêmes opérations sur un buffer plus grand: #define WORD_SIZE 4 // 'x' est approché par excès à un multiple de 'y' #define COUNT_OK(x, y) (##x % ##y != 0 ? ##x+(##y - (##x % ##y)) : ##x) // 'x' est approché par défaut à un multiple de 'y' #define LEN_OK(x, y) (##x-(##x % ##y)) /* Ça lit du processus le 'pid' de 'src' 'count' byte, pour aller ensuite écrire sur le buffer pointé par 'dest', un buffer long 'len' byte. */ int memread(pid_t pid, unsigned char *dest, unsigned char *src, long count, long len) { long off; long res; if (count < 0 || len < 0) return (-1); count = COUNT_OK(count, WORD_SIZE); len = LEN_OK(len, WORD_SIZE); if (len < count) return -1; for (off = 0; off < count; off += WORD_SIZE) { res = ptrace(PTRACE_PEEKTEXT, pid, src + off, 0); if (errno > 0) return -1; else memcpy(dest + off, &res, WORD_SIZE); } return count; } /* Ça écrit sur le processus 'pid' dans 'src' 'count' byte, lit du buffer pointé par 'dest, un buffer long 'len' byte. */ int memwrite(pid_t pid, unsigned char *dest, unsigned char *src, long count, long len) { long off; long res; if (count < 0 || len < 0) return (-1); count = COUNT_OK(count, WORD_SIZE); len = LEN_OK(len, WORD_SIZE); if (len < count) return -1; for (off = 0; off < count; off += WORD_SIZE) { memcpy(&res, src + off, WORD_SIZE); if (ptrace(PTRACE_POKETEXT, pid, dest + off, res) < 0) return -1; } return count; } 0x2 read(2)/write(2) reference ------------------------------------------------------------------------ On doit nettement savoir les paramétres et les 'return value' de ces deux syscall, qui nous servirons aprés: read(2): read up to count bytes from file fd into buffer *buf: arg: eax 3 ebx file descriptor ecx ptr to input buffer edx buffer size, max. count of bytes to receive return: eax no. of bytes received errors: eax EAGAIN, EBADF, EFAULT, EINTR, EINVAL, EIO, EISDIR source: fs/read_write.c write(2): write (up to) count bytes of data from *buf to file fd: arg: eax 4 ebx file descriptor ecx ptr to output buffer edx count of bytes to send return: eax no. of sent bytes (if POSIX conforming f.s.) errors: eax EAGAIN, EBADF, EFAULT, EINTR, EINVAL, EIO, ENOSPC, EPIPE source: fs/read_write.c 0x3 Logging the contents of inbound/outbound telnet/ssh sessions ------------------------------------------------------------------------ Avec ptrace(2) nous pouvons nous accrocher a n'importe quel processus existant (si nous somme root), nous pouvons ainsi voir ce qui passe par la write(2) ou bien la read(2) sans devoir utilizer un module en kernelspace: ceçi nous permet d'éxaminer les log des sessions de telnet ou ssh! sert exactement à ça... fixé quelques bug présents dans la premiére distribution publique. 0x4 Injecting commands on a ptraced telnet/ssh session ------------------------------------------------------------------------ Pourquoi se limiter à lire les log? Nous pouvont modifier ainsi qu'ajouter des donnés dans les buffer de I/O, et ça nous permet indirectement d'exécuter du côde arbitraire sur le systéme... voyons comment: Quand l'usager exécute une quelque opération sur la shell, il introduit une séquence de caractère suivit par '\n', séquence qui vient lit par le client ssh/telnet par un fd. Si la séssion est linebuffered il suffira une seule read(2), une à chaque caractère si elle est unbuffered.. il suffira donc d'attendre une read(2) de un certain fd qui ait comme dernier byte lit '\n' après lequel nous insérerons nos commandes. Retournons à la read(2): comme nous savons, un signal de SIGTRAP est envoyé avant d'éxecuter la syscall et un'autre juste après.. les bytes lu serons disponibles seulement au deuxiéme stop. Nous irons alors écrire en partent par la position ecx+eax, en se souvenent de fixer eax. La dimension des buffer de I/O: | client | length | +-----------------+--------+ | OpenSSH_3.2.3p1 | 16384 | +-----------------+--------+ | telnet | 8192 | +-----------------+--------+ L'espace est limité, mais suffisant pour n'importe quoi, comme aon va voir après :) Puis, ajourné le registre eax il ne faut rien d'autre si non laisser le contrôle au client qui arrengera le reste. Nous devons cependant faire face à un problème: il pourrai y étre l'echo des caractères, ça complique les choses.. il pourrai en effet retourner fragmenté en plusieur write(2). La seule solution "rapide" consiste à cacher n'importe quel output à l'utilisateur jusqu'à quand nous sommes pas sur d'avoir cacher l'echo (et l'output) de nos commandes. ..pour cacher l'output il faudra ne rien écrire, tout en mettant edx à 0 au premier stop, et en se souvenant de fixer eax au deuxième avec la vielle valeur d'edx. Tout ceci dans , have fun! 0x5 Bindshell, the last stage of delirium ------------------------------------------------------------------------ A l'aide de quelque echo -ne redirecté on peut télésauver n'importe quel type de fichier.. même un petit exécutable de 268 o, suffisant pour une bindshell:) Le texte source se trouve dans , voyons comment le compiler et optimiser ça dimension: #compilons le.. gate$ gcc -Wall -s -nostartfiles -nostdlib bind.s -o bind #combien de byte? gate$ wc -c bind 496 bind #ok, enlevons tout ce qui n'est pas éssentiel à l'exécutable gate$ sstrip bind #combien de byte? gate$ wc -c bind 268 bind gate$ Maintenant que nous avons nôtre petit ELF, il nous restera qu'à le transformer dans un seul echo avec : 0x6 References ------------------------------------------------------------------------ [1] Man page of ptrace(2) [2] strace(2) sources [3] http://www.phrack.org/phrack/59/p59-0x0c.txt [4] http://www.linuxgazette.com/issue81/sandeep.html [5] http://linuxassembly.org [6] http://www.lxhp.in-berlin.de/lhpsyscal.html [7] http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html ------------------------------------------------------------------------ EOF -[ WEB ]---------------------------------------------------------------------- http://www.bfi.cx http://bfi.freaknet.org http://www.s0ftpj.org/bfi/ -[ E-MAiL ]------------------------------------------------------------------- bfi@s0ftpj.org -[ PGP ]---------------------------------------------------------------------- -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.3i mQENAzZsSu8AAAEIAM5FrActPz32W1AbxJ/LDG7bB371rhB1aG7/AzDEkXH67nni DrMRyP+0u4tCTGizOGof0s/YDm2hH4jh+aGO9djJBzIEU8p1dvY677uw6oVCM374 nkjbyDjvBeuJVooKo+J6yGZuUq7jVgBKsR0uklfe5/0TUXsVva9b1pBfxqynK5OO lQGJuq7g79jTSTqsa0mbFFxAlFq5GZmL+fnZdjWGI0c2pZrz+Tdj2+Ic3dl9dWax iuy9Bp4Bq+H0mpCmnvwTMVdS2c+99s9unfnbzGvO6KqiwZzIWU9pQeK+v7W6vPa3 TbGHwwH4iaAWQH0mm7v+KdpMzqUPucgvfugfx+kABRO0FUJmSTk4IDxiZmk5OEB1 c2EubmV0PokBFQMFEDZsSu+5yC9+6B/H6QEBb6EIAMRP40T7m4Y1arNkj5enWC/b a6M4oog42xr9UHOd8X2cOBBNB8qTe+dhBIhPX0fDJnnCr0WuEQ+eiw0YHJKyk5ql GB/UkRH/hR4IpA0alUUjEYjTqL5HZmW9phMA9xiTAqoNhmXaIh7MVaYmcxhXwoOo WYOaYoklxxA5qZxOwIXRxlmaN48SKsQuPrSrHwTdKxd+qB7QDU83h8nQ7dB4MAse gDvMUdspekxAX8XBikXLvVuT0ai4xd8o8owWNR5fQAsNkbrdjOUWrOs0dbFx2K9J l3XqeKl3XEgLvVG8JyhloKl65h9rUyw6Ek5hvb5ROuyS/lAGGWvxv2YJrN8ABLo= =o7CG -----END PGP PUBLIC KEY BLOCK----- ============================================================================== -----------------------------------[ EOF ]------------------------------------ ==============================================================================