parent
8e3436b01e
commit
1cb0d10e20
@ -1,31 +1,80 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#pragma section( ".xmp2" )
|
#pragma section( ".xmp2" )
|
||||||
#pragma comment( linker, "/section:.xmp2,RWE" )
|
#pragma comment( linker, "/section:.xmp2,RWE" )
|
||||||
|
|
||||||
|
using u8 = unsigned char;
|
||||||
|
using u16 = unsigned short;
|
||||||
|
using u32 = unsigned int;
|
||||||
|
using u64 = unsigned long long;
|
||||||
using __vmcall_t = void *( * )( ... );
|
using __vmcall_t = void *( * )( ... );
|
||||||
|
|
||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
|
constexpr auto entry_rva = 0x1000;
|
||||||
|
|
||||||
|
enum class calls : u32
|
||||||
|
{
|
||||||
|
get_world = 0xBFFD6FE9,
|
||||||
|
get_hello = 0xBFFD6FDD
|
||||||
|
};
|
||||||
|
|
||||||
|
template < class T, class U > struct _pair_t
|
||||||
|
{
|
||||||
|
T first;
|
||||||
|
U second;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _pair_t< u8, calls > call_map[ 2 ] = { { 0, calls::get_world }, { 1, calls::get_hello } };
|
||||||
|
|
||||||
struct _gen_data
|
struct _gen_data
|
||||||
{
|
{
|
||||||
unsigned char __vmcall_shell_code[3] = {0x0, 0x0, 0x0};
|
u8 bin[ 0x100000 ]; // this will the vmp binary...
|
||||||
} __declspec( allocate( ".xmp2" ) ) gen_data;
|
u8 __vmcall_shell_code[ 2 ][ 15 ] = { {
|
||||||
|
0x68, 0xE9, 0xD6, 0xFF, 0x0B, // push xxxx
|
||||||
|
0x68, 0xE9, 0xD6, 0xFF, 0x0B, // push xxxx
|
||||||
|
0xE9, 0x00, 0x00, 0x00, 0x00 // jmp rip+xxxx
|
||||||
|
},
|
||||||
|
|
||||||
inline __vmcall_t __vmcall = reinterpret_cast< __vmcall_t >( gen_data.__vmcall_shell_code );
|
{
|
||||||
|
0x68, 0xE9, 0xD6, 0xFF, 0x0B, // push xxxx
|
||||||
|
0x68, 0xE9, 0xD6, 0xFF, 0x0B, // push xxxx
|
||||||
|
0xE9, 0x00, 0x00, 0x00, 0x00 // jmp rip+xxxx
|
||||||
|
} };
|
||||||
|
|
||||||
enum class calls : unsigned long long
|
bool init()
|
||||||
{
|
{
|
||||||
get_world = 0xBFFD6FE9,
|
for ( auto idx = 0u; idx < ( sizeof( __vmcall_shell_code ) / 15 ); ++idx )
|
||||||
get_hello = 0xBFFD6FE9
|
{
|
||||||
|
*reinterpret_cast< u32 * >( &__vmcall_shell_code[ idx ][ 1 ] ) =
|
||||||
|
static_cast< u32 >( call_map[ idx ].second );
|
||||||
|
|
||||||
|
*reinterpret_cast< u32 * >( &__vmcall_shell_code[ idx ][ 6 ] ) =
|
||||||
|
static_cast< u32 >( call_map[ idx ].second );
|
||||||
|
|
||||||
|
*reinterpret_cast< u32 * >( &__vmcall_shell_code[ idx ][ 11 ] ) = reinterpret_cast< u32 >(
|
||||||
|
( bin - ( reinterpret_cast< u64 >( &__vmcall_shell_code[ idx ] ) + 15 ) ) + entry_rva );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // only a bool so i can use static/call once...
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template < class T, class... Ts > T call( vm::calls e_call, Ts... args )
|
__declspec( allocate( ".xmp2" ) ) inline _gen_data gen_data;
|
||||||
|
|
||||||
|
template < calls e_call, class T, class... Ts > auto call( Ts... args ) -> T
|
||||||
{
|
{
|
||||||
return reinterpret_cast< T >( __vmcall( e_call, args ) );
|
static auto __init_result = gen_data.init();
|
||||||
|
|
||||||
|
__vmcall_t vmcall = nullptr;
|
||||||
|
for ( auto idx = 0u; idx < sizeof( call_map ) / sizeof( _pair_t< u8, calls > ); ++idx )
|
||||||
|
if ( call_map[ idx ].second == e_call )
|
||||||
|
vmcall = reinterpret_cast< __vmcall_t >( &gen_data.__vmcall_shell_code[ idx ] );
|
||||||
|
|
||||||
|
return reinterpret_cast< T >( vmcall( args... ) );
|
||||||
}
|
}
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
vm::call<unsigned long long>( vm::calls::get_hello );
|
vm::call< vm::calls::get_hello, void * >( "hello world" );
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in new issue