Files
2026-08-27 11:22:01 -06:00

229 lines
6.1 KiB
C++
Executable File

#pragma once
#ifdef _KERNEL_MODE
#include <ntddk.h>
#include <ntdef.h>
#include <xtr1common>
#else
#include <Windows.h>
#include <utility>
#endif
#include <Intrin.h>
/*
* Copyright 2022 Barracudach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// === FAQ === documentation is available at https://github.com/Barracudach
//Supports 2 modes: kernelmode and usermode(x64)
//For kernel- disable Control Flow Guard (CFG) /guard:cf
//usermode c++17 and above
//kernelmode c++14 and above
#define TIME_BASED_XOR_KEY \
(static_cast<uintptr_t>((__TIME__[1] - '0') * 10 + (__TIME__[4] - '0')) * 0xA5A5A5A5A5A5A5A5)
#define SPOOF_FUNC MXRM::SpoofFunction spoof(_AddressOfReturnAddress());
#ifdef _KERNEL_MODE
#define SPOOF_CALL(ret_type,name) (MXRM::SafeCall<ret_type,std::remove_reference_t<decltype(*name)>>(name))
#else
#define SPOOF_CALL(name) (MXRM::SafeCall(name))
#endif
#define MAX_FUNC_BUFFERED 100
#define SHELLCODE_GENERATOR_SIZE 500
namespace MXRM
{
#ifdef _KERNEL_MODE
typedef unsigned __int64 uintptr_t, size_t;
#pragma region std::forward
template <class _Ty>
struct remove_reference {
using type = _Ty;
using _Const_thru_ref_type = const _Ty;
};
template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;
template <class>
constexpr bool is_lvalue_reference_v = false; // determine whether type argument is an lvalue reference
template <class _Ty>
constexpr bool is_lvalue_reference_v<_Ty&> = true;
template <class _Ty>
constexpr _Ty&& forward(
remove_reference_t<_Ty>& _Arg) noexcept { // forward an lvalue as either an lvalue or an rvalue
return static_cast<_Ty&&>(_Arg);
}
template <class _Ty>
constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept { // forward an rvalue as an rvalue
static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
return static_cast<_Ty&&>(_Arg);
}
#pragma endregion
#else
using namespace std;
#endif
}
namespace MXRM
{
class SpoofFunction
{
public:
uintptr_t temp = 0;
static constexpr uintptr_t xor_key = TIME_BASED_XOR_KEY;
void* ret_addr_in_stack = 0;
SpoofFunction(void* addr) : ret_addr_in_stack(addr)
{
temp = *(uintptr_t*)ret_addr_in_stack;
temp ^= xor_key;
*(uintptr_t*)ret_addr_in_stack = 0;
}
~SpoofFunction()
{
temp ^= xor_key;
*(uintptr_t*)ret_addr_in_stack = temp;
}
};
#ifdef _KERNEL_MODE
__forceinline PVOID LocateShellCode(PVOID func, size_t size = 500)
{
void* addr = ExAllocatePoolWithTag(NonPagedPool, size, (ULONG)"File");
if (!addr)
return nullptr;
return memcpy(addr, func, size);
}
#else
__forceinline PVOID LocateShellCode(PVOID func, size_t size = SHELLCODE_GENERATOR_SIZE)
{
void* addr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!addr)
return nullptr;
return memcpy(addr, func, size);
}
#endif
#ifdef _KERNEL_MODE
template <typename RetType, typename Func, typename ...Args>
RetType
#else
template <typename Func, typename ...Args>
typename std::invoke_result<Func, Args...>::type
#endif
__declspec(safebuffers)ShellCodeGenerator(Func f, Args&... args)
{
static constexpr uintptr_t xor_key = TIME_BASED_XOR_KEY;
void* ret_addr_in_stack = _AddressOfReturnAddress();
uintptr_t temp = *(uintptr_t*)ret_addr_in_stack;
temp ^= xor_key;
*(uintptr_t*)ret_addr_in_stack = 0;
if constexpr (std::is_same_v<typename std::invoke_result<Func, Args...>::type, void>)
{
f(args...);
temp ^= xor_key;
*(uintptr_t*)ret_addr_in_stack = temp;
}
else
{
auto&& ret = f(args...);
temp ^= xor_key;
*(uintptr_t*)ret_addr_in_stack = temp;
return ret;
}
}
#ifdef _KERNEL_MODE
template<typename RetType, class Func>
#else
template<class Func >
#endif
class SafeCall
{
Func* funcPtr;
public:
SafeCall(Func* func) :funcPtr(func) {}
template<typename... Args>
__forceinline decltype(auto) operator()(Args&&... args)
{
SPOOF_FUNC;
#ifdef _KERNEL_MODE
using return_type = RetType;
using p_shell_code_generator_type = decltype(&ShellCodeGenerator<RetType, Func*, Args...>);
PVOID self_addr = static_cast<PVOID>(&ShellCodeGenerator<RetType, Func*, Args&&...>);
#else
using return_type = typename std::invoke_result<Func, Args...>::type;
using p_shell_code_generator_type = decltype(&ShellCodeGenerator<Func*, Args...>);
p_shell_code_generator_type self_addr = static_cast<p_shell_code_generator_type>(&ShellCodeGenerator<Func*, Args&&...>);
#endif
p_shell_code_generator_type p_shellcode{};
static size_t count{};
static p_shell_code_generator_type orig_generator[MAX_FUNC_BUFFERED]{};
static p_shell_code_generator_type alloc_generator[MAX_FUNC_BUFFERED]{};
unsigned index{};
while (orig_generator[index])
{
if (orig_generator[index] == self_addr)
{
#ifdef _KERNEL_MODE
//DbgPrint("Found allocated generator");
#else
//std::cout << "Found allocated generator" << std::endl;
#endif
p_shellcode = alloc_generator[index];
break;
}
index++;
}
if (!p_shellcode)
{
#ifdef _KERNEL_MODE
//DbgPrint("Alloc generator");
#else
//std::cout << "Alloc generator" << std::endl;
#endif
p_shellcode = reinterpret_cast<p_shell_code_generator_type>(LocateShellCode(self_addr));
orig_generator[count] = self_addr;
alloc_generator[count] = p_shellcode;
count++;
}
if (!p_shellcode)
{
//DbgPrint("!p_shellcode");
}
return p_shellcode(funcPtr, args...);
}
};
}