Archive for January, 2015

Assignment 1: Shell bind TCP shellcode


Create a Shell_Bind_TCP shellcode that (a) binds to a port, and (b) executes a shell on incoming connection. The port number should be easily configurable.


In order to work with sockets, we need first to determine the syscall number to use. A look in /usr/include/i386-linux-gnu/asm/unistd_32.h shows the socketcall syscall is number 102 (0x66).

a1p1

 

 

 

The man page for socketcall is presented below:

a1p2

 

So in order to work with sockets, we need to also look into the different functions (accept, bind etc). We can find the valid socket function parameters in /usr/include/linux/net.h file:

a1p3

The man page for the socket function:

a1p4

 

So, the socket function is defined as:
int socket (int domain, int type, int protocol)

The address family values (domain) can be found in /usr/src/linux-headers-3.13.0-37/include/linux/socket.h
a1p5

The socket type values can be found in /usr/src/linux-headers-3.13.0-37/include/linux/net.h
a1p6

 

The protocol values are defined in /usr/include/linux/in.h

a1p7

From all the above we deduce that in order to create a TCP socket we need to pass the following parameters to the socket function:

•    Domain: AF_INET (2)
•    Type: SOCK_STREAM (1)
•    Protocol: TCP(6)

Let’s try to translate all that into assembly instructions. The system call is 0x66 which should be stored into EAX. EBX should contain 1, in order to use the socket function (effectively to create the socket). The parameters to the socket function will be pushed on the stack, in the reverse order (remember stack is LIFO) from what they appear in the function’s definition (so protocol, type, domain) and then moving the value of the ESP register to ECX, prior to making the call.
To better visualize the parameters and calling convention we can use a diagram:a1p8

If the function is successful in creating a socket, the kernel will give us a file descriptor for it, stored into EAX. The following image presents the code for creating the socket:

a1p9

After creating the socket, we need to:
•    Bind it to a port and ip address
•    Make it listen for connections
•    Accept a connection and execute the shell

First the bind. The man page tell us the following:
a1p10

From the above, we can see bind expects 3 parameters. First is the socket file descriptor, then a pointer to the sockaddr structure (containing socket parameters) and then the length of this structure. The length should be 14 bytes for sa_data (port and ip address) 2 for the family, 16 bytes in total. Looking at the ip(7) page (man 7 ip) we can see the definition for the sockaddr structure pointer:
a1p11

The address to bind will be passed through sin_addr:
a1p12

Since, we do not know a priori the ip address of the host that the shellcode will run on, we will need to pass the INADDR_ANY value. This can be found again in /usr/include/linux/in.h file:
a1p13

So the INADDR_ANY is 0. If we try to pass this directly, we will introduce NULL bytes to the shellcode. Therefore we will need to cater for that by pushing a zeroed out register instead of the actual 0x00 value we need. Remember that the sockaddr structure must be 16 bytes long. The following diagram aids in visualizing the various parameters (we will bind on port 31452, 0x7ADC):
a1p14

The tricky part here is the sockaddr structure. For IPv4, this is expected to be 16 bytes long. The values will be laid out as follows:
•    Family (AF_INET):  0x0002
•    Port (31452): 0x7adc
•    IP Address (IPADDR_ANY): 00 00 00 00
•    Zero padding: 00 00 00 00 00 00 00 00

All these must be pushed on the stack in reverse order. There are a lot of NULL bytes in this structure that we need to avoid. We will need to push 12 zeros, then the port, then the 0x02 value as word (2 bytes). To get the zeroes, we can use three pushes of a full register, zeroed out (i.e. ESI). The following instructions accomplish that:
a1p15

After these, the stack holds all the necessary data for the sockaddr structure, and we can store the value of ESP into ECX, to get ready for setting up the stack one more time, for the parameters to the sys_socketcall syscall. The complete  bind() call code is presented below:
a1p16

Having completed the bind, we then need to enable the socket to listen for connections. This is accomplished via the listen() function.
a1p17

Just two parameters for this function, the socket file descriptor, and a value for the backlog, say 15. The parameter visualization is presented below.
a1p18

The code for the listen() then can be written.

a1p19

Finally, we need to accept connections and execute a /bind/sh upon incoming connection. In order to accomplish that, we will need to call the accept() function for the socket, but we will need to communicate with this shell via the socket. This can be done by redirecting the standard input, output and error descriptors of the spawned shell, to our socket. This is valid and characteristic of Unix operating systems, where everything is a file, or as Linus himself said “everything is a stream of bytes” (see http://yarchive.net/comp/linux/everything_is_file.html)

Let’s look at the accept man page:
a1p20

It takes the socket file descriptor, and two pointers that will store the details of the peer socket (effectively, the client’s port and ip address when it connects to us). These two pointers should be initialized to 0. Care should be taken here, to the fact, that accept() will return a new socket file descriptor (for the client socket), which we will need to use in the input/output/error redirection latter on.
a1p21

Here is the parameter diagram:
a1p22

The code for accept() can now be written:
a1p23

We are almost done. We need to do the standard input, output and error redirection to our socket and then finish off with the execve-stack code that will be executed upon connection. Remember that the socket file descriptor we will use, is the one from the previous accept() syscall. For the redirection the sys_dup2 syscall will be used.
a1p24

This is straightforward. We will pass only our socket file descriptor from the accept() call. This value is currently stored in EBX, as shown at the end of the accept() code segment above. Remember that the number representations for the 3 file descriptors are:
•    Standard input: 0
•    Standard output: 1
•    Standard error: 2
We can use a register initialized to 2 and loop until 0 in order to have less instructions in the shellcode. The system call number for dup2() is 63, 0x3F (in unistd_32.h)

a1p25

The following code accomplishes the duplication:
a1p26

The last part is the execve-stack code, which is presented below:
a1p27

We are now ready to compile our assembly code. Compile it, and check if there are any null bytes.
a1p28

Then extract the shellcode and paste it into the C file that will execute it.
For the extraction we can create a simple bash script which executes an objdump and applies some commandlinefu (http://www.commandlinefu.com/commands/view/12151/get-shellcode-of-the-binary-using-objdump, see comment by “arno”):
a1p29

Copy and paste the shellcode into shellcode.c. We will need to be able to change the listening port easily, so we will write it in a single line to ease identification.
a1p30
Compile and execute the code:
a1p31

On a new terminal, execute a netstat to see the listening ports:

a1p32

Our shellcode seems to be listening. We connect to the port using netcat and execute a command or two (commands entered shown with red arrows):

a1p33
Upon pressing Ctrl-C the program terminates and the socket is closed.

We can also see the various system calls of our shellcode, by running it under strace:
a1p34
First we have the socket call, which returns the file descriptor number 3. The bind and listen are successful (observe the file descriptor value in the parameters passed to them). Accept is also successful and returns back the file descriptor 4. This is used for the three dup calls, and finally the execve is executed for /bin//sh.


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


 

, , ,

Leave a comment

Design a site like this with WordPress.com
Get started