mirror of
https://github.com/gmh5225/awesome-game-security
synced 2026-06-21 13:56:22 +00:00
archive: add 5 repo prompt(s) [skip ci]
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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, ¶m, 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
|
||||
|
||||

|
||||
|
||||
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
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user