Windows C++ / Return Address Spoofing
Author | External |
Platform | Windows |
Language | C++ |
Technique | Return Address Spoofing |
Description:
This code implements a templated function called spoof_call that takes three arguments: trampoline, fn, and args.... The function creates a struct shell_params that contains two void pointers: trampoline and function. The function then calls the do_call function of the struct argument_remapper, which will forward the arguments to a helper function shellcode_stub_helper that calls fn using the arguments. The number of arguments is limited to 4 or fewer or at least 5, depending on the size of Args. The spoof_call function is used to call fn via the trampoline pointer. The purpose of this code is not clear, but it appears to be related to calling functions in a specific manner.
Code
#include <type_traits>
namespace detail
{
extern "C" void* _spoofer_stub();
template <typename Ret, typename... Args>
static inline auto shellcode_stub_helper(
const void* shell,
Args... args
) -> Ret
{
auto fn = (Ret(*)(Args...))(shell);
return fn(args...);
}
template <std::size_t Argc, typename>
struct argument_remapper
{
// At least 5 params
template<
typename Ret,
typename First,
typename Second,
typename Third,
typename Fourth,
typename... Pack
>
static auto do_call(
const void* shell,
void* shell_param,
First first,
Second second,
Third third,
Fourth fourth,
Pack... pack
) -> Ret
{
return shellcode_stub_helper<
Ret,
First,
Second,
Third,
Fourth,
void*,
void*,
Pack...
>(
shell,
first,
second,
third,
fourth,
shell_param,
nullptr,
pack...
);
}
};
template <std::size_t Argc>
struct argument_remapper<Argc, std::enable_if_t<Argc <= 4>>
{
// 4 or less params
template<
typename Ret,
typename First = void*,
typename Second = void*,
typename Third = void*,
typename Fourth = void*
>
static auto do_call(
const void* shell,
void* shell_param,
First first = First{},
Second second = Second{},
Third third = Third{},
Fourth fourth = Fourth{}
) -> Ret
{
return shellcode_stub_helper<
Ret,
First,
Second,
Third,
Fourth,
void*,
void*
>(
shell,
first,
second,
third,
fourth,
shell_param,
nullptr
);
}
};
}
template <typename Ret, typename... Args>
static inline auto spoof_call(
const void* trampoline,
Ret(*fn)(Args...),
Args... args
) -> Ret
{
struct shell_params
{
const void* trampoline;
void* function;
void* rbx;
};
shell_params p{ trampoline, reinterpret_cast<void*>(fn) };
using mapper = detail::argument_remapper<sizeof...(Args), void>;
return mapper::template do_call<Ret, Args...>((const void*)&detail::_spoofer_stub, &p, args...);
}
Created
January 29, 2023
Last Revised
April 22, 2024