SLAE x86 - Assignment 0x1
Bind TCP Shellcode
Objectives
- Create a shell bind tcp shellcode
- Binds to a port
- Execs shell on incoming connection
- Port number should be easily configurable
Structure
Using bind shell from msfvenom, the needed syscalls can be visualize with the help of libemu's sctest
and dot tool
:
Generated using:
msfvenom --arch x86 --platform linux -p linux/x86/shell_bind_tcp -f raw | sctest -vvv -Ss 10000 -G bind_tcp_shellcode.dot
dot bind_tcp_shellcode.dot -T png -o bind_tcp_shellcode.png
Creating the NASM Code
Syscalls and other values
- Below are the needed syscalls and respective opcodes from
/usr/include/asm/unistd_32.h
SOCKET equ 0x167
BIND equ 0x169
LISTEN equ 0x16b
ACCEPT equ 0x16c
DUP equ 0x3f
EXECVE equ 0xb
- These are declared under
section .text
for better reading of the nasm code together with other constants:
; settings
PORT equ 0xd204 ; default 1234
; argument constants
AF_INET equ 0x2
SOCK_STREAM equ 0x1
Socket(2)
- This will create an endpoint for communication and returns a file descriptor that refers the endpoint. The usage are detailed in: https://man7.org/linux/man-pages/man2/socket.2.html
- Synopsis:
socket(int domain, int type, int protocol)
- Syscall arguments:
- ebx: AF_INET = 2
- ecx: SOCK_STREAM = 1
- edx: IPPROTO_IP = 6
NASM Code:
|
|
Bind(2)
- This will assign an address to the socket referred to by the file descriptor returned from Socket(2). The usage are detailed in: https://man7.org/linux/man-pages/man2/bind.2.html
- Synopsis:
bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
- Syscall arguments:
- ebx: sockfd = eax(returned from previous syscall)
- ecx: sockaddr = { AF_INET; PORT; 0x0; 0x0 }
- AF_INET = 2
- PORT = 1234
- edx: addrlen = 16
NASM Code:
|
|
Listen(2)
- This will mark the sockfd accept incoming connection requests using Accept(2). The usage are detailed in: https://man7.org/linux/man-pages/man2/listen.2.html
- Synopsis:
listen(int sockfd, int backlog)
- Syscall arguments:
- ebx: sockfd = edi(same sockfd used by last syscall)
- ecx: backlog = 0x0(does not need to grow the sockfd for pending connections)
NASM Code:
|
|
Accept4(2)
- This will extract the first connection request for listening socket from Listen(2) then creates a new connected socket, and returns a new file descriptor referring to that socket. The usage are detailed in: https://linux.die.net/man/2/accept4
- Synopsis:
accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
- Syscall arguments:
- ebx: sockfd = edi(same sockfd used by last syscall)
- ecx: sockaddr = 0x0
- edx: addrlen = 0x0
- esi: flags = 0x0
NASM Code:
|
|
Dup(2)
- This will allocate the file descriptors, virtual handles used to access certain process I/O operations and to simulate remote user’s input and display to the terminal. The usage are detailed in: https://man7.org/linux/man-pages/man2/dup.2.html
- Synopsis:
dup(int oldfd, int newfd, int flags)
- Syscall arguments:
- ebx: sockfd = eax(returned sockfd from Accept4(2))
- ecx: sockaddr = stdin, stdout, and stderr
- stdin = 0x0
- stdout = 0x1
- stderr = 0x2
NASM Code:
|
|
Execve(2)
- This will execute the
/bin/sh
program on the remote machine The usage are detailed in: https://man7.org/linux/man-pages/man2/execve.2.html - Synopsis:
execve(const char *pathname, char *const argv[], char *const envp[])
- Syscall arguments:
- ebx: pathname = ‘bin//sh’ address in stack
- ecx: argv = 0x0
- ecx: envp = 0x0
NASM Code:
|
|
Final NASM Code
|
|
Dynamic Configuration
Using a simple Ruby script below, the PORT
number can be dynamically assigned:
|
|
Script usage and shellcode testing
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 - 1558