Public Release

This commit is contained in:
d3adc0de
2022-12-04 13:31:04 +00:00
commit 84855f84e1
25 changed files with 4364 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Debug files
*.pdb
# Visual Studio Files
.vs/
x64/
*.html
+28
View File
@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2022, Alessandro Magnosi, Arash Parsa, Åthanasios Tserpelis
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+152
View File
@@ -0,0 +1,152 @@
# SilentMoonwalk
PoC Implementation of a true call stack spoofer
## TL;DR
SilentMoonwalk is a PoC implementation of a true call stack spoofer, implementing a technique to remove the original caller from the call stack,
using ROP to desynchronize unwinding from control flow.
## Authors
This PoC is the result of a joint research done on the topic of stack spoofing. The authors of the research are:
* [KlezVirus][9]
* [Waldo-IRC][5]
* [Trickster0][6]
I want to stress that this work would have been impossible without the work of [Waldo-IRC][5] and [Trickster0][6], which both
contributed to the early stages of the PoC, and to the research behind the PoC.
## Overview
This repository demonstrates a PoC implementation to spoof the call stack when calling arbitrary Windows APIs.
This attempt was inspired by [this Twitter thread][8], and [this Twitter thread], where sensei [namazso][1] showed and suggested
to extend the stack unwinding approach with a ROP chain to both desynchronize the unwinding from real control flow and restore
the original stack afterwards.
This PoC attempts to do something similar to the above, and uses a desync stack to completely hide the original
call stack, also removing the EXE image base from it. Upon return, a ROP gadget is invoked to restore the original stack.
In the code, this process is repeated 10 times in a loop, using different frames at each iteration, to prove stability.
### Supported Modes
The tool currently supports 2 modes, where one is actually a wrong patch to a non-working pop RBP frame identified, which operates by shifting the current
RSP and adding two fake frames to the call stack. As it operates using synthetic frames, I refer to this mode as "SYNTHETIC".
When selecting the frame that unwinds by popping the RBP register from the stack, the tool might select an unsuitable frame, ending up in an abruptly
cut call stack, as observable below.
![Windows 10 Call Stack - Cut](./assets/img/stack_cut.png)
### Synthetic Call Stack Mode
A silly solution to the problem would be to create two fake frames and link them back to the cut call stack. This would create a sort of apparently legit call stack,
even without a suitable frame which unwinds calling POP RBP, but:
* You would lose the advantage of the desync technique
* The stack would be still unwindable
* The resulting call stack could seem legit just on the first glance, but it would probably not pass a strict check
The result of the _synthetic spoof can be observed in the image below:
![Windows 10 Call Stack - Apparently Legit, non unwinding - getchar](./assets/img/stack_win10_getchar.png)
*Figure 1: Windows 10 - Valid call stack whereby the EXE module was completely removed (calling no parameters function getchar)*
*Note: This operation mode is disabled by default. To enable this mode, change the CALLSTACK_TYPE to 1*
### Desync Stack Mode
This mode is the right solution to the above problem, whereby the non-suitable frame is simply replaced by another, suitable one.
![Windows 10 Call Stack - Legit, unwinding - MessageBoxExA](./assets/img/stack_win10_msgbox_ex.png)
*Figure 2: Windows 10 - Valid call stack whereby the EXE module was completely removed (calling 4 parameters function MessageBoxA)*
## Utility
In the repository, you can find also a little util to inspect runtime functions, which might be useful to analyse runtime function entries.
```
UnwindInspector.exe -h
Unwind Inspector v0.100000
Mandatory args:
-m <module>: Target DLL
-f <function>: Target Function
-a <function-address>: Target Function Address
```
Sample Output:
```
UnwindInspector.exe -m kernelbase -a 0x7FFAAE12182C
[*] Using function address 0x7ffaae12182c
Runtime Function (0x000000000000182C, 0x00000000000019ED)
Unwind Info Address: 0x000000000026AA88
Version: 0
Ver + Flags: 00000000
SizeOfProlog: 0x1f
CountOfCodes: 0xc
FrameRegister: 0x0
FrameOffset: 0x0
UnwindCodes:
[00h] Frame: 0x741f - 0x04 - UWOP_SAVE_NONVOL (RDI, 0x001f)
[01h] Frame: 0x0015 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0015)
[02h] Frame: 0x641f - 0x04 - UWOP_SAVE_NONVOL (RSI, 0x001f)
[03h] Frame: 0x0014 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0014)
[04h] Frame: 0x341f - 0x04 - UWOP_SAVE_NONVOL (RBX, 0x001f)
[05h] Frame: 0x0012 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0012)
[06h] Frame: 0xb21f - 0x02 - UWOP_ALLOC_SMALL (R11, 0x001f)
[07h] Frame: 0xf018 - 0x00 - UWOP_PUSH_NONVOL (R15, 0x0018)
[08h] Frame: 0xe016 - 0x00 - UWOP_PUSH_NONVOL (R14, 0x0016)
[09h] Frame: 0xd014 - 0x00 - UWOP_PUSH_NONVOL (R13, 0x0014)
[0ah] Frame: 0xc012 - 0x00 - UWOP_PUSH_NONVOL (R12, 0x0012)
[0bh] Frame: 0x5010 - 0x00 - UWOP_PUSH_NONVOL (RBP, 0x0010)
```
## Build
In order to build the POC and observe a similar behaviour to the one in the picture, ensure to:
* Disable GS (`/GS-`)
* Disable Code Optimisation (`/Od`)
* Disable Whole Program Optimisation (Remove `/GL`)
* Disable size and speed preference (Remove `/Os`, `/Ot`)
* **Enable** intrinsic if not enabled (`/Oi`)
## Previous Work
It's worth mentioning previous work done on this topic, which built the foundation of this work.
* [Return Address Spoofing][7]: Original technique and idea, by Namaszo. Every other PoC I'm aware of was built on top of that.
* [YouMayPasser][10]: This amazing work by Arash is the first properly done extension of the Return Address Spoofing PoC by Namaszo.
* [VulcanRaven][2]: A call stack spoofer that operates the spoofing by synthetically creating a Thread Stack mirroring another real call stack.
* [Unwinder][3]: A very nice Rust PoC implementation of a call stack spoofer which operates by parsing unwind code information to replace frames in the call stack.
## Credits
* Huge shoutout to [waldo-irc][5] and [trickster0][6], which collaborated with me on this research. I owe everything to them.
* All the credit for the idea behind this goes to [namaszo][1], which I personally consider a genius. He also cross checked this PoC before release, so huge thanks to him.
## Notes
* [SYNTHETIC STACK ONLY]: For a limitation in the way I'm locating the gadgets, the maximum number of arguments is 8 for now (it is TRIVIAL to modify and add more params, but I couldn't bother).
* Testing on this one was pretty limited. There might be exceptions I'm not aware of at the moment.
* Unwinding involving 128-bit registers was no tested.
* Calling functions that use 128-bit registers is not officially supported.
[1]: https://twitter.com/namazso
[2]: https://github.com/WithSecureLabs/CallStackSpoofer/
[3]: https://github.com/Kudaes/Unwinder/
[4]: https://twitter.com/_Kudaes_
[5]: https://twitter.com/waldoirc
[6]: https://twitter.com/trickster012
[7]: https://www.unknowncheats.me/forum/anti-cheat-bypass/268039-x64-return-address-spoofing-source-explanation.html
[8]: https://twitter.com/_Kudaes_/status/1594753842310434816
[9]: https://twitter.com/KlezVirus
[10]: https://github.com/waldo-irc/YouMayPasser
+46
View File
@@ -0,0 +1,46 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SilentMoonwalk", "SilentMoonwalk\SilentMoonwalk.vcxproj", "{E11DC25D-E96D-495D-8968-1BA09C95B673}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{25E04E93-D4AF-4A27-8568-7B0CBE3AF0A2}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnwindInspector", "UnwindInspector\UnwindInspector.vcxproj", "{E86ABDAA-444C-409A-B466-9E034E859C80}"
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
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Debug|x64.ActiveCfg = Debug|x64
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Debug|x64.Build.0 = Debug|x64
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Debug|x86.ActiveCfg = Debug|Win32
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Debug|x86.Build.0 = Debug|Win32
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Release|x64.ActiveCfg = Release|x64
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Release|x64.Build.0 = Release|x64
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Release|x86.ActiveCfg = Release|Win32
{E11DC25D-E96D-495D-8968-1BA09C95B673}.Release|x86.Build.0 = Release|Win32
{E86ABDAA-444C-409A-B466-9E034E859C80}.Debug|x64.ActiveCfg = Debug|x64
{E86ABDAA-444C-409A-B466-9E034E859C80}.Debug|x64.Build.0 = Debug|x64
{E86ABDAA-444C-409A-B466-9E034E859C80}.Debug|x86.ActiveCfg = Debug|Win32
{E86ABDAA-444C-409A-B466-9E034E859C80}.Debug|x86.Build.0 = Debug|Win32
{E86ABDAA-444C-409A-B466-9E034E859C80}.Release|x64.ActiveCfg = Release|x64
{E86ABDAA-444C-409A-B466-9E034E859C80}.Release|x64.Build.0 = Release|x64
{E86ABDAA-444C-409A-B466-9E034E859C80}.Release|x86.ActiveCfg = Release|Win32
{E86ABDAA-444C-409A-B466-9E034E859C80}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {54F8980C-A52E-4F1D-B737-D212E6F548AF}
EndGlobalSection
EndGlobal
+35
View File
@@ -0,0 +1,35 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Visual Studio Dir
x64
File diff suppressed because it is too large Load Diff
+166
View File
@@ -0,0 +1,166 @@
<?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>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{e11dc25d-e96d-495d-8968-1ba09c95b673}</ProjectGuid>
<RootNamespace>TheRealStackSpoof</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>SilentMoonwalk</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<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)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<Optimization>Disabled</Optimization>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<WholeProgramOptimization>false</WholeProgramOptimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(CoreLibraryDependencies);%(AdditionalDependencies);vcruntime.lib;</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="SilentMoonwalk.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\AddressHunter.h" />
<ClInclude Include="include\Common.h" />
<ClInclude Include="include\Functions.h" />
<ClInclude Include="include\Spoof.h" />
<ClInclude Include="include\Test.h" />
</ItemGroup>
<ItemGroup>
<MASM Include="include\asm\SyntheticSpoofer.asm" />
<MASM Include="include\asm\DesyncSpoofer.asm" />
</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="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SilentMoonwalk.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\AddressHunter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Functions.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Spoof.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Test.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="include\asm\SyntheticSpoofer.asm">
<Filter>Source Files</Filter>
</MASM>
<MASM Include="include\asm\DesyncSpoofer.asm">
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>
</Project>
+356
View File
@@ -0,0 +1,356 @@
// https://raw.githubusercontent.com/paranoidninja/PIC-Get-Privileges/main/addresshunter.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <windows.h>
#include <inttypes.h>
#define DEREF( name )*(UINT_PTR *)(name)
#define DEREF_64( name )*(DWORD64 *)(name)
#define DEREF_32( name )*(DWORD *)(name)
#define DEREF_16( name )*(WORD *)(name)
#define DEREF_8( name )*(BYTE *)(name)
#define KERNELBASE_HASH 0xc42f2982
#define KERNEL32DLL_HASH 0xbc5d4571
#define MSVCRTDLL_HASH 0xc3222c90
#define ADVAPI32DLL_HASH 0x8353484b
#define NTDLL_HASH 0x4f576ca1
#define FH_RND_SEED 0xDC072B8A
#define ROL8(v) (v << 8 | v >> 24)
#define ROR8(v) (v >> 8 | v << 24)
#define ROX8(v) ((FH_RND_SEED % 2) ? ROL8(v) : ROR8(v))
//redefine UNICODE_STR struct
typedef struct _UNICODE_STR
{
USHORT Length;
USHORT MaximumLength;
PWSTR pBuffer;
} UNICODE_STR, * PUNICODE_STR;
//redefine PEB_LDR_DATA struct
typedef struct _PEB_LDR_DATA
{
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
//redefine LDR_DATA_TABLE_ENTRY struct
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STR FullDllName;
UNICODE_STR BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
//redefine PEB_FREE_BLOCK struct
typedef struct _PEB_FREE_BLOCK
{
struct _PEB_FREE_BLOCK* pNext;
DWORD dwSize;
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
//redefine PEB struct
typedef struct __PEB
{
BYTE bInheritedAddressSpace;
BYTE bReadImageFileExecOptions;
BYTE bBeingDebugged;
BYTE bSpareBool;
LPVOID lpMutant;
LPVOID lpImageBaseAddress;
PPEB_LDR_DATA pLdr;
LPVOID lpProcessParameters;
LPVOID lpSubSystemData;
LPVOID lpProcessHeap;
PRTL_CRITICAL_SECTION pFastPebLock;
LPVOID lpFastPebLockRoutine;
LPVOID lpFastPebUnlockRoutine;
DWORD dwEnvironmentUpdateCount;
LPVOID lpKernelCallbackTable;
DWORD dwSystemReserved;
DWORD dwAtlThunkSListPtr32;
PPEB_FREE_BLOCK pFreeList;
DWORD dwTlsExpansionCounter;
LPVOID lpTlsBitmap;
DWORD dwTlsBitmapBits[2];
LPVOID lpReadOnlySharedMemoryBase;
LPVOID lpReadOnlySharedMemoryHeap;
LPVOID lpReadOnlyStaticServerData;
LPVOID lpAnsiCodePageData;
LPVOID lpOemCodePageData;
LPVOID lpUnicodeCaseTableData;
DWORD dwNumberOfProcessors;
DWORD dwNtGlobalFlag;
LARGE_INTEGER liCriticalSectionTimeout;
DWORD dwHeapSegmentReserve;
DWORD dwHeapSegmentCommit;
DWORD dwHeapDeCommitTotalFreeThreshold;
DWORD dwHeapDeCommitFreeBlockThreshold;
DWORD dwNumberOfHeaps;
DWORD dwMaximumNumberOfHeaps;
LPVOID lpProcessHeaps;
LPVOID lpGdiSharedHandleTable;
LPVOID lpProcessStarterHelper;
DWORD dwGdiDCAttributeList;
LPVOID lpLoaderLock;
DWORD dwOSMajorVersion;
DWORD dwOSMinorVersion;
WORD wOSBuildNumber;
WORD wOSCSDVersion;
DWORD dwOSPlatformId;
DWORD dwImageSubsystem;
DWORD dwImageSubsystemMajorVersion;
DWORD dwImageSubsystemMinorVersion;
DWORD dwImageProcessAffinityMask;
DWORD dwGdiHandleBuffer[34];
LPVOID lpPostProcessInitRoutine;
LPVOID lpTlsExpansionBitmap;
DWORD dwTlsExpansionBitmapBits[32];
DWORD dwSessionId;
ULARGE_INTEGER liAppCompatFlags;
ULARGE_INTEGER liAppCompatFlagsUser;
LPVOID lppShimData;
LPVOID lpAppCompatInfo;
UNICODE_STR usCSDVersion;
LPVOID lpActivationContextData;
LPVOID lpProcessAssemblyStorageMap;
LPVOID lpSystemDefaultActivationContextData;
LPVOID lpSystemAssemblyStorageMap;
DWORD dwMinimumStackCommit;
} _PEB, * _PPEB;
DWORD HashModule(PCSTR ModuleName, size_t length)
{
DWORD i = 0;
DWORD Hash = FH_RND_SEED;
while (i < length / 2)
{
WORD PartialName = *(WORD*)((ULONG64)ModuleName + i++) | 0x20202020;
Hash ^= PartialName + ROR8(Hash);
}
return Hash;
}
// function to fetch the base address of a Mmodule from the Process Environment Block
UINT64 GetModule(DWORD TargetHash) {
ULONG_PTR dll, val1;
PWSTR val2;
USHORT usCounter;
// We want to stop when we find this
DWORD firstHash = 0;
// PEB is at 0x60 offset and __readgsqword is compiler intrinsic,
// so we don't need to extract it's symbol
dll = __readgsqword(0x60);
dll = (ULONG_PTR)((_PPEB)dll)->pLdr;
val1 = (ULONG_PTR)((PPEB_LDR_DATA)dll)->InMemoryOrderModuleList.Flink;
while (NULL != val1) {
val2 = (PWSTR)((PLDR_DATA_TABLE_ENTRY)val1)->BaseDllName.pBuffer;
usCounter = (USHORT)((PLDR_DATA_TABLE_ENTRY)val1)->BaseDllName.Length;
//calculate the hash of kernel32.dll
DWORD Hash = HashModule((PCSTR)val2, usCounter);
if (firstHash == 0) {
firstHash = Hash;
}
else if (firstHash == Hash) {
break;
}
//wprintf(L"%s: %u\n --> Hash: %x - Target: %x\n", (WCHAR*)val2, usCounter, Hash, TargetHash);
// compare the hash kernel32.dll
if (Hash == TargetHash) {
//return kernel32.dll if found
dll = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)val1)->DllBase;
return dll;
}
val1 = DEREF(val1);
}
return 0;
}
// custom strcmp function since this function will be called by GetSymbolAddress
// which means we have to call strcmp before loading msvcrt.dll
// so we are writing our own my_strcmp so that we don't have to play with egg or chicken dilemma
int my_strcmp(const char* p1, const char* p2) {
const unsigned char* s1 = (const unsigned char*)p1;
const unsigned char* s2 = (const unsigned char*)p2;
unsigned char c1, c2;
do {
c1 = (unsigned char)*s1++;
c2 = (unsigned char)*s2++;
if (c1 == '\0') {
return c1 - c2;
}
} while (c1 == c2);
return c1 - c2;
}
UINT64 GetSymbolAddress(HMODULE hModule, LPCSTR lpProcName) {
UINT64 dllAddress = (UINT64)hModule,
symbolAddress = 0,
exportedAddressTable = 0,
namePointerTable = 0,
ordinalTable = 0;
if (hModule == NULL) {
return 0;
}
PIMAGE_NT_HEADERS ntHeaders = NULL;
PIMAGE_DATA_DIRECTORY dataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
ntHeaders = (PIMAGE_NT_HEADERS)(dllAddress + ((PIMAGE_DOS_HEADER)dllAddress)->e_lfanew);
dataDirectory = (PIMAGE_DATA_DIRECTORY)&ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllAddress + dataDirectory->VirtualAddress);
exportedAddressTable = (dllAddress + exportDirectory->AddressOfFunctions);
namePointerTable = (dllAddress + exportDirectory->AddressOfNames);
ordinalTable = (dllAddress + exportDirectory->AddressOfNameOrdinals);
if (((UINT64)lpProcName & 0xFFFF0000) == 0x00000000) {
exportedAddressTable += ((IMAGE_ORDINAL((UINT64)lpProcName) - exportDirectory->Base) * sizeof(DWORD));
symbolAddress = (UINT64)(dllAddress + DEREF_32(exportedAddressTable));
}
else {
DWORD dwCounter = exportDirectory->NumberOfNames;
while (dwCounter--) {
char* cpExportedFunctionName = (char*)(dllAddress + DEREF_32(namePointerTable));
if (my_strcmp(cpExportedFunctionName, lpProcName) == 0) {
exportedAddressTable += (DEREF_16(ordinalTable) * sizeof(DWORD));
symbolAddress = (UINT64)(dllAddress + DEREF_32(exportedAddressTable));
break;
}
namePointerTable += sizeof(DWORD);
ordinalTable += sizeof(WORD);
}
}
return symbolAddress;
}
UINT64 GetSymbolOffset(HMODULE hModule, LPCSTR lpProcName) {
UINT64 dllAddress = (UINT64)hModule,
symbolAddress = 0,
exportedAddressTable = 0,
namePointerTable = 0,
ordinalTable = 0;
if (hModule == NULL) {
return 0;
}
PIMAGE_NT_HEADERS ntHeaders = NULL;
PIMAGE_DATA_DIRECTORY dataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
ntHeaders = (PIMAGE_NT_HEADERS)(dllAddress + ((PIMAGE_DOS_HEADER)dllAddress)->e_lfanew);
dataDirectory = (PIMAGE_DATA_DIRECTORY)&ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllAddress + dataDirectory->VirtualAddress);
exportedAddressTable = (dllAddress + exportDirectory->AddressOfFunctions);
namePointerTable = (dllAddress + exportDirectory->AddressOfNames);
ordinalTable = (dllAddress + exportDirectory->AddressOfNameOrdinals);
if (((UINT64)lpProcName & 0xFFFF0000) == 0x00000000) {
exportedAddressTable += ((IMAGE_ORDINAL((UINT64)lpProcName) - exportDirectory->Base) * sizeof(DWORD));
symbolAddress = (UINT64)DEREF_32(exportedAddressTable);
}
else {
DWORD dwCounter = exportDirectory->NumberOfNames;
while (dwCounter--) {
char* cpExportedFunctionName = (char*)(dllAddress + DEREF_32(namePointerTable));
if (my_strcmp(cpExportedFunctionName, lpProcName) == 0) {
exportedAddressTable += (DEREF_16(ordinalTable) * sizeof(DWORD));
symbolAddress = (UINT64)DEREF_32(exportedAddressTable);
break;
}
namePointerTable += sizeof(DWORD);
ordinalTable += sizeof(WORD);
}
}
return symbolAddress;
}
char* GetSymbolNameByOffset(HMODULE hModule, UINT64 offset) {
UINT64 dllAddress = (UINT64)hModule,
symbolAddress = 0;
if (hModule == NULL) {
return 0;
}
PIMAGE_NT_HEADERS ntHeaders = NULL;
PIMAGE_DATA_DIRECTORY dataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
ntHeaders = (PIMAGE_NT_HEADERS)(dllAddress + ((PIMAGE_DOS_HEADER)dllAddress)->e_lfanew);
dataDirectory = (PIMAGE_DATA_DIRECTORY)&ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllAddress + dataDirectory->VirtualAddress);
LPDWORD exportedAddressTable = (LPDWORD)(dllAddress + exportDirectory->AddressOfFunctions);
LPDWORD namePointerTable = (LPDWORD)(dllAddress + exportDirectory->AddressOfNames);
LPWORD ordinalTable = (LPWORD)(dllAddress + exportDirectory->AddressOfNameOrdinals);
char* currProcName;
for (SIZE_T i = 0; i < exportDirectory->NumberOfNames; i++) {
// Get current function name
currProcName = (LPSTR)((LPBYTE)hModule + namePointerTable[i]);
// Get current function address
if (exportedAddressTable[ordinalTable[i]] == offset) {
return currProcName;
}
}
return NULL;
}
PVOID GetExceptionDirectoryAddress(HMODULE hModule, DWORD* tSize)
{
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD64)hModule + dosHeader->e_lfanew);
DWORD64 exceptionDirectoryRVA = ntHeader->OptionalHeader.DataDirectory[3].VirtualAddress;
*tSize = ntHeader->OptionalHeader.DataDirectory[3].Size;
DWORD64 imageExceptionDirectory = (DWORD64)((DWORD_PTR)hModule + exceptionDirectoryRVA);
return (PVOID)imageExceptionDirectory;
}
PVOID GetExportDirectoryAddress(HMODULE hModule)
{
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD64)hModule + dosHeader->e_lfanew);
DWORD_PTR exportDirectoryRVA = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
DWORD64 imageExportDirectory = (DWORD64)((DWORD_PTR)hModule + exportDirectoryRVA);
return (PVOID)imageExportDirectory;
}
+340
View File
@@ -0,0 +1,340 @@
#pragma once
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED
#include <Windows.h>
#include <psapi.h>
#include <dbghelp.h>
#include "AddressHunter.h"
#define SEED 123456
#define MAX_FRAMES 154
// Remove if you have a self-made definition of memcmp
#define MemCompare memcmp
// Using custom printf
#define printf custom_printf
void custom_printf(const char* pszFormat, ...);
// Removing malloc deps
#undef malloc
#define malloc(x) HeapAlloc(GetProcessHeap(), 0, x)
#undef realloc
#define realloc(x,s) HeapReAlloc(GetProcessHeap(), 0, x, s)
#undef free
#define free(x) HeapFree(GetProcessHeap(), 0, x)
// Removing memset deps
void* custom_memset(void* dest, int c, size_t count);
#ifdef _DEBUG
#define DPRINT(...) { printf(__VA_ARGS__); }
#else
#define DPRINT(...) {}
#endif
#define HIDWORD(l) ((DWORD)(((DWORDLONG)(l)>>32)&0xFFFFFFFF))
#define BitVal(data,y) ( (data>>y) & 1)
#define BitChainInfo(data) BitVal(data, 2)
#define BitUHandler(data) BitVal(data, 1)
#define BitEHandler(data) BitVal(data, 0)
#define Version(data) BitVal(data, 4)*2 + BitVal(data, 3)
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define B2BP BYTE_TO_BINARY_PATTERN
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
typedef UCHAR UBYTE;
typedef enum _REGISTERS {
RAX = 0,
RCX,
RDX,
RBX,
RSP,
RBP,
RSI,
RDI,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15
} REGISTERS;
typedef union _UNWIND_CODE {
struct {
UBYTE CodeOffset; // 0xFF00
UBYTE UnwindOp : 4; // 0x000f OPCODE
UBYTE OpInfo : 4; // 0x00f0
};
USHORT FrameOffset;
} UNWIND_CODE, * PUNWIND_CODE;
typedef struct _UNWIND_INFO {
UBYTE Version : 3;
UBYTE Flags : 5; // 4 bytes
UBYTE SizeOfProlog; // 4 bytes
UBYTE CountOfCodes; // 4 bytes
UBYTE FrameRegister : 4;
UBYTE FrameOffset : 4; // 4bytes
UNWIND_CODE UnwindCode[1];
union {
OPTIONAL ULONG ExceptionHandler;
OPTIONAL ULONG FunctionEntry;
};
OPTIONAL ULONG ExceptionData[];
} UNWIND_INFO, * PUNWIND_INFO;
#define GetUnwindCodeEntry(info, index) \
((info)->UnwindCode[index])
#define GetLanguageSpecificDataPtr(info) \
((PVOID)&GetUnwindCodeEntry((info),((info)->CountOfCodes + 1) & ~1))
#define GetExceptionHandler(base, info) \
((PEXCEPTION_ROUTINE)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
#define GetChainedFunctionEntry(base, info) \
((PRUNTIME_FUNCTION)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
#define GetExceptionDataPtr(info) \
((PVOID)((PULONG)GetLanguageSpecificDataPtr(info) + 1))
#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64)
#define ADDRESS ADDRESS64
#define LPADDRESS LPADDRESS64
#else
typedef struct _tagADDRESS {
DWORD Offset;
WORD Segment;
ADDRESS_MODE Mode;
} ADDRESS, * LPADDRESS;
#endif
typedef struct _MIN_CTX {
DWORD64 Rax;
DWORD64 Rcx;
DWORD64 Rdx;
DWORD64 Rbx;
DWORD64 Rsp;
DWORD64 Rbp;
DWORD64 Rsi;
DWORD64 Rdi;
DWORD64 R8;
DWORD64 R9;
DWORD64 R10;
DWORD64 R11;
DWORD64 R12;
DWORD64 R13;
DWORD64 R14;
DWORD64 R15;
DWORD64 Rip;
DWORD64 Reserved;
DWORD64 StackSize;
} MIN_CTX, *PMIN_CTX;
typedef enum _UNWIND_OP_CODES {
// x86_64. https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64.
UWOP_PUSH_NONVOL = 0,
UWOP_ALLOC_LARGE, // 1
UWOP_ALLOC_SMALL, // 2
UWOP_SET_FPREG, // 3
UWOP_SAVE_NONVOL, // 4
UWOP_SAVE_NONVOL_BIG, // 5
UWOP_EPILOG, // 6
UWOP_SPARE_CODE, // 7
UWOP_SAVE_XMM128, // 8
UWOP_SAVE_XMM128BIG, // 9
UWOP_PUSH_MACH_FRAME, // 10
// ARM64. https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
UWOP_ALLOC_MEDIUM,
UWOP_SAVE_R19R20X,
UWOP_SAVE_FPLRX,
UWOP_SAVE_FPLR,
UWOP_SAVE_REG,
UWOP_SAVE_REGX,
UWOP_SAVE_REGP,
UWOP_SAVE_REGPX,
UWOP_SAVE_LRPAIR,
UWOP_SAVE_FREG,
UWOP_SAVE_FREGX,
UWOP_SAVE_FREGP,
UWOP_SAVE_FREGPX,
UWOP_SET_FP,
UWOP_ADD_FP,
UWOP_NOP,
UWOP_END,
UWOP_SAVE_NEXT,
UWOP_TRAP_FRAME,
UWOP_CONTEXT,
UWOP_CLEAR_UNWOUND_TO_CALL,
// ARM: https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
UWOP_ALLOC_HUGE,
UWOP_WIDE_ALLOC_MEDIUM,
UWOP_WIDE_ALLOC_LARGE,
UWOP_WIDE_ALLOC_HUGE,
UWOP_WIDE_SAVE_REG_MASK,
UWOP_WIDE_SAVE_SP,
UWOP_SAVE_REGS_R4R7LR,
UWOP_WIDE_SAVE_REGS_R4R11LR,
UWOP_SAVE_FREG_D8D15,
UWOP_SAVE_REG_MASK,
UWOP_SAVE_LR,
UWOP_SAVE_FREG_D0D15,
UWOP_SAVE_FREG_D16D31,
UWOP_WIDE_NOP, // UWOP_NOP
UWOP_END_NOP, // UWOP_END
UWOP_WIDE_END_NOP,
// Custom implementation opcodes (implementation specific).
UWOP_CUSTOM,
} UNWIND_OP_CODES;
// Stack allocations use UOP_AllocSmall, UOP_AllocLarge from above, plus
// the following. AllocSmall, AllocLarge and AllocHuge represent a 16 bit
// instruction, while the WideAlloc* opcodes represent a 32 bit instruction.
// Small can represent a stack offset of 0x7f*4 (252) bytes, Medium can
// represent up to 0x3ff*4 (4092) bytes, Large up to 0xffff*4 (262140) bytes,
// and Huge up to 0xffffff*4 (67108860) bytes.
#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64)
#define STACKFRAME STACKFRAME64
#define LPSTACKFRAME LPSTACKFRAME64
#else
typedef struct _tagSTACKFRAME {
ADDRESS AddrPC;
ADDRESS AddrReturn;
ADDRESS AddrFrame;
ADDRESS AddrStack;
PVOID FuncTableEntry;
DWORD Params[4];
BOOL Far;
BOOL Virtual;
DWORD Reserved[3];
KDHELP KdHelp;
ADDRESS AddrBStore;
} STACKFRAME, * LPSTACKFRAME;
#endif
BYTE ExtractOpInfo(BYTE OpIC) {
return OpIC >> 4;
}
BYTE ExtractOpCode(BYTE OpIC) {
return OpIC & 0x0F;
}
char* GetOpInfo(int op) {
char* reg = (char*)malloc(4);
if (reg == NULL) {
return NULL;
}
custom_memset(reg, 0, 4);
if(op == 0) {
memcpy(reg, "RAX", 4);
}
else if(op == 1) {
memcpy(reg, "RCX", 4);
}
else if(op == 2) {
memcpy(reg, "RDX", 4);
}
else if(op == 3) {
memcpy(reg, "RBX", 4);
}
else if(op == 4) {
memcpy(reg, "RSP", 4);
}
else if(op == 5) {
memcpy(reg, "RBP", 4);
}
else if(op == 6) {
memcpy(reg, "RSI", 4);
}
else if(op == 7) {
memcpy(reg, "RDI", 4);
}
else if(op == 8) {
memcpy(reg, "R8\0", 4);
}
else if(op == 9) {
memcpy(reg, "R9\0", 4);
}
else if(op == 10) {
memcpy(reg, "R10", 4);
}
else if(op == 11) {
memcpy(reg, "R11", 4);
}
else if(op == 12) {
memcpy(reg, "R12", 4);
}
else if(op == 13) {
memcpy(reg, "R13", 4);
}
else if(op == 14) {
memcpy(reg, "R14", 4);
}
else if(op == 15) {
memcpy(reg, "R15", 4);
}
return reg;
}
void custom_printf(const char* pszFormat, ...) {
char buf[1024];
va_list argList;
va_start(argList, pszFormat);
wvsprintfA(buf, pszFormat, argList);
va_end(argList);
DWORD done;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, strlen(buf), &done, NULL);
}
void* custom_memset(void* dest, int val, size_t len) {
for (char* dst = (char*)dest; len != 0; len--) {
*dst++ = val;
}
return dest;
}
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed as 256 + 20
{
next = next * 1103515245 + 12345;
return ((unsigned int)(next / 65536) % 0x7f) + 0x20;
}
void srand(unsigned int seed)
{
next = seed;
}
#endif
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include "Windows.h"
#ifdef _DEBUG
#define DPRINTUNWINDCODE(x) { \
printf("0x%x\t", x->CodeOffset); \
printf("0x%x\t", x->OpInfo); \
printf("0x%x\n", x->UnwindOp); \
}
#else
#define DPRINTUNWINDCODE(x) {}
#endif
#ifdef _DEBUG
#ifdef _VERBOSE_DEBUG
#define DPRINTCTX(x) { \
printf("RAX: 0x%llx -", x.Rax); \
printf("RBX :0x%llx -", x.Rbx); \
printf("RCX: 0x%llx -", x.Rcx); \
printf("RDX: 0x%llx -", x.Rdx); \
printf("RDI: 0x%llx -", x.Rdi); \
printf("RSI: 0x%llx -", x.Rsi); \
printf("RBP: 0x%llx -", x.Rbp); \
printf("RSP: 0x%llx -\n", x.Rsp); \
printf("R8 : 0x%llx -", x.R8 ); \
printf("R9 : 0x%llx -", x.R9 ); \
printf("R10: 0x%llx -", x.R10); \
printf("R11: 0x%llx -", x.R11); \
printf("R12: 0x%llx -", x.R12); \
printf("R13: 0x%llx -", x.R13); \
printf("R14: 0x%llx -", x.R14); \
printf("R15: 0x%llx \n", x.R15); \
printf("RIP: 0x%llx \n", x.Rip); \
}
#else
#define DPRINTCTX(x) {}
#endif
#else
#define DPRINTCTX(x) {}
#endif
typedef PIMAGE_RUNTIME_FUNCTION_ENTRY PERF;
typedef SIZE_T(WINAPI* VirtualQueryType)(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
typedef HANDLE(WINAPI* OpenProcessType)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
typedef DWORD(WINAPI* GetCurrentProcessIdType)();
PIMAGE_RUNTIME_FUNCTION_ENTRY RTFindFunctionByAddress(UINT64, DWORD64);
PIMAGE_RUNTIME_FUNCTION_ENTRY RTFindFunctionByIndex(UINT64, DWORD);
DWORD GetStackFrameSize(HMODULE, PVOID, DWORD*);
DWORD GetStackFrameSizeWhereRbpIsPushedOnStack(HMODULE, PVOID, DWORD*);
DWORD GetStackFrameSizeIgnoringUwopSetFpreg(HMODULE, PVOID, DWORD*);
void PrintUnwindInfo(HMODULE, PVOID);
void LookupSymbolFromRTIndex(HMODULE, int, bool);
void EnumAllRTFunctions(HMODULE);
DWORD FindRTFunctionsUnwind(HMODULE, PVOID);
VOID FindGadget(HMODULE moduleBase, PERF pRuntimeFunctionTable, DWORD rtLastIndex, PDWORD stackSize, PDWORD prtSaveIndex, PDWORD skip, DWORD gadgetType);
DWORD FindProlog(HMODULE moduleBase, PERF pRuntimeFunctionTable, DWORD rtLastIndex, PDWORD stackSize, PDWORD prtSaveIndex, PDWORD skip, PDWORD64 rtTargetOffset);
DWORD FindPushRbp(HMODULE moduleBase, PERF pRuntimeFunctionTable, DWORD rtLastIndex, PDWORD stackSize, PDWORD prtSaveIndex, PDWORD skip, PDWORD64 rtTargetOffset);
+59
View File
@@ -0,0 +1,59 @@
#include "Common.h"
#define JMP_RBX 9215 // 0xff 0x23 --> reversed 0x23 0xff --> to Integer 9215
#define ADD_RSP_0x38 952402760 // 4883C438 --> reversed 38C48348 --> to Integer 952402760
#define RET 0xc3 // One byte, no conversion needed
typedef struct
{
/* POINTERS */
PVOID KernelBaseAddress;
PVOID KernelBaseAddressEnd;
PVOID RtlUserThreadStartAddress;
PVOID BaseThreadInitThunkAddress;
PVOID FirstFrameFunctionPointer;
PVOID SecondFrameFunctionPointer;
PVOID JmpRbxGadget;
PVOID AddRspXGadget;
/* SIZES / OFFSETS */
UINT64 FirstFrameSize;
UINT64 FirstFrameRandomOffset;
UINT64 SecondFrameSize;
UINT64 SecondFrameRandomOffset;
UINT64 JmpRbxGadgetFrameSize;
UINT64 AddRspXGadgetFrameSize;
UINT64 RtlUserThreadStartFrameSize;
UINT64 BaseThreadInitThunkFrameSize;
/* FRAME OFFSET */
UINT64 StackOffsetWhereRbpIsPushed;
/* OTHERS */
PVOID JmpRbxGadgetRef;
PVOID SpoofFunctionPointer;
PVOID ReturnAddress;
/* SPOOFED FOUNCTION NUMBER OF PARAMETERS */
UINT64 Nargs;
/* SPOOFED FOUNCTION PARAMETERS */
PVOID Arg01;
PVOID Arg02;
PVOID Arg03;
PVOID Arg04;
PVOID Arg05;
PVOID Arg06;
PVOID Arg07;
PVOID Arg08;
} SPOOFER, * PSPOOFER;
VOID SpoofCallStack(PSPOOFER);
EXTERN_C PVOID spoof_call(PSPOOFER sConfig);
EXTERN_C PVOID spoof_call_synthetic(PSPOOFER sConfig);
EXTERN_C PVOID get_current_rsp();
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include "Windows.h"
void TestLocateFunctionByAddress();
void TestLookupByFrameOffset();
void TestEnumAllRT(DWORD);
void Test();
@@ -0,0 +1,236 @@
; ------------------------------------------------------------------------------------
;
; Author : klezVirus 2022
; Twitter : https://twitter.com/klezVirus
; Original Idea: Namazso
; Twitter : https://twitter.com/namazso
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
spoof_call proto
restore proto
.data
; ------------------------------------------------------------------------------------
; Spoofing Configuration Structure
; Utility structure to pass all the relevant details from C to ASM regarding the
; stack frames to spoof
; ------------------------------------------------------------------------------------
SPOOFER STRUCT
KernelBaseAddress DQ 1
KernelBaseAddressEnd DQ 1
RtlUserThreadStartAddress DQ 1
BaseThreadInitThunkAddress DQ 1
FirstFrameFunctionPointer DQ 1
SecondFrameFunctionPointer DQ 1
JmpRbxGadget DQ 1
AddRspXGadget DQ 1
FirstFrameSize DQ 1
FirstFrameRandomOffset DQ 1
SecondFrameSize DQ 1
SecondFrameRandomOffset DQ 1
JmpRbxGadgetFrameSize DQ 1
AddRspXGadgetFrameSize DQ 1
RtlUserThreadStartFrameSize DQ 1
BaseThreadInitThunkFrameSize DQ 1
StackOffsetWhereRbpIsPushed DQ 1
JmpRbxGadgetRef DQ 1
SpoofFunctionPointer DQ 1
ReturnAddress DQ 1
Nargs DQ 1
Arg01 DQ 1
Arg02 DQ 1
Arg03 DQ 1
Arg04 DQ 1
Arg05 DQ 1
Arg06 DQ 1
Arg07 DQ 1
Arg08 DQ 1
SPOOFER ENDS
.code
get_current_rsp proc
mov rax, rsp
add rax, 8
ret
get_current_rsp endp
spoof_call proc
; ------------------------------------------------------------------------------------
; Saving non-vol registers
; ------------------------------------------------------------------------------------
mov [rsp+08h], rbp
mov [rsp+10h], rbx
; ------------------------------------------------------------------------------------
; Creating a stack reference to the JMP RBX gadget
; ------------------------------------------------------------------------------------
mov rbx, [rcx].SPOOFER.JmpRbxGadget
mov [rsp+18h], rbx
mov rbx, rsp
add rbx, 18h
mov [rcx].SPOOFER.JmpRbxGadgetRef, rbx
; ------------------------------------------------------------------------------------
; Prolog
; RBP -> Keeps track of original Stack
; RSP -> Desync Stack for Unwinding Info
; ------------------------------------------------------------------------------------
; Note: Everything between RSP and RBP is our new stack frame for unwinding
; ------------------------------------------------------------------------------------
mov rbp, rsp
; ------------------------------------------------------------------------------------
; Creating stack pointer to Restore PROC
; ------------------------------------------------------------------------------------
lea rax, restore
push rax
; Now RBX contains the stack pointer to Restore PROC
; -> Will be called by the JMP [RBX] gadget
lea rbx, [rsp]
; ------------------------------------------------------------------------------------
; Starting Frames Tampering
; ------------------------------------------------------------------------------------
; First Frame (Fake origin)
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.FirstFrameFunctionPointer
mov rax, [rcx].SPOOFER.FirstFrameRandomOffset
add qword ptr [rsp], rax
mov rax, [rcx].SPOOFER.ReturnAddress
sub rax, [rcx].SPOOFER.FirstFrameSize
sub rsp, [rcx].SPOOFER.SecondFrameSize
mov r10, [rcx].SPOOFER.StackOffsetWhereRbpIsPushed
mov [rsp+r10], rax
; ------------------------------------------------------------------------------------
; ROP Frames
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.SecondFrameFunctionPointer
mov rax, [rcx].SPOOFER.SecondFrameRandomOffset
add qword ptr [rsp], rax
; ------------------------------------------------------------------------------------
; 1. JMP [RBX] Gadget
; ------------------------------------------------------------------------------------
sub rsp, [rcx].SPOOFER.JmpRbxGadgetFrameSize
push [rcx].SPOOFER.JmpRbxGadgetRef
sub rsp, [rcx].SPOOFER.AddRspXGadgetFrameSize
mov r10, [rcx].SPOOFER.JmpRbxGadget
mov [rsp+38h], r10
; ------------------------------------------------------------------------------------
; 2. Stack PIVOT (To restore original Control Flow Stack)
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.AddRspXGadget
mov rax, [rcx].SPOOFER.AddRspXGadgetFrameSize
mov [rbp+28h], rax
; ------------------------------------------------------------------------------------
; Set the pointer to the function to call in RAX
; ------------------------------------------------------------------------------------
mov rax, [rcx].SPOOFER.SpoofFunctionPointer
jmp parameter_handler
jmp execute
spoof_call endp
restore proc
mov rsp, rbp
mov rbp, [rsp+08h]
mov rbx, [rsp+10h]
ret
restore endp
parameter_handler proc
mov r9, rax
mov rax, 8
mov r8, [rcx].SPOOFER.Nargs
mul r8
; pop rdx
; sub rsp, rax -- Not necessary
; push rdx
xchg r9, rax
cmp [rcx].SPOOFER.Nargs, 8
je handle_eight
cmp [rcx].SPOOFER.Nargs, 7
je handle_seven
cmp [rcx].SPOOFER.Nargs, 6
je handle_six
cmp [rcx].SPOOFER.Nargs, 5
je handle_five
cmp [rcx].SPOOFER.Nargs, 4
je handle_four
cmp [rcx].SPOOFER.Nargs, 3
je handle_three
cmp [rcx].SPOOFER.Nargs, 2
je handle_two
cmp [rcx].SPOOFER.Nargs, 1
je handle_one
cmp [rcx].SPOOFER.Nargs, 0
je handle_none
parameter_handler endp
handle_eight proc
push r15
mov r15, [rcx].SPOOFER.Arg08
mov [rsp+48h], r15
pop r15
jmp handle_seven
handle_eight endp
handle_seven proc
push r15
mov r15, [rcx].SPOOFER.Arg07
mov [rsp+40h], r15
pop r15
jmp handle_six
handle_seven endp
handle_six proc
push r15
mov r15, [rcx].SPOOFER.Arg06
mov [rsp+38h], r15
pop r15
jmp handle_five
handle_six endp
handle_five proc
push r15
mov r15, [rcx].SPOOFER.Arg05
mov [rsp+30h], r15
pop r15
jmp handle_four
handle_five endp
handle_four proc
mov r9, [rcx].SPOOFER.Arg04
jmp handle_three
handle_four endp
handle_three proc
mov r8, [rcx].SPOOFER.Arg03
jmp handle_two
handle_three endp
handle_two proc
mov rdx, [rcx].SPOOFER.Arg02
jmp handle_one
handle_two endp
handle_one proc
mov rcx, [rcx].SPOOFER.Arg01
jmp handle_none
handle_one endp
handle_none proc
jmp execute
handle_none endp
execute proc
jmp qword ptr rax
execute endp
end
@@ -0,0 +1,297 @@
; ------------------------------------------------------------------------------------
;
; Author : klezVirus 2022
; Twitter : https://twitter.com/klezVirus
; Original Idea: Namazso
; Twitter : https://twitter.com/namazso
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
spoof_call_synthetic proto
restore_synthetic proto
.data
; ------------------------------------------------------------------------------------
; Spoofing Configuration Structure
; Utility structure to pass all the relevant details from C to ASM regarding the
; stack frames to spoof
; ------------------------------------------------------------------------------------
SPOOFER STRUCT
KernelBaseAddress DQ 1
KernelBaseAddressEnd DQ 1
RtlUserThreadStartAddress DQ 1
BaseThreadInitThunkAddress DQ 1
FirstFrameFunctionPointer DQ 1
SecondFrameFunctionPointer DQ 1
JmpRbxGadget DQ 1
AddRspXGadget DQ 1
FirstFrameSize DQ 1
FirstFrameRandomOffset DQ 1
SecondFrameSize DQ 1
SecondFrameRandomOffset DQ 1
JmpRbxGadgetFrameSize DQ 1
AddRspXGadgetFrameSize DQ 1
RtlUserThreadStartFrameSize DQ 1
BaseThreadInitThunkFrameSize DQ 1
StackOffsetWhereRbpIsPushed DQ 1
JmpRbxGadgetRef DQ 1
SpoofFunctionPointer DQ 1
ReturnAddress DQ 1
Nargs DQ 1
Arg01 DQ 1
Arg02 DQ 1
Arg03 DQ 1
Arg04 DQ 1
Arg05 DQ 1
Arg06 DQ 1
Arg07 DQ 1
Arg08 DQ 1
SPOOFER ENDS
.code
spoof_call_synthetic proc
; ------------------------------------------------------------------------------------
; Saving non-vol registers
; ------------------------------------------------------------------------------------
mov [rsp+08h], rbp
mov [rsp+10h], rbx
mov [rsp+18h], r15
; ------------------------------------------------------------------------------------
; Creating a stack reference to the JMP RBX gadget
; ------------------------------------------------------------------------------------
mov rbx, [rcx].SPOOFER.JmpRbxGadget
mov [rsp+20h], rbx
mov rbx, rsp
add rbx, 20h
mov [rcx].SPOOFER.JmpRbxGadgetRef, rbx
; ------------------------------------------------------------------------------------
; Prolog
; RBP -> Keeps track of original Stack
; RSP -> Desync Stack for Unwinding Info
; ------------------------------------------------------------------------------------
; Note: Everything between RSP and RBP is our new stack frame for unwinding
; ------------------------------------------------------------------------------------
sub rsp, 200h
mov rbp, rsp
; ------------------------------------------------------------------------------------
; Creating stack pointer to Restore PROC
; ------------------------------------------------------------------------------------
lea rax, restore_synthetic
push rax
; Now RBX contains the stack pointer to Restore PROC
; -> Will be called by the JMP [RBX] gadget
lea rbx, [rsp]
; ------------------------------------------------------------------------------------
; Starting Frames Tampering
; ------------------------------------------------------------------------------------
; First Frame (Frame preparation)
; The first frame contains the details
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.FirstFrameFunctionPointer
add qword ptr [rsp], 20h
mov rax, [rcx].SPOOFER.ReturnAddress
sub rax, [rcx].SPOOFER.FirstFrameSize
sub rsp, [rcx].SPOOFER.SecondFrameSize
mov r10, [rcx].SPOOFER.StackOffsetWhereRbpIsPushed
mov [rsp+r10], rax
; ------------------------------------------------------------------------------------
; Cutting the call stack. The 0 pushed in this position will be the return address
; of the next frame "RtlUserThreadStart", making it effectively the originating function
; ------------------------------------------------------------------------------------
xor rax, rax
push rax
; ------------------------------------------------------------------------------------
; Here we proceed by adding the two top fake frames:
; - RtlUserThreadStart
; - BaseThreadInitThunk
; ------------------------------------------------------------------------------------
mov rax, [rcx].SPOOFER.FirstFrameFunctionPointer
sub rax, [rcx].SPOOFER.FirstFrameSize
sub rsp, [rcx].SPOOFER.RtlUserThreadStartFrameSize
mov [rsp+30h], rax
; ------------------------------------------------------------------------------------
; RtlUserThreadStart
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.RtlUserThreadStartAddress
add qword ptr [rsp], 21h
sub rsp, [rcx].SPOOFER.BaseThreadInitThunkFrameSize
; ------------------------------------------------------------------------------------
; BaseThreadInitThunk
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.BaseThreadInitThunkAddress
add qword ptr [rsp], 14h
mov rax, [rcx].SPOOFER.RtlUserThreadStartAddress
sub rax, [rcx].SPOOFER.RtlUserThreadStartFrameSize
sub rsp, [rcx].SPOOFER.JmpRbxGadgetFrameSize
mov [rsp+30h], rax
; ------------------------------------------------------------------------------------
; ROP Frames
; These two frames contain the ROP gadgets that will be used to restore the original
; Control Flow stack
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; 1. JMP [RBX] Gadget
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.JmpRbxGadget
mov rax, [rcx].SPOOFER.BaseThreadInitThunkAddress
sub rax, [rcx].SPOOFER.SecondFrameSize
sub rsp, [rcx].SPOOFER.AddRspXGadgetFrameSize
mov [rsp+30h], rax
mov r10, [rcx].SPOOFER.JmpRbxGadget
mov [rsp+38h], r10
; ------------------------------------------------------------------------------------
; 2. Stack PIVOT (To restore original Control Flow Stack)
; ------------------------------------------------------------------------------------
push [rcx].SPOOFER.AddRspXGadget
mov rax, [rcx].SPOOFER.AddRspXGadgetFrameSize
mov [rbp+28h], rax
; ------------------------------------------------------------------------------------
; Finalise
; Placing the pointer to the function to call
; ------------------------------------------------------------------------------------
mov rax, [rbp+28h]
mov [rsp+28h], rax
mov rax, [rbp+30h]
mov [rsp+30h], rax
mov rax, [rcx].SPOOFER.SpoofFunctionPointer
jmp parameter_handler_synthetic
jmp execute_synthetic
spoof_call_synthetic endp
restore_synthetic proc
mov rsp, rbp
add rsp, 200h
mov rbp, [rsp+08h]
mov rbx, [rsp+10h]
mov r15, [rsp+18h]
ret
restore_synthetic endp
parameter_handler_synthetic proc
mov r9, rax
mov rax, 8
mov r8, [rcx].SPOOFER.Nargs
mul r8
; cmp rax, 020h
; ja allocate
; jmp post_allocate
;allocate:
; ------------------------------------------------------------------------------------
; If Not necessary to allocate space for parameters
; ------------------------------------------------------------------------------------
; pop rdx
; sub rax, 020h
; sub rsp, rax
; push rdx
; ------------------------------------------------------------------------------------
;post_allocate:
xchg r9, rax
cmp [rcx].SPOOFER.Nargs, 8
je handle_eight_synthetic
cmp [rcx].SPOOFER.Nargs, 7
je handle_seven_synthetic
cmp [rcx].SPOOFER.Nargs, 6
je handle_six_synthetic
cmp [rcx].SPOOFER.Nargs, 5
je handle_five_synthetic
cmp [rcx].SPOOFER.Nargs, 4
je handle_four_synthetic
cmp [rcx].SPOOFER.Nargs, 3
je handle_three_synthetic
cmp [rcx].SPOOFER.Nargs, 2
je handle_two_synthetic
cmp [rcx].SPOOFER.Nargs, 1
je handle_one_synthetic
cmp [rcx].SPOOFER.Nargs, 0
je handle_none_synthetic
parameter_handler_synthetic endp
handle_eight_synthetic proc
push r15
mov r15, [rcx].SPOOFER.Arg08
mov [rsp+48h], r15
pop r15
jmp handle_seven_synthetic
handle_eight_synthetic endp
handle_seven_synthetic proc
push r15
mov r15, [rcx].SPOOFER.Arg07
mov [rsp+40h], r15
pop r15
jmp handle_six_synthetic
handle_seven_synthetic endp
handle_six_synthetic proc
push r15
mov r15, [rcx].SPOOFER.Arg06
mov [rsp+38h], r15
pop r15
jmp handle_five_synthetic
handle_six_synthetic endp
handle_five_synthetic proc
push r15
mov r15, [rcx].SPOOFER.Arg05
mov [rsp+30h], r15
pop r15
jmp handle_four_synthetic
handle_five_synthetic endp
handle_four_synthetic proc
mov r9, [rcx].SPOOFER.Arg04
jmp handle_three_synthetic
handle_four_synthetic endp
handle_three_synthetic proc
mov r8, [rcx].SPOOFER.Arg03
jmp handle_two_synthetic
handle_three_synthetic endp
handle_two_synthetic proc
mov rdx, [rcx].SPOOFER.Arg02
jmp handle_one_synthetic
handle_two_synthetic endp
handle_one_synthetic proc
mov rcx, [rcx].SPOOFER.Arg01
jmp handle_none_synthetic
handle_one_synthetic endp
handle_none_synthetic proc
jmp execute_synthetic
handle_none_synthetic endp
execute_synthetic proc
jmp qword ptr rax
execute_synthetic endp
end
+333
View File
@@ -0,0 +1,333 @@
#include "include/Common.h"
#include "include/Functions.h"
void LookupSymbolFromRTIndex(HMODULE dllBase, int rtFuntionIndex, bool verbose) {
PIMAGE_RUNTIME_FUNCTION_ENTRY rtFunction = RTFindFunctionByIndex((UINT64)dllBase, rtFuntionIndex);
if (rtFunction == NULL) {
printf("Function not found\n");
return;
}
if (verbose) {
printf("Function found: \n");
printf(" Begin Address 0x%p \n", (PVOID)rtFunction->BeginAddress);
printf(" End Address 0x%p \n", (PVOID)rtFunction->EndAddress);
printf(" Unwind Info Address 0x%p \n", (PVOID)rtFunction->UnwindInfoAddress);
printf("Looking up in exports... \n");
}
char* procName = GetSymbolNameByOffset(dllBase, rtFunction->BeginAddress);
if (procName == NULL) {
if (verbose) {
printf("Function not found\n");
}
return;
}
printf("Function %u found: %s\n", rtFuntionIndex, procName);
if (verbose) {
PrintUnwindInfo(dllBase, (PVOID)rtFunction->UnwindData);
}
return;
}
void PrintUnwindInfo(HMODULE dllBase, PVOID unwindDataAddress) {
PUNWIND_INFO tInfo = (PUNWIND_INFO)((UINT64)dllBase + (DWORD)unwindDataAddress);
printf(" Version: %d \n", Version(tInfo->Flags));
printf(" Ver + Flags: " B2BP " \n", BYTE_TO_BINARY(tInfo->Flags));
printf(" SizeOfProlog: 0x%x \n", tInfo->SizeOfProlog);
printf(" CountOfCodes: 0x%x \n", tInfo->CountOfCodes);
printf(" FrameRegister: 0x%x \n", tInfo->FrameRegister);
printf(" FrameOffset: 0x%x \n", tInfo->FrameOffset);
printf(" UnwindCodes: \n");
char* reg = NULL;
for (int j = 0; j < tInfo->CountOfCodes; j++) {
printf(" [%.2xh] Frame: 0x%.4x - ", j, tInfo->UnwindCode[j].FrameOffset);
reg = GetOpInfo(tInfo->UnwindCode[j].OpInfo);
switch (tInfo->UnwindCode[j].UnwindOp) {
case UWOP_PUSH_NONVOL: // 0
printf("0x%.2x - UWOP_PUSH_NONVOL (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_ALLOC_LARGE: // 1
printf("0x%.2x - UWOP_ALLOC_LARGE (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_ALLOC_SMALL: // 2
printf("0x%.2x - UWOP_ALLOC_SMALL (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_SET_FPREG: // 3
printf("0x%.2x - UWOP_SET_FPREG (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_SAVE_NONVOL: // 4
printf("0x%.2x - UWOP_SAVE_NONVOL (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_SAVE_NONVOL_BIG: // 5
printf("0x%.2x - UWOP_SAVE_NONVOL_BIG (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_EPILOG: // 6
printf("0x%.2x - UWOP_EPILOG (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
case UWOP_SAVE_XMM128: // 8
printf("0x%.2x - UWOP_SAVE_XMM128 (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_SPARE_CODE: // 7
printf("0x%.2x - UWOP_SPARE_CODE (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
case UWOP_SAVE_XMM128BIG: // 9
printf("0x%.2x - UWOP_SAVE_XMM128BIG (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
case UWOP_PUSH_MACH_FRAME:
printf("0x%.2x - UWOP_PUSH_MACH_FRAME (%3s, 0x%.4x)\n", tInfo->UnwindCode[j].UnwindOp, reg, tInfo->UnwindCode[j].CodeOffset);
break;
default:
break;
}
if (NULL != reg) {
free(reg);
}
}
if (BitChainInfo(tInfo->Flags)) {
printf(" Function Entry Offset: 0x%p\n", GetChainedFunctionEntry(dllBase, tInfo));
}
if (BitUHandler(tInfo->Flags)) {
}
if (BitEHandler(tInfo->Flags)) {
PVOID dataPtr = GetExceptionDataPtr(tInfo);
PVOID handlerPtr = GetExceptionHandler(dllBase, tInfo);
ULONG data = *((PULONG)dataPtr);
INT32 handler = *((PDWORD)handlerPtr);
printf(" Exception Handler Offset: 0x%p\n", GetExceptionHandler(dllBase, tInfo));
printf(" Exception Data Offset: 0x%x\n", data);
}
return;
}
void EnumAllRTFunctions(HMODULE moduleBase)
{
DWORD tSize;
PRUNTIME_FUNCTION pRuntimeFunctionTable;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
pRuntimeFunctionTable = (PRUNTIME_FUNCTION)(GetExceptionDirectoryAddress(moduleBase, &tSize));
for (DWORD i = 0; i <= 5038; i++)
{
/*
PRUNTIME_FUNCTION rtft = (PRUNTIME_FUNCTION)(imageExportDirectory + 0xc*i);
*/
printf("Runtime Function %u \n", i);
printf(" Begin Address 0x%p\n End Address 0x%p\n Unwind Info Address 0x%p\n",
(PVOID)pRuntimeFunctionTable[i].BeginAddress,
(PVOID)pRuntimeFunctionTable[i].EndAddress,
(PVOID)pRuntimeFunctionTable[i].UnwindInfoAddress);
PrintUnwindInfo(moduleBase, (PVOID)pRuntimeFunctionTable[i].UnwindData);
}
// printf(BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(UBYTE(UNW_FLAG_CHAININFO | UNW_FLAG_UHANDLER| UNW_FLAG_EHANDLER )));
}
PIMAGE_RUNTIME_FUNCTION_ENTRY RTFindFunctionByAddress(UINT64 moduleBase, DWORD64 functionOffset) {
DWORD tSize;
PRUNTIME_FUNCTION pRuntimeFunctionTable;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
pRuntimeFunctionTable = (PRUNTIME_FUNCTION)(GetExceptionDirectoryAddress((HMODULE)moduleBase, &tSize));
pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(GetExportDirectoryAddress((HMODULE)moduleBase));
for (DWORD i = 0; i < pImageExportDirectory->NumberOfFunctions; i++)
{
// printf("0x%X - 0x%X\n", pRuntimeFunctionTable[i].BeginAddress, functionOffset);
if (pRuntimeFunctionTable[i].BeginAddress == functionOffset) {
printf("\n Runtime Function (0x%p, 0x%p)\n Unwind Info Address: 0x%p\n",
(PVOID)pRuntimeFunctionTable[i].BeginAddress,
(PVOID)pRuntimeFunctionTable[i].EndAddress,
(PVOID)pRuntimeFunctionTable[i].UnwindInfoAddress);
return pRuntimeFunctionTable + i;
}
}
return NULL;
}
PIMAGE_RUNTIME_FUNCTION_ENTRY RTFindFunctionByIndex(UINT64 kernelBase, DWORD index) {
DWORD tSize;
PRUNTIME_FUNCTION pRuntimeFunctionTable;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
pRuntimeFunctionTable = (PRUNTIME_FUNCTION)(GetExceptionDirectoryAddress((HMODULE)kernelBase, &tSize));
pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(GetExportDirectoryAddress((HMODULE)kernelBase));
return pRuntimeFunctionTable + index;
}
DWORD FindRTFunctionsUnwind(HMODULE moduleBase, PVOID tUnwindCodeAddress) {
DWORD tSize;
PUNWIND_CODE tUnwindCode;
PUNWIND_INFO unwindInfo;
PRUNTIME_FUNCTION pRuntimeFunctionTable;
tUnwindCode = (PUNWIND_CODE)tUnwindCodeAddress;
pRuntimeFunctionTable = (PRUNTIME_FUNCTION)(GetExceptionDirectoryAddress(moduleBase, &tSize));
for (DWORD i = 0; i <= 5038; i++)
{
unwindInfo = (PUNWIND_INFO)((UINT64)moduleBase + (DWORD)pRuntimeFunctionTable[i].UnwindData);
for (int j = 0; j < unwindInfo->CountOfCodes; j++) {
if (unwindInfo->UnwindCode[j].FrameOffset == tUnwindCode->FrameOffset) {
printf("Found frame offset with Runtime Function: %u, unwindCode: %u \n", i + 1, j);
printf("Found: 0x%x - Expected: 0x%x \n", unwindInfo->UnwindCode[j].FrameOffset, tUnwindCode->FrameOffset);
printf("Address in module: 0x%p \n", (PVOID)((UINT64)moduleBase + (DWORD)pRuntimeFunctionTable[i].BeginAddress));
return i;
}
// TODO: Implement the rest after
}
}
printf("Function not found\n");
return 0;
}
void usage()
{
printf("\n Unwind Inspector v%f \n", VERSION);
printf("\n Made with <3 by %s \n\n", AUTHOR);
printf(" Mandatory args: \n"
" -m <module>: Target DLL\n"
" -f <function>: Target Function\n"
" -a <function-address>: Target Function Address\n"
);
printf("\n\n");
}
int wmain(int argc, wchar_t** argv)
{
LPCWSTR moduleName = NULL;
LPCWSTR functionName = NULL;
UINT64 functionAddress = NULL;
char functionNameA[MAX_PATH] = {0};
HMODULE moduleBase = NULL;
PVOID functionPtr = NULL;
PERF targetFp = NULL;
while ((argc > 1) && (argv[1][0] == '-'))
{
switch (argv[1][1])
{
case 'f':
++argv;
--argc;
functionName = argv[1];
if (wcslen(argv[1]) == 0) {
usage();
return -1;
}
break;
case 'a':
++argv;
--argc;
if (wcslen(argv[1]) == 0) {
usage();
return -1;
}
functionAddress = (UINT64)wcstoll(argv[1], NULL, 16);
break;
case 'm':
++argv;
--argc;
if (wcslen(argv[1]) == 0) {
usage();
return -1;
}
moduleName = argv[1];
break;
case 'h':
usage();
return -1;
break;
default:
printf("[-] Wrong Argument: %ls\n", argv[1]);
usage();
return -1;
}
++argv;
--argc;
}
if ((NULL == functionName && NULL == functionAddress) || NULL == moduleName) {
usage();
return -1;
}
moduleBase = LoadLibraryW(moduleName);
if (NULL == moduleBase) {
printf("[-] Module %ws not found. Aborting\n", moduleName);
return -1;
}
if (NULL == functionAddress){
size_t bytesCopied;
wcstombs_s(&bytesCopied, (char*)functionNameA, MAX_PATH, (const wchar_t*)functionName, MAX_PATH - 1);
functionPtr = (PVOID)GetProcAddress(moduleBase, (LPCSTR)functionNameA);
if (NULL == functionPtr) {
printf("[-] Function %s not found. Aborting\n", (LPCSTR)functionNameA);
return -1;
}
}
else {
printf("[*] Using function address 0x%I64x\n", functionAddress);
functionPtr = (PVOID)functionAddress;
}
targetFp = RTFindFunctionByAddress((UINT64)moduleBase, (DWORD64)functionPtr - (DWORD64)moduleBase);
if (NULL == targetFp) {
printf("[-] Function %s not found in Runtime Function Table. Aborting\n", (LPCSTR)functionNameA);
return -1;
}
PrintUnwindInfo(moduleBase, (PVOID)targetFp->UnwindData);
}
+140
View File
@@ -0,0 +1,140 @@
<?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>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{e86abdaa-444c-409a-b466-9e034e859c80}</ProjectGuid>
<RootNamespace>UnwindInspector</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="UnwindInspector.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\AddressHunter.h" />
<ClInclude Include="include\Common.h" />
<ClInclude Include="include\Functions.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,33 @@
<?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="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="UnwindInspector.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\AddressHunter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Functions.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
+356
View File
@@ -0,0 +1,356 @@
// https://raw.githubusercontent.com/paranoidninja/PIC-Get-Privileges/main/addresshunter.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <windows.h>
#include <inttypes.h>
#define DEREF( name )*(UINT_PTR *)(name)
#define DEREF_64( name )*(DWORD64 *)(name)
#define DEREF_32( name )*(DWORD *)(name)
#define DEREF_16( name )*(WORD *)(name)
#define DEREF_8( name )*(BYTE *)(name)
#define KERNELBASE_HASH 0xc42f2982
#define KERNEL32DLL_HASH 0xbc5d4571
#define MSVCRTDLL_HASH 0xc3222c90
#define ADVAPI32DLL_HASH 0x8353484b
#define NTDLL_HASH 0x4f576ca1
#define FH_RND_SEED 0xDC072B8A
#define ROL8(v) (v << 8 | v >> 24)
#define ROR8(v) (v >> 8 | v << 24)
#define ROX8(v) ((FH_RND_SEED % 2) ? ROL8(v) : ROR8(v))
//redefine UNICODE_STR struct
typedef struct _UNICODE_STR
{
USHORT Length;
USHORT MaximumLength;
PWSTR pBuffer;
} UNICODE_STR, * PUNICODE_STR;
//redefine PEB_LDR_DATA struct
typedef struct _PEB_LDR_DATA
{
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
//redefine LDR_DATA_TABLE_ENTRY struct
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STR FullDllName;
UNICODE_STR BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
//redefine PEB_FREE_BLOCK struct
typedef struct _PEB_FREE_BLOCK
{
struct _PEB_FREE_BLOCK* pNext;
DWORD dwSize;
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
//redefine PEB struct
typedef struct __PEB
{
BYTE bInheritedAddressSpace;
BYTE bReadImageFileExecOptions;
BYTE bBeingDebugged;
BYTE bSpareBool;
LPVOID lpMutant;
LPVOID lpImageBaseAddress;
PPEB_LDR_DATA pLdr;
LPVOID lpProcessParameters;
LPVOID lpSubSystemData;
LPVOID lpProcessHeap;
PRTL_CRITICAL_SECTION pFastPebLock;
LPVOID lpFastPebLockRoutine;
LPVOID lpFastPebUnlockRoutine;
DWORD dwEnvironmentUpdateCount;
LPVOID lpKernelCallbackTable;
DWORD dwSystemReserved;
DWORD dwAtlThunkSListPtr32;
PPEB_FREE_BLOCK pFreeList;
DWORD dwTlsExpansionCounter;
LPVOID lpTlsBitmap;
DWORD dwTlsBitmapBits[2];
LPVOID lpReadOnlySharedMemoryBase;
LPVOID lpReadOnlySharedMemoryHeap;
LPVOID lpReadOnlyStaticServerData;
LPVOID lpAnsiCodePageData;
LPVOID lpOemCodePageData;
LPVOID lpUnicodeCaseTableData;
DWORD dwNumberOfProcessors;
DWORD dwNtGlobalFlag;
LARGE_INTEGER liCriticalSectionTimeout;
DWORD dwHeapSegmentReserve;
DWORD dwHeapSegmentCommit;
DWORD dwHeapDeCommitTotalFreeThreshold;
DWORD dwHeapDeCommitFreeBlockThreshold;
DWORD dwNumberOfHeaps;
DWORD dwMaximumNumberOfHeaps;
LPVOID lpProcessHeaps;
LPVOID lpGdiSharedHandleTable;
LPVOID lpProcessStarterHelper;
DWORD dwGdiDCAttributeList;
LPVOID lpLoaderLock;
DWORD dwOSMajorVersion;
DWORD dwOSMinorVersion;
WORD wOSBuildNumber;
WORD wOSCSDVersion;
DWORD dwOSPlatformId;
DWORD dwImageSubsystem;
DWORD dwImageSubsystemMajorVersion;
DWORD dwImageSubsystemMinorVersion;
DWORD dwImageProcessAffinityMask;
DWORD dwGdiHandleBuffer[34];
LPVOID lpPostProcessInitRoutine;
LPVOID lpTlsExpansionBitmap;
DWORD dwTlsExpansionBitmapBits[32];
DWORD dwSessionId;
ULARGE_INTEGER liAppCompatFlags;
ULARGE_INTEGER liAppCompatFlagsUser;
LPVOID lppShimData;
LPVOID lpAppCompatInfo;
UNICODE_STR usCSDVersion;
LPVOID lpActivationContextData;
LPVOID lpProcessAssemblyStorageMap;
LPVOID lpSystemDefaultActivationContextData;
LPVOID lpSystemAssemblyStorageMap;
DWORD dwMinimumStackCommit;
} _PEB, * _PPEB;
DWORD HashModule(PCSTR ModuleName, size_t length)
{
DWORD i = 0;
DWORD Hash = FH_RND_SEED;
while (i < length / 2)
{
WORD PartialName = *(WORD*)((ULONG64)ModuleName + i++) | 0x20202020;
Hash ^= PartialName + ROR8(Hash);
}
return Hash;
}
// function to fetch the base address of a Mmodule from the Process Environment Block
UINT64 GetModule(DWORD TargetHash) {
ULONG_PTR dll, val1;
PWSTR val2;
USHORT usCounter;
// We want to stop when we find this
DWORD firstHash = 0;
// PEB is at 0x60 offset and __readgsqword is compiler intrinsic,
// so we don't need to extract it's symbol
dll = __readgsqword(0x60);
dll = (ULONG_PTR)((_PPEB)dll)->pLdr;
val1 = (ULONG_PTR)((PPEB_LDR_DATA)dll)->InMemoryOrderModuleList.Flink;
while (NULL != val1) {
val2 = (PWSTR)((PLDR_DATA_TABLE_ENTRY)val1)->BaseDllName.pBuffer;
usCounter = (USHORT)((PLDR_DATA_TABLE_ENTRY)val1)->BaseDllName.Length;
//calculate the hash of kernel32.dll
DWORD Hash = HashModule((PCSTR)val2, usCounter);
if (firstHash == 0) {
firstHash = Hash;
}
else if (firstHash == Hash) {
break;
}
//wprintf(L"%s: %u\n --> Hash: %x - Target: %x\n", (WCHAR*)val2, usCounter, Hash, TargetHash);
// compare the hash kernel32.dll
if (Hash == TargetHash) {
//return kernel32.dll if found
dll = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)val1)->DllBase;
return dll;
}
val1 = DEREF(val1);
}
return 0;
}
// custom strcmp function since this function will be called by GetSymbolAddress
// which means we have to call strcmp before loading msvcrt.dll
// so we are writing our own my_strcmp so that we don't have to play with egg or chicken dilemma
int my_strcmp(const char* p1, const char* p2) {
const unsigned char* s1 = (const unsigned char*)p1;
const unsigned char* s2 = (const unsigned char*)p2;
unsigned char c1, c2;
do {
c1 = (unsigned char)*s1++;
c2 = (unsigned char)*s2++;
if (c1 == '\0') {
return c1 - c2;
}
} while (c1 == c2);
return c1 - c2;
}
UINT64 GetSymbolAddress(HMODULE hModule, LPCSTR lpProcName) {
UINT64 dllAddress = (UINT64)hModule,
symbolAddress = 0,
exportedAddressTable = 0,
namePointerTable = 0,
ordinalTable = 0;
if (hModule == NULL) {
return 0;
}
PIMAGE_NT_HEADERS ntHeaders = NULL;
PIMAGE_DATA_DIRECTORY dataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
ntHeaders = (PIMAGE_NT_HEADERS)(dllAddress + ((PIMAGE_DOS_HEADER)dllAddress)->e_lfanew);
dataDirectory = (PIMAGE_DATA_DIRECTORY)&ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllAddress + dataDirectory->VirtualAddress);
exportedAddressTable = (dllAddress + exportDirectory->AddressOfFunctions);
namePointerTable = (dllAddress + exportDirectory->AddressOfNames);
ordinalTable = (dllAddress + exportDirectory->AddressOfNameOrdinals);
if (((UINT64)lpProcName & 0xFFFF0000) == 0x00000000) {
exportedAddressTable += ((IMAGE_ORDINAL((UINT64)lpProcName) - exportDirectory->Base) * sizeof(DWORD));
symbolAddress = (UINT64)(dllAddress + DEREF_32(exportedAddressTable));
}
else {
DWORD dwCounter = exportDirectory->NumberOfNames;
while (dwCounter--) {
char* cpExportedFunctionName = (char*)(dllAddress + DEREF_32(namePointerTable));
if (my_strcmp(cpExportedFunctionName, lpProcName) == 0) {
exportedAddressTable += (DEREF_16(ordinalTable) * sizeof(DWORD));
symbolAddress = (UINT64)(dllAddress + DEREF_32(exportedAddressTable));
break;
}
namePointerTable += sizeof(DWORD);
ordinalTable += sizeof(WORD);
}
}
return symbolAddress;
}
UINT64 GetSymbolOffset(HMODULE hModule, LPCSTR lpProcName) {
UINT64 dllAddress = (UINT64)hModule,
symbolAddress = 0,
exportedAddressTable = 0,
namePointerTable = 0,
ordinalTable = 0;
if (hModule == NULL) {
return 0;
}
PIMAGE_NT_HEADERS ntHeaders = NULL;
PIMAGE_DATA_DIRECTORY dataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
ntHeaders = (PIMAGE_NT_HEADERS)(dllAddress + ((PIMAGE_DOS_HEADER)dllAddress)->e_lfanew);
dataDirectory = (PIMAGE_DATA_DIRECTORY)&ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllAddress + dataDirectory->VirtualAddress);
exportedAddressTable = (dllAddress + exportDirectory->AddressOfFunctions);
namePointerTable = (dllAddress + exportDirectory->AddressOfNames);
ordinalTable = (dllAddress + exportDirectory->AddressOfNameOrdinals);
if (((UINT64)lpProcName & 0xFFFF0000) == 0x00000000) {
exportedAddressTable += ((IMAGE_ORDINAL((UINT64)lpProcName) - exportDirectory->Base) * sizeof(DWORD));
symbolAddress = (UINT64)DEREF_32(exportedAddressTable);
}
else {
DWORD dwCounter = exportDirectory->NumberOfNames;
while (dwCounter--) {
char* cpExportedFunctionName = (char*)(dllAddress + DEREF_32(namePointerTable));
if (my_strcmp(cpExportedFunctionName, lpProcName) == 0) {
exportedAddressTable += (DEREF_16(ordinalTable) * sizeof(DWORD));
symbolAddress = (UINT64)DEREF_32(exportedAddressTable);
break;
}
namePointerTable += sizeof(DWORD);
ordinalTable += sizeof(WORD);
}
}
return symbolAddress;
}
char* GetSymbolNameByOffset(HMODULE hModule, UINT64 offset) {
UINT64 dllAddress = (UINT64)hModule,
symbolAddress = 0;
if (hModule == NULL) {
return 0;
}
PIMAGE_NT_HEADERS ntHeaders = NULL;
PIMAGE_DATA_DIRECTORY dataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
ntHeaders = (PIMAGE_NT_HEADERS)(dllAddress + ((PIMAGE_DOS_HEADER)dllAddress)->e_lfanew);
dataDirectory = (PIMAGE_DATA_DIRECTORY)&ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllAddress + dataDirectory->VirtualAddress);
LPDWORD exportedAddressTable = (LPDWORD)(dllAddress + exportDirectory->AddressOfFunctions);
LPDWORD namePointerTable = (LPDWORD)(dllAddress + exportDirectory->AddressOfNames);
LPWORD ordinalTable = (LPWORD)(dllAddress + exportDirectory->AddressOfNameOrdinals);
char* currProcName;
for (SIZE_T i = 0; i < exportDirectory->NumberOfNames; i++) {
// Get current function name
currProcName = (LPSTR)((LPBYTE)hModule + namePointerTable[i]);
// Get current function address
if (exportedAddressTable[ordinalTable[i]] == offset) {
return currProcName;
}
}
return NULL;
}
PVOID GetExceptionDirectoryAddress(HMODULE hModule, DWORD* tSize)
{
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD64)hModule + dosHeader->e_lfanew);
DWORD64 exceptionDirectoryRVA = ntHeader->OptionalHeader.DataDirectory[3].VirtualAddress;
*tSize = ntHeader->OptionalHeader.DataDirectory[3].Size;
DWORD64 imageExceptionDirectory = (DWORD64)((DWORD_PTR)hModule + exceptionDirectoryRVA);
return (PVOID)imageExceptionDirectory;
}
PVOID GetExportDirectoryAddress(HMODULE hModule)
{
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD64)hModule + dosHeader->e_lfanew);
DWORD_PTR exportDirectoryRVA = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
DWORD64 imageExportDirectory = (DWORD64)((DWORD_PTR)hModule + exportDirectoryRVA);
return (PVOID)imageExportDirectory;
}
+319
View File
@@ -0,0 +1,319 @@
#pragma once
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED
#include <Windows.h>
#include <psapi.h>
#include <dbghelp.h>
#include <stdio.h>
#include <stdlib.h>
#include "AddressHunter.h"
#define VERSION 0.1
#define AUTHOR "KlezVirus"
#define MAX_FRAMES 154
// Remove if you have a self-made definition of memcmp
#define MemCompare memcmp
// Removing malloc deps
#undef malloc
#define malloc(x) HeapAlloc(GetProcessHeap(), 0, x)
#undef realloc
#define realloc(x,s) HeapReAlloc(GetProcessHeap(), 0, x, s)
#undef free
#define free(x) HeapFree(GetProcessHeap(), 0, x)
// Removing memset deps
void* custom_memset(void* dest, int c, size_t count);
#ifdef _DEBUG
#define DPRINT(...) { printf(__VA_ARGS__); }
#else
#define DPRINT(...) {}
#endif
#define HIDWORD(l) ((DWORD)(((DWORDLONG)(l)>>32)&0xFFFFFFFF))
#define BitVal(data,y) ( (data>>y) & 1)
#define BitChainInfo(data) BitVal(data, 2)
#define BitUHandler(data) BitVal(data, 1)
#define BitEHandler(data) BitVal(data, 0)
#define Version(data) BitVal(data, 4)*2 + BitVal(data, 3)
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define B2BP BYTE_TO_BINARY_PATTERN
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
typedef UCHAR UBYTE;
typedef PIMAGE_RUNTIME_FUNCTION_ENTRY PERF;
typedef enum _REGISTERS {
RAX = 0,
RCX,
RDX,
RBX,
RSP,
RBP,
RSI,
RDI,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15
} REGISTERS;
typedef union _UNWIND_CODE {
struct {
UBYTE CodeOffset; // 0xFF00
UBYTE UnwindOp : 4; // 0x000f OPCODE
UBYTE OpInfo : 4; // 0x00f0
};
USHORT FrameOffset;
} UNWIND_CODE, * PUNWIND_CODE;
typedef struct _UNWIND_INFO {
UBYTE Version : 3;
UBYTE Flags : 5; // 4 bytes
UBYTE SizeOfProlog; // 4 bytes
UBYTE CountOfCodes; // 4 bytes
UBYTE FrameRegister : 4;
UBYTE FrameOffset : 4; // 4bytes
UNWIND_CODE UnwindCode[1];
union {
OPTIONAL ULONG ExceptionHandler;
OPTIONAL ULONG FunctionEntry;
};
OPTIONAL ULONG ExceptionData[];
} UNWIND_INFO, * PUNWIND_INFO;
#define GetUnwindCodeEntry(info, index) \
((info)->UnwindCode[index])
#define GetLanguageSpecificDataPtr(info) \
((PVOID)&GetUnwindCodeEntry((info),((info)->CountOfCodes + 1) & ~1))
#define GetExceptionHandler(base, info) \
((PEXCEPTION_ROUTINE)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
#define GetChainedFunctionEntry(base, info) \
((PRUNTIME_FUNCTION)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
#define GetExceptionDataPtr(info) \
((PVOID)((PULONG)GetLanguageSpecificDataPtr(info) + 1))
#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64)
#define ADDRESS ADDRESS64
#define LPADDRESS LPADDRESS64
#else
typedef struct _tagADDRESS {
DWORD Offset;
WORD Segment;
ADDRESS_MODE Mode;
} ADDRESS, * LPADDRESS;
#endif
typedef struct _MIN_CTX {
DWORD64 Rax;
DWORD64 Rcx;
DWORD64 Rdx;
DWORD64 Rbx;
DWORD64 Rsp;
DWORD64 Rbp;
DWORD64 Rsi;
DWORD64 Rdi;
DWORD64 R8;
DWORD64 R9;
DWORD64 R10;
DWORD64 R11;
DWORD64 R12;
DWORD64 R13;
DWORD64 R14;
DWORD64 R15;
DWORD64 Rip;
DWORD64 Reserved;
DWORD64 StackSize;
} MIN_CTX, *PMIN_CTX;
typedef enum _UNWIND_OP_CODES {
// x86_64. https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64.
UWOP_PUSH_NONVOL = 0,
UWOP_ALLOC_LARGE, // 1
UWOP_ALLOC_SMALL, // 2
UWOP_SET_FPREG, // 3
UWOP_SAVE_NONVOL, // 4
UWOP_SAVE_NONVOL_BIG, // 5
UWOP_EPILOG, // 6
UWOP_SPARE_CODE, // 7
UWOP_SAVE_XMM128, // 8
UWOP_SAVE_XMM128BIG, // 9
UWOP_PUSH_MACH_FRAME, // 10
// ARM64. https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
UWOP_ALLOC_MEDIUM,
UWOP_SAVE_R19R20X,
UWOP_SAVE_FPLRX,
UWOP_SAVE_FPLR,
UWOP_SAVE_REG,
UWOP_SAVE_REGX,
UWOP_SAVE_REGP,
UWOP_SAVE_REGPX,
UWOP_SAVE_LRPAIR,
UWOP_SAVE_FREG,
UWOP_SAVE_FREGX,
UWOP_SAVE_FREGP,
UWOP_SAVE_FREGPX,
UWOP_SET_FP,
UWOP_ADD_FP,
UWOP_NOP,
UWOP_END,
UWOP_SAVE_NEXT,
UWOP_TRAP_FRAME,
UWOP_CONTEXT,
UWOP_CLEAR_UNWOUND_TO_CALL,
// ARM: https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
UWOP_ALLOC_HUGE,
UWOP_WIDE_ALLOC_MEDIUM,
UWOP_WIDE_ALLOC_LARGE,
UWOP_WIDE_ALLOC_HUGE,
UWOP_WIDE_SAVE_REG_MASK,
UWOP_WIDE_SAVE_SP,
UWOP_SAVE_REGS_R4R7LR,
UWOP_WIDE_SAVE_REGS_R4R11LR,
UWOP_SAVE_FREG_D8D15,
UWOP_SAVE_REG_MASK,
UWOP_SAVE_LR,
UWOP_SAVE_FREG_D0D15,
UWOP_SAVE_FREG_D16D31,
UWOP_WIDE_NOP, // UWOP_NOP
UWOP_END_NOP, // UWOP_END
UWOP_WIDE_END_NOP,
// Custom implementation opcodes (implementation specific).
UWOP_CUSTOM,
} UNWIND_OP_CODES;
// Stack allocations use UOP_AllocSmall, UOP_AllocLarge from above, plus
// the following. AllocSmall, AllocLarge and AllocHuge represent a 16 bit
// instruction, while the WideAlloc* opcodes represent a 32 bit instruction.
// Small can represent a stack offset of 0x7f*4 (252) bytes, Medium can
// represent up to 0x3ff*4 (4092) bytes, Large up to 0xffff*4 (262140) bytes,
// and Huge up to 0xffffff*4 (67108860) bytes.
#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64)
#define STACKFRAME STACKFRAME64
#define LPSTACKFRAME LPSTACKFRAME64
#else
typedef struct _tagSTACKFRAME {
ADDRESS AddrPC;
ADDRESS AddrReturn;
ADDRESS AddrFrame;
ADDRESS AddrStack;
PVOID FuncTableEntry;
DWORD Params[4];
BOOL Far;
BOOL Virtual;
DWORD Reserved[3];
KDHELP KdHelp;
ADDRESS AddrBStore;
} STACKFRAME, * LPSTACKFRAME;
#endif
BYTE ExtractOpInfo(BYTE OpIC) {
return OpIC >> 4;
}
BYTE ExtractOpCode(BYTE OpIC) {
return OpIC & 0x0F;
}
char* GetOpInfo(int op) {
char* reg = (char*)malloc(4);
if (reg == NULL) {
return NULL;
}
custom_memset(reg, 0, 4);
if(op == 0) {
memcpy(reg, "RAX", 4);
}
else if(op == 1) {
memcpy(reg, "RCX", 4);
}
else if(op == 2) {
memcpy(reg, "RDX", 4);
}
else if(op == 3) {
memcpy(reg, "RBX", 4);
}
else if(op == 4) {
memcpy(reg, "RSP", 4);
}
else if(op == 5) {
memcpy(reg, "RBP", 4);
}
else if(op == 6) {
memcpy(reg, "RSI", 4);
}
else if(op == 7) {
memcpy(reg, "RDI", 4);
}
else if(op == 8) {
memcpy(reg, "R8\0", 4);
}
else if(op == 9) {
memcpy(reg, "R9\0", 4);
}
else if(op == 10) {
memcpy(reg, "R10", 4);
}
else if(op == 11) {
memcpy(reg, "R11", 4);
}
else if(op == 12) {
memcpy(reg, "R12", 4);
}
else if(op == 13) {
memcpy(reg, "R13", 4);
}
else if(op == 14) {
memcpy(reg, "R14", 4);
}
else if(op == 15) {
memcpy(reg, "R15", 4);
}
return reg;
}
void* custom_memset(void* dest, int val, size_t len) {
for (char* dst = (char*)dest; len != 0; len--) {
*dst++ = val;
}
return dest;
}
#endif
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include "Windows.h"
#ifdef _DEBUG
#define DPRINTUNWINDCODE(x) { \
printf("0x%x\t", x->CodeOffset); \
printf("0x%x\t", x->OpInfo); \
printf("0x%x\n", x->UnwindOp); \
}
#else
#define DPRINTUNWINDCODE(x) {}
#endif
#ifdef _DEBUG
#ifdef _VERBOSE_DEBUG
#define DPRINTCTX(x) { \
printf("RAX: 0x%llx -", x.Rax); \
printf("RBX :0x%llx -", x.Rbx); \
printf("RCX: 0x%llx -", x.Rcx); \
printf("RDX: 0x%llx -", x.Rdx); \
printf("RDI: 0x%llx -", x.Rdi); \
printf("RSI: 0x%llx -", x.Rsi); \
printf("RBP: 0x%llx -", x.Rbp); \
printf("RSP: 0x%llx -\n", x.Rsp); \
printf("R8 : 0x%llx -", x.R8 ); \
printf("R9 : 0x%llx -", x.R9 ); \
printf("R10: 0x%llx -", x.R10); \
printf("R11: 0x%llx -", x.R11); \
printf("R12: 0x%llx -", x.R12); \
printf("R13: 0x%llx -", x.R13); \
printf("R14: 0x%llx -", x.R14); \
printf("R15: 0x%llx \n", x.R15); \
printf("RIP: 0x%llx \n", x.Rip); \
}
#else
#define DPRINTCTX(x) {}
#endif
#else
#define DPRINTCTX(x) {}
#endif
typedef SIZE_T(WINAPI* VirtualQueryType)(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
typedef HANDLE(WINAPI* OpenProcessType)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
typedef DWORD(WINAPI* GetCurrentProcessIdType)();
PIMAGE_RUNTIME_FUNCTION_ENTRY RTFindFunctionByAddress(UINT64, DWORD64);
PIMAGE_RUNTIME_FUNCTION_ENTRY RTFindFunctionByIndex(UINT64, DWORD);
DWORD GetStackFrameSize(HMODULE, PVOID, DWORD*);
DWORD GetStackFrameSizeWhereRbpIsPushedOnStack(HMODULE, PVOID, DWORD*);
DWORD GetStackFrameSizeIgnoringUwopSetFpreg(HMODULE, PVOID, DWORD*);
void PrintUnwindInfo(HMODULE, PVOID);
void LookupSymbolFromRTIndex(HMODULE, int, bool);
void EnumAllRTFunctions(HMODULE);
DWORD FindRTFunctionsUnwind(HMODULE, PVOID);
VOID FindGadget(HMODULE moduleBase, PERF pRuntimeFunctionTable, DWORD rtLastIndex, PDWORD stackSize, PDWORD prtSaveIndex, PDWORD skip, DWORD gadgetType);
DWORD FindProlog(HMODULE moduleBase, PERF pRuntimeFunctionTable, DWORD rtLastIndex, PDWORD stackSize, PDWORD prtSaveIndex, PDWORD skip, PDWORD64 rtTargetOffset);
DWORD FindPopRbp(HMODULE moduleBase, PERF pRuntimeFunctionTable, DWORD rtLastIndex, PDWORD stackSize, PDWORD prtSaveIndex, PDWORD skip, PDWORD64 rtTargetOffset);
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include "Windows.h"
void TestLocateFunctionByAddress();
void TestLookupByFrameOffset();
void TestEnumAllRT(DWORD);
void Test();
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB