3 #include "../../Asm/AsmHelperBase.h"
4 #include "../Process.h"
15 template<
typename Fn >
34 #pragma warning(disable : 4127)
44 NTSTATUS
Call( T& result, std::vector<AsmVariant>& args,
Thread* contextThread =
nullptr )
51 return LastNtStatus();
54 bool isFloat = std::is_same<T, float>::value;
55 bool isDouble = std::is_same<T, double>::value || std::is_same<T, long double>::value;
58 eReturnType retType = rt_int32;
64 else if (
sizeof(T) ==
sizeof(uint64_t))
66 else if (!std::is_reference<T>::value &&
sizeof(T) >
sizeof(uint64_t))
69 auto pfnNew = brutal_cast<
const void*>(_pfn);
71 _process.remote().PrepareCallAssembly( a, pfnNew, args, _callConv, retType );
74 if (contextThread ==
nullptr)
75 _process.remote().
ExecInNewThread( a->make(), a->getCodeSize(), result2 );
76 else if (*contextThread == _process.remote()._hWorkThd)
79 _process.remote().
ExecInAnyThread( a->make(), a->getCodeSize(), result2, *contextThread );
82 _process.remote().GetCallResult<T>( result );
84 return STATUS_SUCCESS;
87 #pragma warning(default : 4127)
89 inline type ptr()
const {
return _pfn; }
92 RemoteFuncBase(
const RemoteFuncBase& ) =
delete;
93 RemoteFuncBase& operator =(
const RemoteFuncBase&) =
delete;
96 eCalligConvention _callConv;
102 template<
typename... Args>
105 static const size_t arg_count =
sizeof...(Args);
110 inline std::vector<AsmVariant>& getArgsRaw()
const {
return _args; }
111 inline std::tuple<Args...>& getArgs()
const {
return _targs; }
116 auto getArg() -> decltype(std::get<pos>( _targs ))
118 return std::get<pos>( _targs );
122 void updateArgs()
const
124 for (
auto& arg : _args)
125 if (arg.type == AsmVariant::dataPtr)
126 _process.memory().
Read( arg.new_imm_val, arg.size, (
void*)arg.imm_val );
130 void setArg(
int pos,
const AsmVariant& newVal )
132 if (_args.size() > (size_t)pos)
137 template<
typename... TArgs>
140 , _targs( static_cast<Args&&>(args)... )
141 , _args( std::vector<AsmVariant>{
static_cast<Args&&
>(args)... } ) { }
144 FuncArguments(
const FuncArguments& ) =
delete;
145 FuncArguments& operator =(
const FuncArguments&) =
delete;
148 mutable std::vector<AsmVariant> _args;
149 mutable std::tuple<Args...> _targs;
154 template<
typename Fn >
157 #define DECLPFN(CALL_OPT, CALL_DEF, ...) \
158 template<__VA_ARGS__ typename R, typename... Args > \
159 class RemoteFunction< R( CALL_OPT* )(Args...) > : public RemoteFuncBase<R( CALL_OPT* )(Args...)>, public FuncArguments<Args...> \
162 typedef typename std::conditional<std::is_same<R, void>::value, int, R>::type ReturnType; \
165 template<typename... TArgs> \
166 RemoteFunction( Process& proc, typename RemoteFuncBase::type ptr, TArgs&&... args ) \
167 : RemoteFuncBase( proc, ptr, CALL_DEF ) \
168 , FuncArguments( proc, static_cast<Args&&>(args)... ) { } \
170 inline DWORD Call( ReturnType& result, Thread* contextThread = nullptr ) \
172 NTSTATUS status = RemoteFuncBase::Call( result, getArgsRaw(), contextThread ); \
173 FuncArguments::updateArgs( ); \
181 DECLPFN( __cdecl, cc_cdecl );
185 DECLPFN( __stdcall, cc_stdcall );
186 DECLPFN( __thiscall, cc_thiscall );
187 DECLPFN( __fastcall, cc_fastcall );
191 template<
class C,
typename R,
typename... Args >
195 typedef typename std::conditional<std::is_same<R, void>::value, int, R>::type ReturnType;
196 typedef typename ReturnType( C::*type )(Args...);
201 , FuncArguments( proc ) { }
204 :
RemoteFuncBase( proc, (
typename RemoteFuncBase::type)ptr, cc_thiscall )
205 , FuncArguments( proc, pClass, args... ) { }
207 inline DWORD Call( R& result,
Thread* contextThread =
nullptr )
210 FuncArguments::updateArgs();
BLACKBONE_API Thread * getWorker()
Get worker thread
Definition: RemoteExec.h:114
BLACKBONE_API NTSTATUS ExecInAnyThread(PVOID pCode, size_t size, uint64_t &callResult, Thread &thread)
Execute code in context of any existing thread
Definition: RemoteExec.cpp:154
BLACKBONE_API NTSTATUS Read(ptr_t dwAddress, size_t dwSize, PVOID pResult, bool handleHoles=false)
Read data
Definition: ProcessMemory.cpp:81
BLACKBONE_API NTSTATUS ExecInWorkerThread(PVOID pCode, size_t size, uint64_t &callResult)
Execute code in context of our worker thread
Definition: RemoteExec.cpp:92
General purpose assembly variable
Definition: AsmVariant.hpp:16
Base class for remote function pointer
Definition: RemoteFunction.hpp:16
BLACKBONE_API NTSTATUS CreateRPCEnvironment(bool bThread=true, bool bEvent=true)
Create environment for future remote procedure calls
Definition: RemoteExec.cpp:270
Definition: RemoteFunction.hpp:103
NTSTATUS Call(T &result, std::vector< AsmVariant > &args, Thread *contextThread=nullptr)
Perform remote function call
Definition: RemoteFunction.hpp:44
Definition: RemoteFunction.hpp:155
Thread management
Definition: Thread.h:44
BLACKBONE_API NTSTATUS ExecInNewThread(PVOID pCode, size_t size, uint64_t &callResult)
Create new thread and execute code in it. Wait until execution ends
Definition: RemoteExec.cpp:34
Definition: AsmHelper32.cpp:6