@ -12,98 +12,8 @@ namespace vm
create_routine ( ) ;
ir_builder = std : : make_shared < llvm_irbuilder_t > ( * llvm_ctx ) ;
ir_builder - > SetInsertPoint ( llvm_code_blocks [ 0 ] . second ) ;
// do not change the ordering of these function calls...
create_native_registers ( ) ;
create_virtual_stack ( ) ;
lift_vm_entry ( ) ;
create_virtual_registers ( ) ;
}
void vmp_rtn_t : : lift_vm_entry ( void )
{
for ( const auto & instr : vm_ctx - > vm_entry )
{
if ( instr . instr . mnemonic = = ZYDIS_MNEMONIC_PUSH )
{
// push [xxxxx] we know this is zero and the next push is the image base...
if ( instr . instr . operands [ 0 ] . type = = ZYDIS_OPERAND_TYPE_MEMORY )
{
push ( 8 , llvm : : ConstantInt : : get ( ir_builder - > getInt64Ty ( ) , 0ull ) ) ;
push ( 8 , llvm : : ConstantInt : : get ( ir_builder - > getInt64Ty ( ) , vm_ctx - > image_base ) ) ;
break ; // dont make these if statements a switch case because we need to use this break...
}
else if ( instr . instr . operands [ 0 ] . type = = ZYDIS_OPERAND_TYPE_IMMEDIATE )
{
push ( 8 , llvm : : ConstantInt : : get ( ir_builder - > getInt64Ty ( ) , instr . instr . operands [ 0 ] . imm . value . u ,
false ) ) ;
}
else if ( instr . instr . operands [ 0 ] . type = = ZYDIS_OPERAND_TYPE_REGISTER )
{
push ( 8 , load_value ( 8 , native_registers [ instr . instr . operands [ 0 ] . reg . value ] ) ) ;
}
}
else if ( instr . instr . mnemonic = = ZYDIS_MNEMONIC_PUSHFQ )
{
// just push 0 as the value itself wont matter...
push ( 8 , load_value ( 8 , native_registers [ ZYDIS_REGISTER_RFLAGS ] ) ) ;
}
}
}
void vmp_rtn_t : : create_native_registers ( void )
{
llvm_module - > getOrInsertGlobal ( " rax " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RAX ] = llvm_module - > getGlobalVariable ( " rax " ) ;
llvm_module - > getOrInsertGlobal ( " rbx " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RBX ] = llvm_module - > getGlobalVariable ( " rbx " ) ;
llvm_module - > getOrInsertGlobal ( " rcx " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RCX ] = llvm_module - > getGlobalVariable ( " rcx " ) ;
llvm_module - > getOrInsertGlobal ( " rdx " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RDX ] = llvm_module - > getGlobalVariable ( " rdx " ) ;
llvm_module - > getOrInsertGlobal ( " rsi " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RSI ] = llvm_module - > getGlobalVariable ( " rsi " ) ;
llvm_module - > getOrInsertGlobal ( " rdi " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RDI ] = llvm_module - > getGlobalVariable ( " rdi " ) ;
llvm_module - > getOrInsertGlobal ( " rbp " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RBP ] = llvm_module - > getGlobalVariable ( " rbp " ) ;
llvm_module - > getOrInsertGlobal ( " rsp " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RSP ] = llvm_module - > getGlobalVariable ( " rsp " ) ;
llvm_module - > getOrInsertGlobal ( " r8 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R8 ] = llvm_module - > getGlobalVariable ( " r8 " ) ;
llvm_module - > getOrInsertGlobal ( " r9 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R9 ] = llvm_module - > getGlobalVariable ( " r9 " ) ;
llvm_module - > getOrInsertGlobal ( " r10 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R10 ] = llvm_module - > getGlobalVariable ( " r10 " ) ;
llvm_module - > getOrInsertGlobal ( " r11 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R11 ] = llvm_module - > getGlobalVariable ( " r11 " ) ;
llvm_module - > getOrInsertGlobal ( " r12 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R12 ] = llvm_module - > getGlobalVariable ( " r12 " ) ;
llvm_module - > getOrInsertGlobal ( " r13 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R13 ] = llvm_module - > getGlobalVariable ( " r13 " ) ;
llvm_module - > getOrInsertGlobal ( " r14 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R14 ] = llvm_module - > getGlobalVariable ( " r14 " ) ;
llvm_module - > getOrInsertGlobal ( " r15 " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_R15 ] = llvm_module - > getGlobalVariable ( " r15 " ) ;
llvm_module - > getOrInsertGlobal ( " rflags " , ir_builder - > getInt64Ty ( ) ) ;
native_registers [ ZYDIS_REGISTER_RFLAGS ] = llvm_module - > getGlobalVariable ( " rflags " ) ;
flags = ir_builder - > CreateAlloca ( ir_builder - > getInt64Ty ( ) , nullptr , " flags " ) ;
create_virtual_registers ( ) ;
}
void vmp_rtn_t : : create_virtual_registers ( void )
@ -119,7 +29,8 @@ namespace vm
{
// function has no arguments and returns void... maybe change this in the future as i learn
// more and more LLVM...
auto func_ty = llvm : : FunctionType : : get ( llvm : : Type : : getVoidTy ( * llvm_ctx ) , false ) ;
auto func_ty = llvm : : FunctionType : : get ( llvm : : Type : : getVoidTy ( * llvm_ctx ) ,
{ llvm : : PointerType : : getInt64PtrTy ( * llvm_ctx ) } , false ) ;
// convert the rtn_begin address to a hex string and prepend "rtn_" to it...
std : : stringstream rtn_name ;
@ -127,6 +38,7 @@ namespace vm
llvm_fptr = llvm : : Function : : Create ( func_ty , llvm : : GlobalValue : : LinkageTypes : : ExternalLinkage ,
rtn_name . str ( ) . c_str ( ) , * llvm_module ) ;
for ( const auto & vmp2_code_block : vmp2_code_blocks )
{
// create basic block name... block_xxxxxxxx format...
@ -137,78 +49,33 @@ namespace vm
}
}
void vmp_rtn_t : : push ( std : : uint8_t byte_size , llvm_value_t * val )
{
auto spi = ir_builder - > CreateLoad ( ir_builder - > getInt64Ty ( ) , stack_ptr , false ) ;
auto new_spi = ir_builder - > CreateSub ( spi , llvm : : ConstantInt : : get ( ir_builder - > getInt64Ty ( ) , byte_size ) ) ;
ir_builder - > CreateStore ( new_spi , stack_ptr ) ;
auto * i64_zero = llvm : : ConstantInt : : get ( * llvm_ctx , llvm : : APInt ( 64 , 0 ) ) ;
llvm_value_t * indices [ 2 ] = { i64_zero , new_spi } ;
auto stack_ptr = ir_builder - > CreateInBoundsGEP ( virtual_stack , llvm : : ArrayRef < llvm_value_t * > ( indices , 2 ) ) ;
if ( byte_size > 1 )
{
auto casted_ptr = ir_builder - > CreatePointerCast (
stack_ptr , llvm : : PointerType : : get ( llvm : : IntegerType : : get ( * llvm_ctx , byte_size * 8 ) , 0 ) ) ;
ir_builder - > CreateStore ( val , casted_ptr ) ;
}
else
ir_builder - > CreateStore ( val , stack_ptr ) ;
}
llvm_value_t * vmp_rtn_t : : pop ( std : : uint8_t byte_size )
void vmp_rtn_t : : push ( std : : uint8_t num_bytes , llvm_value_t * val )
{
llvm_value_t * output_value = nullptr ;
auto current_spi = ir_builder - > CreateLoad ( ir_builder - > getInt64Ty ( ) , stack_ptr , false ) ;
llvm_value_t * i64_zero = llvm : : ConstantInt : : get ( * llvm_ctx , llvm : : APInt ( 64 , 0 ) ) ;
llvm_value_t * indices [ 2 ] = { i64_zero , current_spi } ;
auto top_stack = ir_builder - > CreateInBoundsGEP ( virtual_stack , llvm : : ArrayRef < llvm : : Value * > ( indices , 2 ) ) ;
if ( byte_size > 1 )
{
auto casted_ptr = ir_builder - > CreatePointerCast (
top_stack , llvm : : PointerType : : get ( llvm : : IntegerType : : get ( * llvm_ctx , byte_size * 8 ) , 0 ) ) ;
// sub rsp, num_bytes
auto rsp = llvm_fptr - > getArg ( 0 ) ;
auto rsp_i64 = ir_builder - > CreatePtrToInt ( rsp , ir_builder - > getInt64Ty ( ) ) ;
auto sub_rsp_val = ir_builder - > CreateSub ( rsp_i64 , ir_builder - > getInt64 ( num_bytes ) ) ;
ir_builder - > CreateStore ( sub_rsp_val , rsp ) ;
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 ) ;
auto new_spi = ir_builder - > CreateAdd (
current_spi , llvm : : ConstantInt : : get ( llvm : : IntegerType : : get ( * llvm_ctx , 64 ) , byte_size ) ) ;
ir_builder - > CreateStore ( new_spi , stack_ptr ) ;
return output_value ;
// mov [rsp], val
auto rsp_cast_ptr = ir_builder - > CreatePointerCast (
rsp , llvm : : PointerType : : get ( llvm : : IntegerType : : get ( * llvm_ctx , num_bytes * 8 ) , false ) ) ;
ir_builder - > CreateStore ( val , rsp_cast_ptr ) ;
}
llvm_value_t * vmp_rtn_t : : p eek( std : : uint8_t byte_size , std : : uint8_t byte_offset )
llvm_value_t * vmp_rtn_t : : pop ( std : : uint8_t num_bytes )
{
auto current_spi = ir_builder - > CreateLoad ( llvm : : IntegerType : : get ( * llvm_ctx , 64 ) , stack_ptr , false ) ;
if ( byte_offset )
{
auto t1 = ir_builder - > CreateAdd (
current_spi , llvm : : ConstantInt : : get ( llvm : : IntegerType : : get ( * llvm_ctx , 64 ) , byte_offset ) ) ;
current_spi = ir_builder - > CreateLoad ( llvm : : IntegerType : : get ( * llvm_ctx , 64 ) , t1 , false ) ;
}
auto i64_zero = llvm : : ConstantInt : : get ( * llvm_ctx , llvm : : APInt ( 64 , 0 ) ) ;
llvm_value_t * indices [ 2 ] = { i64_zero , current_spi } ;
auto top_stack = ir_builder - > CreateInBoundsGEP ( virtual_stack , llvm : : ArrayRef < llvm : : Value * > ( indices , 2 ) ) ;
// mov rax, [rsp]
auto rsp = llvm_fptr - > getArg ( 0 ) ;
auto rsp_cast_ptr = ir_builder - > CreatePointerCast (
rsp , llvm : : PointerType : : get ( llvm : : IntegerType : : get ( * llvm_ctx , num_bytes * 8 ) , false ) ) ;
auto pop_val = ir_builder - > CreateLoad ( rsp_cast_ptr ) ;
if ( byte_size > 1 )
{
auto casted_ptr = ir_builder - > CreatePointerCast (
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 ) ;
}
else
return ir_builder - > CreateLoad ( llvm : : IntegerType : : get ( * llvm_ctx , byte_size * 8 ) , top_stack ) ;
// add rsp, num_bytes
auto rsp_i64 = ir_builder - > CreatePtrToInt ( rsp , ir_builder - > getInt64Ty ( ) ) ;
auto sub_rsp_val = ir_builder - > CreateAdd ( rsp_i64 , ir_builder - > getInt64 ( num_bytes ) ) ;
ir_builder - > CreateStore ( sub_rsp_val , rsp ) ;
return pop_val ;
}
llvm_value_t * vmp_rtn_t : : load_value ( std : : uint8_t byte_size , llvm_global_value_t * var )
@ -235,18 +102,6 @@ namespace vm
return ir_builder - > CreateLoad ( llvm : : IntegerType : : get ( * llvm_ctx , byte_size * 8 ) , var ) ;
}
void vmp_rtn_t : : create_virtual_stack ( void )
{
// allocate stack space...
virtual_stack = ir_builder - > CreateAlloca ( llvm : : ArrayType : : get ( llvm : : IntegerType : : get ( * llvm_ctx , 8 ) , 1024 ) ,
nullptr , " stack " ) ;
// allocate stack pointer...
stack_ptr = ir_builder - > CreateAlloca ( llvm : : IntegerType : : get ( * llvm_ctx , 64 ) , nullptr , " sp " ) ;
ir_builder - > CreateStore ( llvm : : ConstantInt : : get ( llvm : : IntegerType : : getInt64Ty ( * llvm_ctx ) , 1024 ) ,
stack_ptr ) ;
}
llvm_function_t * vmp_rtn_t : : lift ( void )
{
auto & code_blocks = llvm_fptr - > getBasicBlockList ( ) ;
@ -255,7 +110,6 @@ namespace vm
for ( auto idx = 0u ; idx < code_blocks . size ( ) ; + + idx )
{
ir_builder - > SetInsertPoint ( llvm_code_blocks [ idx ] . second ) ;
for ( auto & vinstr : vmp2_code_blocks [ idx ] . vinstrs )
{
if ( ! lifters - > lift ( this , vmp2_code_blocks [ idx ] , vinstr , ir_builder . get ( ) ) )