|
|
@ -111,6 +111,7 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
llvm_module->getOrInsertGlobal( "rflags", ir_builder->getInt64Ty() );
|
|
|
|
llvm_module->getOrInsertGlobal( "rflags", ir_builder->getInt64Ty() );
|
|
|
|
native_registers[ ZYDIS_REGISTER_RFLAGS ] = llvm_module->getGlobalVariable( "rflags" );
|
|
|
|
native_registers[ ZYDIS_REGISTER_RFLAGS ] = llvm_module->getGlobalVariable( "rflags" );
|
|
|
|
|
|
|
|
flags = ir_builder->CreateAlloca( ir_builder->getInt64Ty(), nullptr, "flags" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vmp_rtn_t::create_virtual_registers( void )
|
|
|
|
void vmp_rtn_t::create_virtual_registers( void )
|
|
|
@ -147,11 +148,11 @@ namespace vm
|
|
|
|
void vmp_rtn_t::push( std::uint8_t byte_size, llvm::Value *input_value )
|
|
|
|
void vmp_rtn_t::push( std::uint8_t byte_size, llvm::Value *input_value )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Load the current stack index into a temporary variable
|
|
|
|
// Load the current stack index into a temporary variable
|
|
|
|
auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
|
|
|
|
auto current_stack_index = ir_builder->CreateLoad( ir_builder->getInt64Ty(), stack_ptr, false );
|
|
|
|
|
|
|
|
|
|
|
|
// Subtract the input value size from the current stack index
|
|
|
|
// Subtract the input value size from the current stack index
|
|
|
|
auto new_stack_index = ir_builder->CreateSub(
|
|
|
|
auto new_stack_index =
|
|
|
|
current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) );
|
|
|
|
ir_builder->CreateSub( current_stack_index, llvm::ConstantInt::get( ir_builder->getInt64Ty(), byte_size ) );
|
|
|
|
|
|
|
|
|
|
|
|
// Store the newly calculated stack index into VSP
|
|
|
|
// Store the newly calculated stack index into VSP
|
|
|
|
ir_builder->CreateStore( new_stack_index, stack_ptr );
|
|
|
|
ir_builder->CreateStore( new_stack_index, stack_ptr );
|
|
|
@ -178,67 +179,56 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
llvm::Value *vmp_rtn_t::pop( std::uint8_t byte_size )
|
|
|
|
llvm::Value *vmp_rtn_t::pop( std::uint8_t byte_size )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Load the current stack index into a temporary variable
|
|
|
|
llvm::Value *output_value = nullptr;
|
|
|
|
auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
|
|
|
|
auto current_spi = ir_builder->CreateLoad( ir_builder->getInt64Ty(), stack_ptr, false );
|
|
|
|
|
|
|
|
|
|
|
|
// Get a pointer to the top byte of the stack
|
|
|
|
|
|
|
|
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
|
|
|
|
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
|
|
|
|
llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index };
|
|
|
|
llvm::Value *indices[ 2 ] = { i64_zero, current_spi };
|
|
|
|
auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
|
|
|
auto top_stack = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
|
|
|
|
|
|
|
|
|
|
|
// Read the value at the top of the stack
|
|
|
|
if ( byte_size > 1 )
|
|
|
|
llvm::Value *output_value = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( byte_size == 1 )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 8 ), stack_ptr );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Cast the current stack pointer so the stack item width matches the width of the output value
|
|
|
|
|
|
|
|
auto casted_ptr = ir_builder->CreatePointerCast(
|
|
|
|
auto casted_ptr = ir_builder->CreatePointerCast(
|
|
|
|
stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
|
|
|
|
top_stack, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
|
|
|
|
|
|
|
|
|
|
|
|
output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr );
|
|
|
|
output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
output_value = ir_builder->CreateLoad( ir_builder->getInt8Ty(), top_stack );
|
|
|
|
|
|
|
|
|
|
|
|
// Subtract the input value size from the current stack index
|
|
|
|
|
|
|
|
auto new_stack_index = ir_builder->CreateAdd(
|
|
|
|
auto new_stack_index = ir_builder->CreateAdd(
|
|
|
|
current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) );
|
|
|
|
current_spi, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) );
|
|
|
|
|
|
|
|
|
|
|
|
// Store the newly calculated stack index into VSP
|
|
|
|
ir_builder->CreateStore( new_stack_index, stack_ptr );
|
|
|
|
ir_builder->CreateStore( new_stack_index, this->stack_ptr );
|
|
|
|
|
|
|
|
return output_value;
|
|
|
|
return output_value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
llvm::Value *vmp_rtn_t::peek( std::uint8_t byte_size, std::uint8_t byte_offset )
|
|
|
|
llvm::Value *vmp_rtn_t::peek( std::uint8_t byte_size, std::uint8_t byte_offset )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Load the current stack index into a temporary variable
|
|
|
|
auto current_spi = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
|
|
|
|
auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( byte_offset )
|
|
|
|
if ( byte_offset )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto t1 = ir_builder->CreateAdd(
|
|
|
|
auto t1 = ir_builder->CreateAdd(
|
|
|
|
current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_offset ) );
|
|
|
|
current_spi, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_offset ) );
|
|
|
|
|
|
|
|
|
|
|
|
current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), t1, false );
|
|
|
|
current_spi = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), t1, false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Get a pointer to the top byte of the stack + byte_offset (if any)
|
|
|
|
|
|
|
|
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
|
|
|
|
llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) );
|
|
|
|
llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index };
|
|
|
|
llvm::Value *indices[ 2 ] = { i64_zero, current_spi };
|
|
|
|
auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
|
|
|
auto top_stack = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
|
|
|
|
|
|
|
|
|
|
|
if ( byte_size != 1 )
|
|
|
|
if ( byte_size > 1 )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto casted_ptr = ir_builder->CreatePointerCast(
|
|
|
|
auto casted_ptr = ir_builder->CreatePointerCast(
|
|
|
|
stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
|
|
|
|
top_stack, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) );
|
|
|
|
|
|
|
|
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr );
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), stack_ptr );
|
|
|
|
return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), top_stack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|