├── SyscallTest ├── dllinj.gif └── SyscallTests.ps1 ├── LICENSE ├── README.md └── NtCreateThreadEx.ps1 /SyscallTest/dllinj.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Souhardya/Catharsis/HEAD/SyscallTest/dllinj.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | "THE BEER-WARE LICENSE" (Revision 42): 2 | 3 | As long as you retain this notice you can do whatever you want with this 4 | stuff. If we meet some day, and you think this stuff is worth it, you can 5 | buy us a beer in return. 6 | 7 | This project is distributed in the hope that it will be useful, but WITHOUT 8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9 | FITNESS FOR A PARTICULAR PURPOSE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Catharsis (Work in progress) 2 | Raw syscall implementations with Powershell 3 | 4 | 5 | ### Brief 6 | 7 | This project mainly focuses on using syscalls for calling NT-functions instead of directly calling them 8 | 9 | To use the examples please implement the syscall number correctly according to your Windows distribution and also take note of the architecture 10 | 11 | 12 | 13 | ![Dll Injector Demo](SyscallTest/dllinj.gif) 14 | 15 | 16 | #### References 17 | 18 | 19 | https://undocumented.ntinternals.net/ 20 | 21 | https://j00ru.vexillium.org/syscalls/nt/64/ 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SyscallTest/SyscallTests.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | NtSuspend Process syscall test 4 | Author: Souhardya Sardar 5 | #> 6 | 7 | $ProcessID = 1234 #ProcessId to suspend 8 | 9 | function Get-DelegateType 10 | { 11 | Param 12 | ( 13 | [OutputType([Type])] 14 | 15 | [Parameter( Position = 0)] 16 | [Type[]] 17 | $Parameters = (New-Object Type[](0)), 18 | 19 | [Parameter( Position = 1 )] 20 | [Type] 21 | $ReturnType = [Void] 22 | ) 23 | 24 | $Domain = [AppDomain]::CurrentDomain 25 | $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 26 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 27 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 28 | $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 29 | $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) 30 | $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') 31 | $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) 32 | $MethodBuilder.SetImplementationFlags('Runtime, Managed') 33 | 34 | Write-Output $TypeBuilder.CreateType() 35 | } 36 | 37 | function Get-ProcAddress 38 | { 39 | Param 40 | ( 41 | 42 | [OutputType([IntPtr])] 43 | 44 | [Parameter( Position = 0, Mandatory = $True )] 45 | [String] 46 | $Module, 47 | 48 | [Parameter( Position = 1, Mandatory = $True )] 49 | [String] 50 | $Procedure 51 | ) 52 | 53 | # Get a reference to System.dll in the GAC 54 | $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | 55 | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } 56 | $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') 57 | # Get a reference to the GetModuleHandle and GetProcAddress methods 58 | $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') 59 | $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress', [reflection.bindingflags] "Public,Static", $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null); 60 | # Get a handle to the module specified 61 | $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) 62 | $tmpPtr = New-Object IntPtr 63 | $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) 64 | 65 | # Return the address of the function 66 | Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) 67 | } 68 | 69 | 70 | $openaddr = Get-ProcAddress kernel32.dll OpenProcess 71 | $openDelgate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) 72 | $openProc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($openaddr, $openDelgate) 73 | $proc = $openProc.Invoke(0x00000800, $false, $ProcessID) #change pid here 74 | 75 | 76 | $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc 77 | $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) 78 | $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) 79 | 80 | 81 | #Winver : Windows Version 1803 82 | [Byte[]] $ntsuspendstub = @(0x49, 0x89, 0xCA, 0xB8, 0xB3, 0x01, 0x00, 0x00, 0x0F, 0x05, 0xC3) 83 | #0: 49 89 ca mov %rcx,%r10 84 | #3: b8 b3 01 00 00 mov $0x1b3,%eax 85 | #8: 0f 05 syscall 86 | #a: c3 retq 87 | 88 | $suspendDelegate = Get-DelegateType @([IntPtr]) ([UInt32]) 89 | $shellcodeBuf = $VirtualAlloc.Invoke([System.IntPtr]::Zero, $ntsuspendstub.Length, 0x3000, 0x40) 90 | [System.Runtime.InteropServices.Marshal]::Copy($ntsuspendstub, 0, $shellcodeBuf, $ntsuspendstub.Length) 91 | $sysdelgate = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($shellcodeBuf, $suspendDelegate) 92 | $sysdelgate.DynamicInvoke($proc) 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /NtCreateThreadEx.ps1: -------------------------------------------------------------------------------- 1 | function NtCreateThreadEx() 2 | { 3 | <# 4 | .SYNOPSIS 5 | Dll Injection using NtCreateThreadEx 6 | Author: Souhardya Sardar 7 | .PARAMETER DllPath 8 | The dllname to be used. 9 | .PARAMETER ProcessID 10 | The process Id of the process 11 | .EXAMPLE 12 | PS>Import-Module .\NtCreateThreadEx.ps1 13 | NtCreateThreadEx -DllPath FullPathToDll -ProcessID 123 14 | #> 15 | 16 | [CmdletBinding()] Param ( 17 | [Parameter(Position = 0, Mandatory = $True)] 18 | [String] 19 | $ProcessID, 20 | 21 | [Parameter(Position = 1, Mandatory = $True)] 22 | [String] 23 | $DllPath 24 | ) 25 | 26 | [Byte[]]$dllBuf = [System.Text.Encoding]::Default.GetBytes($DllPath) 27 | 28 | 29 | #Winver : Windows Version 1803 x64 30 | [Byte[]] $NtCreateThreadExStub = @(0x49, 0x89, 0xCA, 0xB8, 0xBB, 0x00, 0x00, 0x00, 0x0F, 0x05, 0xC3) 31 | #0: 49 89 ca mov %rcx,%r10 32 | #3: b8 bb 00 00 00 mov $0xbb,%eax 33 | #8: 0f 05 syscall 34 | #a: c3 retq 35 | 36 | function Local:Get-DelegateType 37 | { 38 | Param 39 | ( 40 | [OutputType([Type])] 41 | 42 | [Parameter( Position = 0)] 43 | [Type[]] 44 | $Parameters = (New-Object Type[](0)), 45 | 46 | [Parameter( Position = 1 )] 47 | [Type] 48 | $ReturnType = [Void] 49 | ) 50 | 51 | $Domain = [AppDomain]::CurrentDomain 52 | $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 53 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 54 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 55 | $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 56 | $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) 57 | $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') 58 | $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) 59 | $MethodBuilder.SetImplementationFlags('Runtime, Managed') 60 | 61 | Write-Output $TypeBuilder.CreateType() 62 | } 63 | 64 | function Local:Get-ProcAddress 65 | { 66 | Param 67 | ( 68 | 69 | [OutputType([IntPtr])] 70 | 71 | [Parameter( Position = 0, Mandatory = $True )] 72 | [String] 73 | $Module, 74 | 75 | [Parameter( Position = 1, Mandatory = $True )] 76 | [String] 77 | $Procedure 78 | ) 79 | 80 | # Get a reference to System.dll in the GAC 81 | $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | 82 | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } 83 | $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') 84 | # Get a reference to the GetModuleHandle and GetProcAddress methods 85 | $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') 86 | $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress', [reflection.bindingflags] "Public,Static", $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null); 87 | # Get a handle to the module specified 88 | $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) 89 | $tmpPtr = New-Object IntPtr 90 | $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) 91 | 92 | # Return the address of the function 93 | Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) 94 | } 95 | 96 | 97 | 98 | 99 | $openaddr = Get-ProcAddress kernel32.dll OpenProcess 100 | $openDelgate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) 101 | $openProc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($openaddr, $openDelgate) 102 | $prochandle = $openProc.Invoke(0x001F0FFF, $false, $ProcessID) 103 | if($prochandle -eq '0') 104 | { 105 | Throw "[!] Cannot open a handle to the process: $ProcessID" 106 | } 107 | 108 | 109 | 110 | $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx 111 | $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) 112 | $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) 113 | $remotememoryaddress = $VirtualAllocEx.Invoke($prochandle, [System.IntPtr]::Zero, $DllPath.Length+1 , 0x3000, 0x40) # Reserve|Commit, RWX 114 | if($remotememoryaddress -eq '0') 115 | { 116 | Throw "[!]Cannot allocate enough memory: $ProcessID" 117 | } 118 | 119 | 120 | $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory 121 | $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [IntPtr]) ([Bool]) 122 | $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) 123 | if(!$WriteProcessMemory.Invoke($prochandle, $remotememoryaddress, $dllBuf , [Uint32]$DllPath.Length+1 , [IntPtr]::Zero)) 124 | { 125 | Throw "[!] Cannot write in remote process: $ProcessID" 126 | } 127 | 128 | 129 | $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc 130 | $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) 131 | $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) 132 | 133 | $LoadLibraryAAddr = Get-ProcAddress kernel32.dll LoadLibraryA 134 | 135 | 136 | $NtCreateThreadDelgate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [bool], [Uint32], [Uint32], [Uint32], [IntPtr]) ([Uint32]) 137 | $shellcodeBuf = $VirtualAlloc.Invoke([System.IntPtr]::Zero, $NtCreateThreadExStub.Length, 0x3000, 0x40) 138 | [System.Runtime.InteropServices.Marshal]::Copy($NtCreateThreadExStub, 0, $shellcodeBuf, $NtCreateThreadExStub.Length) 139 | $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($shellcodeBuf, $NtCreateThreadDelgate) 140 | 141 | 142 | $hRemoteThread = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(8) #would work 143 | $NtCreateThreadEx.DynamicInvoke($hRemoteThread, [Uint32]0x1FFFFF, [IntPtr]::Zero, $prochandle, $LoadLibraryAAddr, $remotememoryaddress, $false, [UInt32]::Zero, [UInt32]::Zero, [UInt32]::Zero, [IntPtr]::Zero) 144 | 145 | 146 | } 147 | --------------------------------------------------------------------------------