Skip to main content

Assignment 1b

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: SLAE64-1434

Target Operating System: 64 bit Linux (x86_64 GNU/Linux)

Assignment 1b:

Remove all the nulls from the Bind TCP Shellcode discussed, in a creative way.

GitHub Link: https://github.com/rtaylor777/nasm/blob/master/BindShell1434.nasm

Size = 82 bytes
NULLS = 0

BindShell1434.nasm

Intro

This shellcode, when executed, listens on port 4444 for a connection. Once a client connects to port 4444 a /bin/sh shell is launched and the client can interact with the shell.

In the listing of assembly language sourcecode above the lines 26 to 74 are the networking portion of the code and lines 76 to 92 launch the /bin/sh shell.

For a gentler introduction if this is your first time reading one of my blog posts I recommend  you start out with the post that explains the ExecveStack1434 shellcode:
http://a41l4.blogspot.ca/2017/01/execvestack1434.html

Testing 

Once you have downloaded the BindShell1434.nasm source code from the GitHub link above, you will need to assemble it. Assuming you have the NASM assembler ( http://www.nasm.us/ ):

Assemble:
nasm -felf64 BindShell1434.nasm -o BindShell1434.o

Link:
ld BindShell1434.o -o BindShell1434

Run:
./BindShell1434

If you run netstat (in another terminal) you can see your new service listening on port 4444:
Connecting a client, from a different terminal:
When you exit the client it will close the BindShell1434 as well.

Note:
There is a default delay of one minute before Linux will allow you to bind to the same port again. So if you try to run BindShell1434 again before a minute has passed you will get a Segmentation Fault.

Normally what would happen is the BindShell would have bound to another port because 4444 was not yet permitted to be used by Linux. When this happens an error code is returned in the RAX register, which if I coded my BindShell differently, would not have caused a Segmentation Fault. But I figured since the point is we don't want our BindShell to bind to some alternate random port anyway it might as well assume that it was successful getting port 4444.

To see more about this topic search Google for the text TIME_WAIT.

Socket Programming

A good intro to Socket programming for Linux can be found here:
http://www.linuxhowtos.org/C_C++/socket.htm

The shellcode that we are discussing is acting as a server. You can see the steps required listed on the page I referenced above and they are:
•  Create a socket with the socket() system call
•  Bind the socket to an address using the bind() system call. For a server socket on the Internet, an address consists of a port number on the host machine.
•  Listen for connections with the listen() system call
•  Accept a connection with the accept() system call. This call typically blocks until a client connects with the server.
•  Send and receive data


Although the above discussion is specifically from the perspective of C and C++ programming, the principle is the same for assembly language.

You can see I labeled sections of code in the assembly language listing above to help identify each section as it relates to the steps.

Create a Socket, Step 1

You can find details about the socket() system call on the Linux command line in the man pages:

man socket

From this we see that the function signature looks like this:

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

In assembly language, arguments are usually passed in certain registers and return values are placed in the RAX register.

A value is also placed in the RAX register before making a system call and it is used to indicate what system call it is that we are trying to make.

Registers used for a system call:

RAX - System Call Number
RDI  - First Argument
RSI  - Second Argument
RDX - Third Argument
R10 - Fourth Argument
R8   - Fifth Argument
R9   - Sixth Argument

How do I know what value to put in RAX for what system call? There is a file on my system that lists the system call numbers:

"/usr/include/x86_64-linux-gnu/asm/unistd_64.h"

The next question is what do I put into the registers to represent:

int domain?
int type?
int protocol?

From the man page for socket we are going to use the IPv4 protocol and so the constant we are instructed to use is:

AF_INET

But what number does that represent? I found that information on my system in this file:

"/usr/include/x86_64-linux-gnu/bits/socket.h"

AF_INET maps to PF_INET which has a value of 2.

For the next argument "type" we want to create a TCP connection so we select

SOCK_STREAM

On my system I found that defined in this file:

"/usr/include/x86_64-linux-gnu/bits/socket_type.h"

SOCK_STREAM has a value of 1.

For the 3rd parameter? I noticed this in the man page for socket:

"Normally only a single protocol exists to support a particular socket type within a given protocol family, in which case protocol can be specified as 0."

So for our first system call, namely creating a socket, we have determined the values that we want to put into each register.

RAX = 41
RDI = 2
RSI = 1
RDX = 0

There were only 3 parameters so we can move on to the system call itself. For that we simply use the assembly language command:

syscall


That takes us up to line 37 in our source code listing.

If you are wondering what "cdq" does that stands for convert double word to quad word. Provided the value of EAX is positive, it will zero EAX. Now I mentioned in the ExecveStack1434 discussion that when  you write to a 32 bit register, it will automatically zero the upper 32 bits of the 64 bit register. So, provided that EAX is positive, and we know it is after putting the value 41 into RAX, cdq will ultimately zero RDX.

Bind, Step 2

This step is a little more complicated because we have to create a data structure and pass addresses to it. The socket signature for bind looks like...
man bind
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockfd = socket descriptor ( on Linux it is really using up the same resource as file descriptors ).
The socket descriptor is what was returned from our socket() system call.

Line 39 is moving the returned socket descriptor from RAX to RDI. The RDI register is where it needs to be for the other syscalls that we will be making further along. The command xchg edi,eax is swapping 32 bit values. A signed 32 bit positive number can have over 2 billion values. The socket descriptor even on the busiest server process would have a value well below that so, this instruction is not a risk.

The structure required is 16 bytes in size and we are constructing it on the stack. As we add items to the stack, the stack pointer is moved to lower addresses in memory. When we are done building our structure the stack pointer will point to the bottom end of our structure which is perfect for passing to the system call.

Building the structure in C would look like this:
server.sin_family = AF_INET
server.sin_port = htons(PORT)
server.sin_addr.s_addr = INADDR_ANY
bzero(&server.sin_zero, 8)

Since the last 8 bytes of the structure are zeros (nulls) we can simply push a zeroed register (64 bits is 8 bytes) to the stack. That is the instruction on line 40, RDX is still zero from the previous syscall.

For the lower 8 bytes of our structure, we need to include information about the port that we wish to bind to. Line 41establishes the lower 8 bytes of our structure with the value 2 in the lowest byte. This 2 represents the sin_family which we know from our first system call is AF_INET. The next line moves the hex value 0x5c11 into that 8 byte structure and puts it into the 3rd and 4th byte.

How does 0x5c11 relate to 4444? Well first of all, the value needs to be in the network byte order format which is also known as "big endian". See https://en.wikipedia.org/wiki/Endianness . On top of that, the value is an int and not the text 4444. So it is best to represent it in hex format.

We can use assembly language to figure all this out. Consider these 2 lines of assembly language:

mov eax, 4444 ; move desired port into rax
bswap eax        ; Reverses the byte order of a 32-bit or 64-bit (destination) register. This instruction                          ; is provided for converting little-endian values to big-endian format and vice versa.

While stepping through these instructions in GDB (GNU Debugger) we see:
Then
Lines 43 and 44 move the address of our structure into the RSI register (the 2nd parameter for the syscall).

Line 45 is saving the value "2" to be used in the next syscall (Listen).

On line 46 I am loading the bind system call number 49 into RAX.

We have one argument for our bind call left and that is simply to put the size of our structure (16 bytes) into the 3rd argument, RDX, and we see that in line 47.

Line 48 makes the call to bind our socket to port 4444.

Listen, Step 3

man listen
int listen(int sockfd, int backlog);

RDI still has our sockfd value in it from when we set up the previous bind call.

On Line 50 we are moving the system call number for listen (50) into RAX. Note that this is the instruction that would cause a segmentation fault if the result from the previous system call was an error code. We could have used another byte to ensure that only 50 was in RAX by pushing 50 and popping it into RAX, but we chose to believe that our previous call was successful and expect RAX to be zero before we try moving 50 into AL (the lowest byte of RAX).

On Line 51 we are putting the value 2 into RSI, we pushed 2 onto the stack on line 45 from the Bind section.

Line 52 is our Listen syscall which, depending on the state of RAX either succeeds or segfaults.

Accept, Step 4

man 2 accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

The structure expected by Accept is the same type of structure (sockaddr) that we built for the Bind call. In fact with the Accept call the system call itself is responsible for populating the structure with the values that represent the client who has made the connection to our listening socket. So we just need an empty 16 byte structure, or really any 16 bytes whether it has values in it or not.

It just so happens that the RSP stack pointer is presently pointing to the sockaddr structure that we created for our Bind syscall, and testing shows that reuse of this structure for the Accept syscall does not adversely impact the existing socket on which we are Listening. So we can save a couple more bytes in our code.


Lines 54 and 55 are just setting RSI to point to the sockadde structure on the stack.
Remember that RDI is already set and points to our sockfd value.

Lines 56 puts the value 16 onto the stack. Fortunately the RDX register still had the value 16 in it from when we put it there earlier.

Lines 56 and 57 are moving the pointer to the value 16, which is on the stack, into the RDX register.

Line 59 is putting the system call value for Accept (43) into RAX.

Line 60 makes the Accept syscall.

Something to note at this point is the Accept syscall will "block", meaning that the syscall will not return until a client has made a connection. So our code is paused and waits for the connection before continuing execution.

After the connection from the client has been made, the return value in RAX is a new sockfd value representing the socket connection between us (our process) and the client. Because we intend to close our original socket and thereby stop the Listener and release the binding to port 4444 in the next syscall, we will backup this new sockfd value temporarily to RDX, and that is line 61.

When a process exits (terminates) the system will clean up open file or socket descriptors that are associated with that process. So closing the original socket and releasing the binding on port 4444 and stopping the Listener at this point in our code might only be serving the purpose of providing a little stealth. Perhaps you wish the keep the command shell ( /bin/sh ) open for an extended amount of time and you do not wish to have the port 4444 visible in the listing of listening sockets on the host. In any case we can reduce the size of our shellcode by avoiding the next Close syscall and I will demonstrate that in another shellcode.

Close

man close
int close(int fd);

The one and only parameter, the sockfd value is already in RDI.
Lines 63 and 64 are moving the system call value for Close (3) into RAX.

Since we wish to use the value 3 for the next Dup2 loop we save it on the stack and that is Line 65.

Line 66 makes the syscall and Closes our original socket which was bound to port 4444 and Listening.

Dup2

man dup2
int dup2(int oldfd, int newfd);

On Linux every new process has at least 3 file descriptors automatically opened for it that it can use. These file descriptors are used for input, output, and error output and the file descriptor values are always 0 for input, 1 for output, and 2 for error output.
See: http://www.linuxtechi.com/standard-input-output-error-in-linux/

So what we are doing in this section of code is mapping those standard functions (input, output, error) to use our new socket (sockfd) instead of the default values 0, 1 and 2.

On Line 68 we are putting our backed up sockfd for the client connection, which we had previously put into RDX, into RDI.

On line 69 we are popping the value 3 off of the stack into RSI which we had pushed there earlier on line 65.

Line 70 to 74 is a loop which calls dup2 3 times. For the 3 calls our sockfd is in the first parameter and the values 2, 1, and 0 are in the second parameter.

We have to keep moving the value for the dup2 system call (33) into RAX because the return value from dup2 overwrites it.

On line 71, we are again assuming that the value from a previous system call did not return an error value so we can save a byte by just setting AL, the lowest byte of RAX.

Line 72 decrements the value in RSI, which is why we initialized it to 3 and not 2. The syscall is performed on line 73.

On Line 74 if the zero flag has not been set the execution jumps back to line 70 and repeats.

Execve

If you worked through the ExecveStack1434 Blog post that I posted earlier:
http://a41l4.blogspot.ca/2017/01/execvestack1434.html 
You can probably already work out what is happening starting on Line 78, but I will provide an explanation of the differences here.


Because of the way the dup2 loop was counting down the value of RSI to zero, we already know that RSI is zero. Also, if you were paying attention to the return values of the dup2 system call you would notice that after the last dup2 call the RAX register has a value of 0. So we can save a few bytes by not having to zero them.

For the rest of the code we are setting up a zero terminated string value '/bin//sh' on the stack and moving a pointer to it into RDI. As discused in our ExecveStack1434 blog post, the system will ignore the extra slash in our /bin//sh string and in the mean time we have managed create an 8 byte string that does not contain any NULLS and which fits exactly into the RBX register.

Line 88, cdq is necessary in order to zero RDX. We discussed cdq earlier during our Create a Socket section.

Finally we move the system call value (59) into RAX and make the call to execve.

Now all input, output, and error output for our process (which has been replaced by /bin/sh) are routed to the client. The client can now interact with the /bin/sh shell running on our system, the
system where our shellcode was executed.

Shellcode.c


The Assignment

The Assignmet was "Remove all the nulls from the Bind TCP Shellcode discussed, in a creative way". 

The Bind TCP Shellcode discussed had these properties:
Number of bytes = 185
Number of nulls = 51

In the BindShell1434 shellcode I have reduced these properties to:
Number of bytes = 82
Number of nulls = 0

The objective of the first part of the assignment can be measured by simply counting the remaining NULLS in the bytecode. I believe that the steps that I took to remove the NULLS and reduce the bytecode size to less than 1/2 showed creativity.

Summary

The BindShell1434 shellcode listens on port 4444 for a client connection, and when a client connects it provides a /bin/sh shell for the client to interact with.

If you wish to learn more about assembly language, I highly recommend the "SecurityTube Linux Assembly Expert course and certification."

http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/








Comments

Popular posts from this blog

GIAC GXPN Review – SANS SEC660 (Advanced Penetration Testing, Exploit Writing, and Ethical Hacking)   Intro  SANS is a well respected and premier cyber security training company that employs industry experts as instructors. GIAC is a company that produces testing to validate the skills of security professionals. GIAC exams validate the learning outcomes of the SANS courses. Prerequisites Before attempting this course you should be familiar with penetration testing as this is an advanced course. I would say that you should also be familiar with assembly language and shellcoding. It would be best if you have studied basic stack overflow exploits prior to this course. You will need a basic understanding of programming in C or C++ (preferably both). Scripting using Python would be a useful prerequisite. If you could learn a bit of Ruby scripting it would help for the Metasploit module creation. Be familiar with various routing and networking protocols. Course Coverage This course covers ma

PolySetuidExecve1434

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: SLAE64-1434 Target Operating System : 64 bit Linux (x86_64 GNU/Linux) This blog post is part of Assignment 6: http://a41l4.blogspot.ca/2017/03/assignment-6.html The Original Version: http://shell-storm.org/shellcode/files/shellcode-77.php My Version: GitHub Link : https://github.com/rtaylor777/nasm/blob/master/PolySetuidExecve1434.nasm Published : https://www.exploit-db.com/exploits/41498/ Original Shellcode bytes = 49 My version: Number of bytes = 31 Number of nulls = 0 PolySetuidExecve1434.nasm Intro This shellcode when executed will first setuid(0) and then execute /bin/sh and provide you with a shell. The purpose of calling setuid(0) is, suppose that you have managed to inject this shellcode into an executable that is Set-UID root. I

PolyFlushIPTables1434

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: SLAE64-1434 Target Operating System : 64 bit Linux (x86_64 GNU/Linux) This blog post is part of Assignment 6: http://a41l4.blogspot.ca/2017/03/assignment-6.html The Original Version: http://shell-storm.org/shellcode/files/shellcode-683.php Original size: 50 bytes (don't believe what he says :) My Version: GitHub Link : https://github.com/rtaylor777/nasm/blob/master/PolyFlushIPTables1434.nasm Published : https://www.exploit-db.com/exploits/41503/ My version: Number of bytes = 47 Number of nulls = 0 PolyFlushIPTables1434.nasm  Intro This shellcode basically just executes /sbin/iptables -F without any other parameters. man iptables "-F, --flush [chain]               Flush  the  selected  chain (all the chains in the table if none i