archive: add 5 repo prompt(s) [skip ci]

This commit is contained in:
github-actions[bot]
2026-02-24 13:46:32 +00:00
parent e1138fd7ea
commit b549120fbd
5 changed files with 7573 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+536
View File
@@ -0,0 +1,536 @@
Project Path: arc_evilashz_ProxyAPICall_3b1dqtjo
Source Tree:
```txt
arc_evilashz_ProxyAPICall_3b1dqtjo
├── ProxyAPICall.cpp
├── ProxyAPICall.sln
├── ProxyAPICall.vcxproj
├── README.md
└── stub.h
```
`ProxyAPICall.cpp`:
```cpp
#include <windows.h>
#include <tuple>
#include <map>
#include <stdio.h>
#include "stub.h"
char* WorkCallbackArgAddr = NULL;
int offset = 0;
template<class Tuple, std::size_t N>
struct TuplePrinter {
static void operate(const Tuple& t)
{
TuplePrinter<Tuple, N - 1>::operate(t);
memcpy(WorkCallbackArgAddr + offset, &std::get<N - 1>(t), sizeof(char*));
offset += sizeof(char*);
}
};
template<class Tuple>
struct TuplePrinter<Tuple, 1> {
static void operate(const Tuple& t)
{
memcpy(WorkCallbackArgAddr + offset, &std::get<0>(t), sizeof(char*));
offset += sizeof(char*);
}
};
template<class... Args>
void OperateTuple(const std::tuple<Args...>& t){
TuplePrinter<decltype(t), sizeof...(Args)>::operate(t);
}
template<typename... ServiceArgs>
uint32_t ProxyCall(ServiceArgs... args) {
//Init
FARPROC pTpAllocWork = GetProcAddress(GetModuleHandleA("ntdll"), "TpAllocWork");
FARPROC pTpPostWork = GetProcAddress(GetModuleHandleA("ntdll"), "TpPostWork");
FARPROC pTpReleaseWork = GetProcAddress(GetModuleHandleA("ntdll"), "TpReleaseWork");
//Init Call Stub Map
std::map<int, unsigned char*> stub_map;
stub_map.insert(std::make_pair(1, WorkCallback_stub_arg_1));
stub_map.insert(std::make_pair(2, WorkCallback_stub_arg_2));
stub_map.insert(std::make_pair(3, WorkCallback_stub_arg_3));
stub_map.insert(std::make_pair(4, WorkCallback_stub_arg_4));
stub_map.insert(std::make_pair(5, WorkCallback_stub_arg_5));
stub_map.insert(std::make_pair(6, WorkCallback_stub_arg_6));
stub_map.insert(std::make_pair(7, WorkCallback_stub_arg_7));
stub_map.insert(std::make_pair(8, WorkCallback_stub_arg_8));
stub_map.insert(std::make_pair(9, WorkCallback_stub_arg_9));
stub_map.insert(std::make_pair(10, WorkCallback_stub_arg_10));
stub_map.insert(std::make_pair(11, WorkCallback_stub_arg_11));
std::size_t argsize = sizeof...(ServiceArgs);
auto data = std::make_tuple(std::forward<ServiceArgs>(args)...);
std::size_t argBufferSize = argsize * sizeof(char*);
WorkCallbackArgAddr = (char*)malloc(argBufferSize);
memset(WorkCallbackArgAddr, 0x00, argBufferSize);
//operate args
OperateTuple(data);
//locate args num
auto maplocation = stub_map.find(argsize);
unsigned char* WorkCallback_stub = maplocation->second;
PTP_WORK WorkReturn = NULL;
((TPALLOCWORK)pTpAllocWork)(&WorkReturn, (PTP_WORK_CALLBACK)WorkCallback_stub, WorkCallbackArgAddr, NULL);
((TPPOSTWORK)pTpPostWork)(WorkReturn);
((TPRELEASEWORK)pTpReleaseWork)(WorkReturn);
WaitForSingleObject((HANDLE)-1, 0x1000);
free(WorkCallbackArgAddr);
return 0;
}
int main()
{
void* allocation = nullptr;
SIZE_T size = 0x1000;
UINT_PTR pNtAllocateVirtualMemory = (UINT_PTR)GetProcAddress(GetModuleHandleA("ntdll"), "NtAllocateVirtualMemory");
ProxyCall(pNtAllocateVirtualMemory,
(ULONG_PTR) -1,
&allocation,
(ULONG_PTR) 0,
&size,
(ULONG_PTR)MEM_RESERVE | MEM_COMMIT,
(ULONG_PTR)PAGE_READWRITE);
printf("allocatedAddress: %p\n", allocation);
}
```
`ProxyAPICall.sln`:
```sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33103.184
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProxyAPICall", "ProxyAPICall.vcxproj", "{80B8E19E-68DE-484B-8B5C-A03E499BD646}"
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
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Debug|x64.ActiveCfg = Debug|x64
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Debug|x64.Build.0 = Debug|x64
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Debug|x86.ActiveCfg = Debug|Win32
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Debug|x86.Build.0 = Debug|Win32
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Release|x64.ActiveCfg = Release|x64
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Release|x64.Build.0 = Release|x64
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Release|x86.ActiveCfg = Release|Win32
{80B8E19E-68DE-484B-8B5C-A03E499BD646}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F063D57C-BB40-4366-BB1E-57C5AF57A24B}
EndGlobalSection
EndGlobal
```
`ProxyAPICall.vcxproj`:
```vcxproj
<?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>{80b8e19e-68de-484b-8b5c-a03e499bd646}</ProjectGuid>
<RootNamespace>ProxyAPICall</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="ProxyAPICall.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stub.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
```
`README.md`:
```md
# ProxyAPICall
Just another version of the custom stack call from Proxy-Function-Calls-For-ETwTI
Support 1 to 11 args call
Compile in VisualStudio
### Study:
https://0xdarkvortex.dev/hiding-in-plainsight/
https://github.com/paranoidninja/Proxy-Function-Calls-For-ETwTI
```
`stub.h`:
```h
#pragma once
#include <windows.h>
//stub in .text section
#define ALLOC_ON_CODE \
_Pragma("section(\".text\")") \
__declspec(allocate(".text"))
typedef NTSTATUS(NTAPI* TPALLOCWORK)(PTP_WORK* ptpWrk, PTP_WORK_CALLBACK pfnwkCallback, PVOID OptionalArg, PTP_CALLBACK_ENVIRON CallbackEnvironment);
typedef VOID(NTAPI* TPPOSTWORK)(PTP_WORK);
typedef VOID(NTAPI* TPRELEASEWORK)(PTP_WORK);
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_1[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_2[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_3[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx + 0x18]
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_4[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx + 0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_5[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx + 0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx+0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_6[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx + 0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x30, // mov r10, QWORD PTR[rbx + 0x30]
0x4c, 0x89, 0x54, 0x24, 0x30, // mov QWORD PTR[rsp + 0x30], r10
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx + 0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_7[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx+0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x38, // mov r10, QWORD PTR[rbx + 0x38]
0x4c, 0x89, 0x54, 0x24, 0x38, // mov QWORD PTR[rsp + 0x38], r10
0x4c, 0x8b, 0x53, 0x30, // mov r10, QWORD PTR[rbx + 0x30]
0x4c, 0x89, 0x54, 0x24, 0x30, // mov QWORD PTR[rsp + 0x30], r10
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx + 0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_8[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx+0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x40, // mov r10, QWORD PTR[rbx + 0x40]
0x4c, 0x89, 0x54, 0x24, 0x40, // mov QWORD PTR[rsp + 0x40], r10
0x4c, 0x8b, 0x53, 0x38, // mov r10, QWORD PTR[rbx + 0x38]
0x4c, 0x89, 0x54, 0x24, 0x38, // mov QWORD PTR[rsp + 0x38], r10
0x4c, 0x8b, 0x53, 0x30, // mov r10, QWORD PTR[rbx + 0x30]
0x4c, 0x89, 0x54, 0x24, 0x30, // mov QWORD PTR[rsp + 0x30], r10
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx + 0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_9[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx+0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x48, // mov r10, QWORD PTR[rbx + 0x48]
0x4c, 0x89, 0x54, 0x24, 0x48, // mov QWORD PTR[rsp + 0x48], r10
0x4c, 0x8b, 0x53, 0x40, // mov r10, QWORD PTR[rbx + 0x40]
0x4c, 0x89, 0x54, 0x24, 0x40, // mov QWORD PTR[rsp + 0x40], r10
0x4c, 0x8b, 0x53, 0x38, // mov r10, QWORD PTR[rbx + 0x38]
0x4c, 0x89, 0x54, 0x24, 0x38, // mov QWORD PTR[rsp + 0x38], r10
0x4c, 0x8b, 0x53, 0x30, // mov r10, QWORD PTR[rbx + 0x30]
0x4c, 0x89, 0x54, 0x24, 0x30, // mov QWORD PTR[rsp + 0x30], r10
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx + 0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_10[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx+0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x50, // mov r10, QWORD PTR[rbx + 0x50]
0x4c, 0x89, 0x54, 0x24, 0x50, // mov QWORD PTR[rsp + 0x50], r10
0x4c, 0x8b, 0x53, 0x48, // mov r10, QWORD PTR[rbx + 0x48]
0x4c, 0x89, 0x54, 0x24, 0x48, // mov QWORD PTR[rsp + 0x48], r10
0x4c, 0x8b, 0x53, 0x40, // mov r10, QWORD PTR[rbx + 0x40]
0x4c, 0x89, 0x54, 0x24, 0x40, // mov QWORD PTR[rsp + 0x40], r10
0x4c, 0x8b, 0x53, 0x38, // mov r10, QWORD PTR[rbx + 0x38]
0x4c, 0x89, 0x54, 0x24, 0x38, // mov QWORD PTR[rsp + 0x38], r10
0x4c, 0x8b, 0x53, 0x30, // mov r10, QWORD PTR[rbx + 0x30]
0x4c, 0x89, 0x54, 0x24, 0x30, // mov QWORD PTR[rsp + 0x30], r10
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx + 0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
ALLOC_ON_CODE unsigned char WorkCallback_stub_arg_11[] = {
0x48, 0x89, 0xd3, // mov rbx, rdx
0x48, 0x8b, 0x03, // mov rax, QWORD PTR[rbx]
0x48, 0x8b, 0x4b, 0x08, // mov rcx, QWORD PTR[rbx + 0x8]
0x48, 0x8b, 0x53, 0x10, // mov rdx, QWORD PTR[rbx + 0x10]
0x4c, 0x8b, 0x43, 0x18, // mov r8, QWORD PTR[rbx+0x18]
0x4c, 0x8b, 0x4b, 0x20, // mov r9, QWORD PTR[rbx + 0x20]
0x4c, 0x8b, 0x53, 0x58, // mov r10, QWORD PTR[rbx + 0x58]
0x4c, 0x89, 0x54, 0x24, 0x58, // mov QWORD PTR[rsp + 0x58], r10
0x4c, 0x8b, 0x53, 0x48, // mov r10, QWORD PTR[rbx + 0x48]
0x4c, 0x89, 0x54, 0x24, 0x48, // mov QWORD PTR[rsp + 0x48], r10
0x4c, 0x8b, 0x53, 0x40, // mov r10, QWORD PTR[rbx + 0x40]
0x4c, 0x89, 0x54, 0x24, 0x40, // mov QWORD PTR[rsp + 0x40], r10
0x4c, 0x8b, 0x53, 0x38, // mov r10, QWORD PTR[rbx + 0x38]
0x4c, 0x89, 0x54, 0x24, 0x38, // mov QWORD PTR[rsp + 0x38], r10
0x4c, 0x8b, 0x53, 0x30, // mov r10, QWORD PTR[rbx + 0x30]
0x4c, 0x89, 0x54, 0x24, 0x30, // mov QWORD PTR[rsp + 0x30], r10
0x4c, 0x8b, 0x53, 0x28, // mov r10, QWORD PTR[rbx + 0x28]
0x4c, 0x89, 0x54, 0x24, 0x28, // mov QWORD PTR[rsp + 0x28], r10
0xff, 0xe0 // jmp rax
};
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+640
View File
@@ -0,0 +1,640 @@
Project Path: arc_susMdT_LoudSunRun_36ou4jif
Source Tree:
```txt
arc_susMdT_LoudSunRun_36ou4jif
├── Macros.h
├── README.md
├── Structs.h
├── Testing.c
└── test.asm
```
`Macros.h`:
```h
#pragma once
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) == 0)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define true 1
#define MAX_STACK_SIZE 12000
#define RBP_OP_INFO 0x5
```
`README.md`:
```md
# LoudSunRun
Stack Spoofing with Synthetic frames based on the work of namazso, SilentMoonWalk, and VulcanRaven
## Why?
Learning purposes
## Overview
There are a few steps this program does
1. Allocate args on stack
2. Generate fake frames
3. Prep syscall
4. Spoof the return address
5. Make the call
To perform these, a param struct is passed as arg 5 and the number of stack args is passed on arg 6. The param struct contains the following:
* address of the `jmp rbx` gadget
* the original return address (for the Spoof function to return to)
* the stack sizes of our fake frames and gadget
* the address we want our fake frames to show on the call stack
* a SSN for syscalls (if included/ommited for non indirect syscalls, it does not affect anything)
The total stack size of the fake frames is calculated and the stack args are moved accordingly. A 0 is pushed onto the stack. This cuts off the stack walk.
Frames are then added, but in reverse order of appearence on the stack. They are planted like so
1. Decrement stack pointer by the frame's size
2. Place the return address at the stack pointer
Then, the param struct is modified to "save" some information. The `fixup` function is loaded into the rbx, so when the function returns (to a `jmp rbx` gadget), it will land into `fixup`. Fixup then undoes all the funky stack pointer movement, restores the rbx, and jumps back to the OG return address.
## Implementation
A function can be called like so
```c
Spoof(arg1, arg2, arg3, arg4, &param, function, (PVOID)0);
```
Param is a struct containing some necessary information for the call to have fake frames added.
The 6th argument is a pointer to the function to execute
The 7th argument specifies the number of args to pass to the stack. It has to be at an 8 byte size.
Example of calling NtAllocateVirtualMemory with the indirect syscall method
```c
/////////////////////////////
// Initialize param struct //
/////////////////////////////
PVOID ReturnAddress = NULL;
PRM p = { 0 };
NTSTATUS status = STATUS_SUCCESS;
// just find a JMP RBX gadget. Can look anywhere. I chose k32
p.trampoline = FindGadget((LPBYTE)GetModuleHandle(L"kernel32.dll"), 0x200000);
printf("[+] Gadget is at 0x%llx\n", p.trampoline);
// You should probably walk the export table, but this is quick and easy.
ReturnAddress = (PBYTE)(GetProcAddress(LoadLibraryA("kernel32.dll"), "BaseThreadInitThunk")) + 0x14;
p.BTIT_ss = CalculateFunctionStackSizeWrapper(ReturnAddress);
p.BTIT_retaddr = ReturnAddress;
ReturnAddress = (PBYTE)(GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlUserThreadStart")) + 0x21;
p.RUTS_ss = CalculateFunctionStackSizeWrapper(ReturnAddress);
p.RUTS_retaddr = ReturnAddress;
p.Gadget_ss = CalculateFunctionStackSizeWrapper(p.trampoline);
// Hard coded for my machine, theoretically you do FreshyCalls or something
p.ssn = 0x18;
/////////////////////////////
// Initialize Syscall Args //
/////////////////////////////
PVOID alloc = NULL;
SIZE_T size = 1024;
///////////////////////////
// Call with fake frames //
///////////////////////////
Spoof((PVOID)(-1), &alloc, NULL, &size, &p, pNtAllocateVirtualMemory, (PVOID)2, (PVOID)(MEM_COMMIT | MEM_RESERVE), (PVOID)PAGE_EXECUTE_READWRITE);
```
If your machine works like mine, it will look like this
![Call Stack](https://i.imgur.com/aHWnX4S.png)
Example calling calc
```
unsigned char buf[] = //msfvenom brrr
PVOID alloc = NULL;
SIZE_T size = 1024;
PVOID pNtAllocateVirtualMemory = (PBYTE)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAllocateVirtualMemory")) + 0x12;
PVOID pMemcpy = GetProcAddress(LoadLibraryA("msvcrt.dll"), "memcpy");
PVOID pNtCreateThreadEx = (PBYTE)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx")) + 0x12;
p.ssn = 0x18;
Spoof((PVOID)(-1), &alloc, NULL, &size, &p, pNtAllocateVirtualMemory, (PVOID)2, (PVOID)(MEM_COMMIT | MEM_RESERVE), (PVOID)PAGE_EXECUTE_READWRITE);
Spoof(alloc, buf, (PVOID)276, NULL, &p, pMemcpy, (PVOID)0);
p.ssn = 0xc2;
PVOID hThread = NULL;
Spoof(&hThread, (PVOID)THREAD_ALL_ACCESS, NULL, (PVOID)(-1), &p, pNtCreateThreadEx, (PVOID)7, alloc, NULL, NULL, NULL, NULL, NULL, NULL);
Spoof((PVOID)INFINITE, NULL, NULL, NULL, &p, Sleep, (PVOID)0);
```
## Concerns
I have not done extensive testing with this. I only called a few functions and tried a local shellcode injection. There could be some edge cases I haven't tested.
Please reach out to me for any comments and such. Godspeed.
## Credits
5pider - Gadget Finder code
namazso - Return Address Spoofing
klezvirus, waldoirc, trickster0 - SilentMoonWalk (for Frame funky things)
william-burgess - Vulcan Raven (for finding stack wrapper)
```
`Structs.h`:
```h
#pragma once
#include <Windows.h>
typedef struct
{
PVOID Fixup; // 0
PVOID OG_retaddr; // 8
PVOID rbx; // 16
PVOID rdi; // 24
PVOID BTIT_ss; // 32
PVOID BTIT_retaddr; // 40
PVOID Gadget_ss; // 48
PVOID RUTS_ss; // 56
PVOID RUTS_retaddr; // 64
PVOID ssn; // 72
PVOID trampoline; // 80
PVOID rsi; // 88
PVOID r12; // 96
PVOID r13; // 104
PVOID r14; // 112
PVOID r15; // 120
} PRM, * PPRM;
/* God Bless Vulcan Raven*/
typedef struct
{
LPCWSTR dllPath;
ULONG offset;
ULONG totalStackSize;
BOOL requiresLoadLibrary;
BOOL setsFramePointer;
PVOID returnAddress;
BOOL pushRbp;
ULONG countOfCodes;
BOOL pushRbpIndex;
} StackFrame, * PStackFrame;
typedef enum _UNWIND_OP_CODES {
UWOP_PUSH_NONVOL = 0, /* info == register number */
UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */
UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
} UNWIND_CODE_OPS;
typedef union _UNWIND_CODE {
struct {
BYTE CodeOffset;
BYTE UnwindOp : 4;
BYTE OpInfo : 4;
};
USHORT FrameOffset;
} UNWIND_CODE, * PUNWIND_CODE;
typedef struct _UNWIND_INFO {
BYTE Version : 3;
BYTE Flags : 5;
BYTE SizeOfProlog;
BYTE CountOfCodes;
BYTE FrameRegister : 4;
BYTE FrameOffset : 4;
UNWIND_CODE UnwindCode[1];
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
* union {
* OPTIONAL ULONG ExceptionHandler;
* OPTIONAL ULONG FunctionEntry;
* };
* OPTIONAL ULONG ExceptionData[]; */
} UNWIND_INFO, * PUNWIND_INFO;
```
`Testing.c`:
```c
#include <Windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include "Structs.h"
#include "Macros.h"
extern PVOID NTAPI Spoof(PVOID a, ...);
PVOID FindGadget(LPBYTE Module, ULONG Size)
{
for (int x = 0; x < Size; x++)
{
if (memcmp(Module + x, "\xFF\x23", 2) == 0)
{
return (PVOID)(Module + x);
};
};
return NULL;
}
/* Credit to VulcanRaven project for the original implementation of these two*/
ULONG CalculateFunctionStackSize(PRUNTIME_FUNCTION pRuntimeFunction, const DWORD64 ImageBase)
{
NTSTATUS status = STATUS_SUCCESS;
PUNWIND_INFO pUnwindInfo = NULL;
ULONG unwindOperation = 0;
ULONG operationInfo = 0;
ULONG index = 0;
ULONG frameOffset = 0;
StackFrame stackFrame = { 0 };
// [0] Sanity check incoming pointer.
if (!pRuntimeFunction)
{
status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
// [1] Loop over unwind info.
// NB As this is a PoC, it does not handle every unwind operation, but
// rather the minimum set required to successfully mimic the default
// call stacks included.
pUnwindInfo = (PUNWIND_INFO)(pRuntimeFunction->UnwindData + ImageBase);
while (index < pUnwindInfo->CountOfCodes)
{
unwindOperation = pUnwindInfo->UnwindCode[index].UnwindOp;
operationInfo = pUnwindInfo->UnwindCode[index].OpInfo;
// [2] Loop over unwind codes and calculate
// total stack space used by target Function.
switch (unwindOperation) {
case UWOP_PUSH_NONVOL:
// UWOP_PUSH_NONVOL is 8 bytes.
stackFrame.totalStackSize += 8;
// Record if it pushes rbp as
// this is important for UWOP_SET_FPREG.
if (RBP_OP_INFO == operationInfo)
{
stackFrame.pushRbp = true;
// Record when rbp is pushed to stack.
stackFrame.countOfCodes = pUnwindInfo->CountOfCodes;
stackFrame.pushRbpIndex = index + 1;
}
break;
case UWOP_SAVE_NONVOL:
//UWOP_SAVE_NONVOL doesn't contribute to stack size
// but you do need to increment index.
index += 1;
break;
case UWOP_ALLOC_SMALL:
//Alloc size is op info field * 8 + 8.
stackFrame.totalStackSize += ((operationInfo * 8) + 8);
break;
case UWOP_ALLOC_LARGE:
// Alloc large is either:
// 1) If op info == 0 then size of alloc / 8
// is in the next slot (i.e. index += 1).
// 2) If op info == 1 then size is in next
// two slots.
index += 1;
frameOffset = pUnwindInfo->UnwindCode[index].FrameOffset;
if (operationInfo == 0)
{
frameOffset *= 8;
}
else
{
index += 1;
frameOffset += (pUnwindInfo->UnwindCode[index].FrameOffset << 16);
}
stackFrame.totalStackSize += frameOffset;
break;
case UWOP_SET_FPREG:
// This sets rsp == rbp (mov rsp,rbp), so we need to ensure
// that rbp is the expected value (in the frame above) when
// it comes to spoof this frame in order to ensure the
// call stack is correctly unwound.
stackFrame.setsFramePointer = true;
break;
default:
printf("[-] Error: Unsupported Unwind Op Code\n");
status = STATUS_ASSERTION_FAILURE;
break;
}
index += 1;
}
// If chained unwind information is present then we need to
// also recursively parse this and add to total stack size.
if (0 != (pUnwindInfo->Flags & UNW_FLAG_CHAININFO))
{
index = pUnwindInfo->CountOfCodes;
if (0 != (index & 1))
{
index += 1;
}
pRuntimeFunction = (PRUNTIME_FUNCTION)(&pUnwindInfo->UnwindCode[index]);
return CalculateFunctionStackSize(pRuntimeFunction, ImageBase, stackFrame);
}
// Add the size of the return address (8 bytes).
stackFrame.totalStackSize += 8;
return stackFrame.totalStackSize;
Cleanup:
return status;
}
ULONG CalculateFunctionStackSizeWrapper(PVOID ReturnAddress)
{
NTSTATUS status = STATUS_SUCCESS;
PRUNTIME_FUNCTION pRuntimeFunction = NULL;
DWORD64 ImageBase = 0;
PUNWIND_HISTORY_TABLE pHistoryTable = NULL;
// [0] Sanity check return address.
if (!ReturnAddress)
{
status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
// [1] Locate RUNTIME_FUNCTION for given Function.
pRuntimeFunction = RtlLookupFunctionEntry((DWORD64)ReturnAddress, &ImageBase, pHistoryTable);
if (NULL == pRuntimeFunction)
{
status = STATUS_ASSERTION_FAILURE;
printf("[!] STATUS_ASSERTION_FAILURE\n");
goto Cleanup;
}
// [2] Recursively calculate the total stack size for
// the Function we are "returning" to.
return CalculateFunctionStackSize(pRuntimeFunction, ImageBase);
Cleanup:
return status;
}
int bruh(int a, int b, int c, int d, int* e, int* f, int* g)
{
*e = 7;
*f = 8;
*g = 9;
}
int main() {
PVOID ReturnAddress = NULL;
PRM p = { 0 };
PRM ogp = { 0 };
NTSTATUS status = STATUS_SUCCESS;
PVOID pPrintf = GetProcAddress(LoadLibraryA("msvcrt.dll"), "printf");
p.trampoline = FindGadget((LPBYTE)GetModuleHandle(L"kernel32.dll"), 0x200000);
printf("[+] Gadget is at 0x%llx\n", p.trampoline);
ReturnAddress = (PBYTE)(GetProcAddress(LoadLibraryA("kernel32.dll"), "BaseThreadInitThunk")) + 0x14; // Would walk export table but am lazy
p.BTIT_ss = CalculateFunctionStackSizeWrapper(ReturnAddress);
p.BTIT_retaddr = ReturnAddress;
ReturnAddress = (PBYTE)(GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlUserThreadStart")) + 0x21;
p.RUTS_ss = CalculateFunctionStackSizeWrapper(ReturnAddress);
p.RUTS_retaddr = ReturnAddress;
p.Gadget_ss = CalculateFunctionStackSizeWrapper(p.trampoline);
// 0 stack args
for (int i = 0; i < 2; i++)
{
Spoof("[+] Iteration %d\n", i, NULL, NULL, &p, pPrintf, (PVOID)0);
Spoof(4000, NULL, NULL, NULL, &p, Sleep, (PVOID)0);
Spoof("[+] Returning to 0x%llx\n", _ReturnAddress(), NULL, NULL, &p, pPrintf, (PVOID)0);
}
// 1 stack arg
for (int i = 0; i < 500; i++)
{
PVOID alloc = Spoof((PVOID)(-1), 0, 1024, MEM_COMMIT | MEM_RESERVE, &p, VirtualAllocEx, (PVOID)1, (PVOID)PAGE_EXECUTE_READWRITE);
Spoof("[+] Allocated to 0x%llx\n", alloc, NULL, NULL, &p, pPrintf, (PVOID)0);
}
// 2 stack arg
PVOID pNtAllocateVirtualMemory = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAllocateVirtualMemory");
for (int i = 0; i < 500; i++)
{
PVOID alloc = NULL;
SIZE_T size = 1024;
PVOID base = NULL;
Spoof((PVOID)(-1), &alloc, NULL, &size, &p, pNtAllocateVirtualMemory, (PVOID)2, (PVOID)(MEM_COMMIT | MEM_RESERVE), (PVOID)PAGE_EXECUTE_READWRITE);
Spoof("[+] NtAllocated to 0x%llx\n", alloc, NULL, NULL, &p, pPrintf, (PVOID)0);
}
// indirect syscall
p.ssn = 0x18;
for (int i = 0; i < 500; i++)
{
PVOID alloc = NULL;
SIZE_T size = 1024;
PVOID base = NULL;
Spoof((PVOID)(-1), &alloc, NULL, &size, &p, (PBYTE)pNtAllocateVirtualMemory + 0x12, (PVOID)2, (PVOID) (MEM_COMMIT | MEM_RESERVE), (PVOID) PAGE_EXECUTE_READWRITE);
Spoof("[+] Indirectly Allocated to 0x%llx\n", alloc, NULL, NULL, &p, pPrintf, (PVOID)0);
}
// gets
char* buffer = malloc(50);
size_t size = 50;
Spoof(buffer, size, NULL, NULL, &p, gets_s, (PVOID) 0);
int e = 0;
int f = 0;
int g = 0;
/* Testing if stack args get modified */
Spoof((PVOID)0, (PVOID)0, (PVOID)0, (PVOID)0, &p, bruh, (PVOID)3, &e, &f, &g);
Spoof("e: %d\n", e, NULL, NULL, &p, pPrintf, (PVOID)0);
Spoof("f: %d\n", f, NULL, NULL, &p, pPrintf, (PVOID)0);
Spoof("g: %d\n", g, NULL, NULL, &p, pPrintf, (PVOID)0);
Spoof("Cya\n",NULL, NULL, NULL, &p, pPrintf, (PVOID)0);
return 0;
}
```
`test.asm`:
```asm
Spoof proto
Setup proto
NtWait proto
.code
Spoof proc
pop rax ; Real return address in rax
mov r10, rdi ; Store OG rdi in r10
mov r11, rsi ; Store OG rsi in r11
mov rdi, [rsp + 32] ; Storing struct in the rdi
mov rsi, [rsp + 40] ; Storing function to call
; ---------------------------------------------------------------------
; Storing our original registers
; ---------------------------------------------------------------------
mov [rdi + 24], r10 ; Storing OG rdi into param
mov [rdi + 88], r11 ; Storing OG rsi into param
mov [rdi + 96], r12 ; Storing OG r12 into param
mov [rdi + 104], r13 ; Storing OG r13 into param
mov [rdi + 112], r14 ; Storing OG r14 into param
mov [rdi + 120], r15 ; Storing OG r15 into param
mov r12, rax ; OG code used r12 for ret addr
; ---------------------------------------------------------------------
; Prepping to move stack args
; ---------------------------------------------------------------------
xor r11, r11 ; r11 will hold the # of args that have been "pushed"
mov r13, [rsp + 30h] ; r13 will hold the # of args total that will be pushed
mov r14, 200h ; r14 will hold the offset we need to push stuff
add r14, 8
add r14, [rdi + 56] ; stack size of RUTS
add r14, [rdi + 48] ; stack size of BTIT
add r14, [rdi + 32] ; stack size of our gadget frame
sub r14, 20h ; first stack arg is located at +0x28 from rsp, so we sub 0x20 from the offset. Loop will sub 0x8 each time
mov r10, rsp
add r10, 30h ; offset of stack arg added to rsp
looping:
xor r15, r15 ; r15 will hold the offset + rsp base
cmp r11, r13 ; comparing # of stack args added vs # of stack args we need to add
je finish
; ---------------------------------------------------------------------
; Getting location to move the stack arg to
; ---------------------------------------------------------------------
sub r14, 8 ; 1 arg means r11 is 0, r14 already 0x28 offset.
mov r15, rsp ; get current stack base
sub r15, r14 ; subtract offset
; ---------------------------------------------------------------------
; Procuring the stack arg
; ---------------------------------------------------------------------
add r10, 8
push [r10]
pop [r15] ; move the stack arg into the right location
; ---------------------------------------------------------------------
; Increment the counter and loop back in case we need more args
; ---------------------------------------------------------------------
add r11, 1
jmp looping
finish:
; ----------------------------------------------------------------------
; Creating a big 320 byte working space
; ----------------------------------------------------------------------
sub rsp, 200h
; ----------------------------------------------------------------------
; Pushing a 0 to cut off the return addresses after RtlUserThreadStart.
; Need to figure out why this cuts off the call stack
; ----------------------------------------------------------------------
push 0
; ----------------------------------------------------------------------
; RtlUserThreadStart + 0x14 frame
; ----------------------------------------------------------------------
sub rsp, [rdi + 56]
mov r11, [rdi + 64]
mov [rsp], r11
; ----------------------------------------------------------------------
; BaseThreadInitThunk + 0x21 frame
; ----------------------------------------------------------------------
sub rsp, [rdi + 32]
mov r11, [rdi + 40]
mov [rsp], r11
; ----------------------------------------------------------------------
; Gadget frame
; ----------------------------------------------------------------------
sub rsp, [rdi + 48]
mov r11, [rdi + 80]
mov [rsp], r11
; ----------------------------------------------------------------------
; Adjusting the param struct for the fixup
; ----------------------------------------------------------------------
mov r11, rsi ; Copying function to call into r11
mov [rdi + 8], r12 ; Real return address is now moved into the "OG_retaddr" member
mov [rdi + 16], rbx ; original rbx is stored into "rbx" member
lea rbx, [fixup] ; Fixup address is moved into rbx
mov [rdi], rbx ; Fixup member now holds the address of Fixup
mov rbx, rdi ; Address of param struct (Fixup) is moved into rbx
; ----------------------------------------------------------------------
; Syscall stuff. Shouldn't affect performance even if a syscall isnt made
; ----------------------------------------------------------------------
mov r10, rcx
mov rax, [rdi + 72]
jmp r11
fixup:
mov rcx, rbx
add rsp, 200h ; Big frame thing
add rsp, [rbx + 48] ; Stack size
add rsp, [rbx + 32] ; Stack size
add rsp, [rbx + 56] ; Stack size
mov rbx, [rcx + 16] ; Restoring OG RBX
mov rdi, [rcx + 24] ; ReStoring OG rdi
mov rsi, [rcx + 88] ; ReStoring OG rsi
mov r12, [rcx + 96] ; ReStoring OG r12
mov r13, [rcx + 104] ; ReStoring OG r13
mov r14, [rcx + 112] ; ReStoring OG r14
mov r15, [rcx + 120] ; ReStoring OG r15
jmp QWORD ptr [rcx + 8]
Spoof endp
end
```