BlackBone
Windows memory hacking library
 All Classes Functions
AsmVariant.hpp
1 #pragma once
2 
3 
4 #include "../Config.h"
5 #pragma warning(disable : 4100)
6 #include <AsmJit/asmjit.h>
7 #pragma warning(default : 4100)
8 
9 #include <memory>
10 
11 namespace blackbone
12 {
16  class AsmVariant
17  {
18  friend class AsmHelper32;
19  friend class AsmHelper64;
20  friend class RemoteExec;
21 
22  template<typename... Args>
23  friend class FuncArguments;
24 
25  public:
26  enum eType
27  {
28  noarg, // void
29  reg, // register
30  imm, // immediate value (e.g. address)
31  imm_double, // double or long double
32  imm_float, // float
33  dataPtr, // pointer to local data (e.g. string or pointer to structure)
34  dataStruct, // structure passed by value
35  structRet, // pointer to space into which return value is copied (used when returning structures by value)
36  mem, // stack variable
37  mem_ptr // pointer to stack variable
38  };
39 
40  public:
41  BLACKBONE_API AsmVariant( void )
42  : AsmVariant( noarg, 0, 0 ) { }
43 
44  BLACKBONE_API AsmVariant( int _imm )
45  : AsmVariant( imm, sizeof(_imm), static_cast<size_t>(_imm) ) { }
46 
47  BLACKBONE_API AsmVariant( unsigned long _imm )
48  : AsmVariant( imm, sizeof(_imm), static_cast<size_t>(_imm) ) { }
49 
50  BLACKBONE_API AsmVariant( size_t _imm )
51  : AsmVariant( imm, sizeof(_imm), _imm ) { }
52 
53  BLACKBONE_API AsmVariant( char* ptr )
54  : AsmVariant( dataPtr, strlen( ptr ) + 1, reinterpret_cast<size_t>(ptr) ) { }
55 
56  BLACKBONE_API AsmVariant( const char* ptr )
57  : AsmVariant( const_cast<char*>(ptr) ) { }
58 
59  BLACKBONE_API AsmVariant( wchar_t* ptr )
60  : AsmVariant( dataPtr, (wcslen( ptr ) + 1) * sizeof(wchar_t), reinterpret_cast<size_t>(ptr) ) { }
61 
62  BLACKBONE_API AsmVariant( const wchar_t* ptr )
63  : AsmVariant( const_cast<wchar_t*>(ptr) ) { }
64 
65  BLACKBONE_API AsmVariant( void* _imm )
66  : AsmVariant( imm, sizeof(void*), reinterpret_cast<size_t>(_imm) ) { }
67 
68  BLACKBONE_API AsmVariant( const void* _imm )
69  : AsmVariant( imm, sizeof(void*), reinterpret_cast<size_t>(_imm) ) { }
70 
71  // In MSVS compiler 'long double' and 'double' are both 8 bytes long
72  BLACKBONE_API AsmVariant( long double _imm_fpu )
73  : AsmVariant( (double)_imm_fpu ) { }
74 
75  BLACKBONE_API AsmVariant( double _imm_fpu )
76  : type( imm_double )
77  , size( sizeof(double) )
78  , imm_double_val( _imm_fpu )
79  , new_imm_val( 0 ) { }
80 
81  BLACKBONE_API AsmVariant( float _imm_fpu )
82  : type( imm_float )
83  , size( sizeof(float) )
84  , imm_float_val( _imm_fpu )
85  , new_imm_val( 0 ) { }
86 
87  BLACKBONE_API AsmVariant( asmjit::host::GpReg _reg )
88  : type( reg )
89  , size( sizeof(size_t) )
90  , reg_val( _reg )
91  , imm_double_val( -1.0 )
92  , new_imm_val( 0 ) { }
93 
94  // Stack variable
95  BLACKBONE_API AsmVariant( asmjit::host::Mem _mem )
96  : type( mem )
97  , size( sizeof(size_t) )
98  , mem_val( _mem )
99  , imm_double_val( -1.0 ) { }
100 
101  // Pointer to stack address
102  BLACKBONE_API AsmVariant( asmjit::host::Mem* _mem )
103  : type( mem_ptr )
104  , size( sizeof(size_t) )
105  , mem_val( *_mem )
106  , imm_double_val( -1.0 )
107  , new_imm_val( 0 ) { }
108 
109  BLACKBONE_API AsmVariant( const asmjit::host::Mem* _mem )
110  : AsmVariant( const_cast<asmjit::host::Mem*>(_mem) ) { }
111 
112  template <typename T>
113  AsmVariant( T* ptr )
114  : AsmVariant( dataPtr, sizeof(T), reinterpret_cast<size_t>(ptr) ) { }
115 
116  template <typename T>
117  AsmVariant( const T* ptr )
118  {
119  //
120  // Treat function pointer as void*
121  //
122  const bool isFunction = std::is_function<typename std::remove_pointer<T>::type>::value;
123  typedef typename std::conditional<isFunction, void*, T>::type Type;
124 
125  type = isFunction ? imm : dataPtr;
126  size = sizeof(Type);
127  imm_val = reinterpret_cast<size_t>(ptr);
128  new_imm_val = 0;
129  }
130 
131  template <typename T>
132  AsmVariant( const T* ptr, size_t size )
133  : AsmVariant( dataPtr, size, reinterpret_cast<size_t>(ptr) ) { }
134 
135  template <typename T>
136  AsmVariant( T& val )
137  : AsmVariant( dataPtr, sizeof(T), reinterpret_cast<size_t>(&val) ) { }
138 
139  template <typename T>
140  AsmVariant( const T& val )
141  : AsmVariant( dataPtr, sizeof(T), reinterpret_cast<size_t>(&val) ) {}
142 
143  // Pass argument by value case
144  // Real RValue reference types are not supported because of ambiguity
145  #pragma warning(disable : 4127)
146  template <typename T>
147  AsmVariant( T&& val )
148  : AsmVariant( dataStruct, sizeof(T), reinterpret_cast<size_t>(&val) )
149  {
150  // Check if argument fits into register
151  if (sizeof(T) <= sizeof(void*) && !std::is_class<T>::value)
152  {
153  type = imm;
154  imm_val = 0;
155  memcpy( &imm_val, &val, sizeof(T) );
156  }
157  else
158  {
159  buf.reset( new uint8_t[sizeof(T)] );
160  imm_val = reinterpret_cast<size_t>(buf.get());
161  memcpy( buf.get(), &val, sizeof(T) );
162  }
163  }
164  #pragma warning(default : 4127)
165 
166  BLACKBONE_API AsmVariant( AsmVariant&& other )
167  {
168  *this = std::move( other );
169  }
170 
171  BLACKBONE_API AsmVariant( const AsmVariant& other ) = default;
172  BLACKBONE_API AsmVariant& operator =(const AsmVariant& other) = default;
173 
174  //
175  // Get floating point value as raw data
176  //
177  BLACKBONE_API inline uint32_t getImm_float() const { return *(reinterpret_cast<const uint32_t*>(&imm_float_val)); }
178  BLACKBONE_API inline uint64_t getImm_double() const { return *(reinterpret_cast<const uint64_t*>(&imm_double_val)); }
179 
184  BLACKBONE_API inline bool reg86Compatible() const
185  {
186  if (type == dataStruct || type == imm_float || type == imm_double || type == structRet)
187  return false;
188  else
189  return true;
190  }
191 
192  private:
193  //
200  AsmVariant( eType _type, size_t _size, size_t val )
201  : type( _type )
202  , size( _size )
203  , imm_val( val )
204  , new_imm_val( 0 ) { }
205 
206  private:
207  eType type; // Variable type
208  size_t size; // Variable size
209 
210  asmjit::host::GpReg reg_val; // General purpose register
211  asmjit::host::Mem mem_val; // Memory pointer
212 
213  // Immediate values
214  union
215  {
216  size_t imm_val;
217  double imm_double_val;
218  float imm_float_val;
219  };
220 
221  size_t new_imm_val; // Replaced immediate value for dataPtr type
222 
223  // rvalue reference buffer
224  std::shared_ptr<uint8_t> buf;
225  };
226 
227 }
Definition: AsmHelper64.h:9
Definition: RemoteExec.h:20
General purpose assembly variable
Definition: AsmVariant.hpp:16
BLACKBONE_API bool reg86Compatible() const
Check if argument can be passed in x86 register
Definition: AsmVariant.hpp:184
Definition: RemoteFunction.hpp:103
32 bit assembler helper
Definition: AsmHelper32.h:11
Definition: AsmHelper32.cpp:6