added code to add relocs in unpacked sections...

merge-requests/6/head
_xeroxz 3 years ago
parent f4229133ad
commit ceb4f38cb7

@ -2,13 +2,27 @@
#include <functional> #include <functional>
#include <unicorn/unicorn.h> #include <unicorn/unicorn.h>
#include <xtils.hpp>
#include <Zydis/Zydis.h> #include <Zydis/Zydis.h>
#include <atomic> #include <atomic>
#include <fstream> #include <fstream>
#include <map> #include <map>
#include <nt/image.hpp> #include <nt/image.hpp>
#include <vector> #include <vector>
#include <xtils.hpp>
struct process_module_info_t
{
std::uintptr_t section, mapped_base, img_base;
std::uint32_t image_size, flags;
std::uint16_t loaded_order_index, init_order_index, load_count, file_name_offset;
char file_path[ 0x100 ];
};
struct process_modules_t
{
std::uint32_t cnt;
process_module_info_t modules[ VAR_LEN ];
};
#define PAGE_4KB 0x1000 #define PAGE_4KB 0x1000
#define STACK_SIZE PAGE_4KB * 512 #define STACK_SIZE PAGE_4KB * 512
@ -50,12 +64,9 @@ namespace engine
std::uintptr_t img_base, img_size, heap_offset, pack_section_offset; std::uintptr_t img_base, img_size, heap_offset, pack_section_offset;
win::image_t<> *win_img; win::image_t<> *win_img;
static void alloc_pool_hook( uc_engine *, unpack_t * );
static void free_pool_hook( uc_engine *, unpack_t * );
static void local_alloc_hook( uc_engine *, unpack_t * ); static void local_alloc_hook( uc_engine *, unpack_t * );
static void local_free_hook( uc_engine *, unpack_t * ); static void local_free_hook( uc_engine *, unpack_t * );
static void load_library_hook( uc_engine *, unpack_t * ); static void load_library_hook( uc_engine *, unpack_t * );
static void query_system_info_hook( uc_engine *, unpack_t * );
static void uc_strcpy( uc_engine *, char *buff, std::uintptr_t addr ); static void uc_strcpy( uc_engine *, char *buff, std::uintptr_t addr );
static bool iat_dispatcher( uc_engine *uc, uint64_t address, uint32_t size, unpack_t *unpack ); static bool iat_dispatcher( uc_engine *uc, uint64_t address, uint32_t size, unpack_t *unpack );
@ -68,11 +79,8 @@ namespace engine
std::vector< std::uintptr_t > loaded_modules; std::vector< std::uintptr_t > loaded_modules;
std::map< std::string, std::pair< std::uint32_t, iat_hook_t > > iat_hooks = { std::map< std::string, std::pair< std::uint32_t, iat_hook_t > > iat_hooks = {
{ "ExAllocatePool", { EX_ALLOCATE_POOL_VECTOR, &alloc_pool_hook } },
{ "ExFreePool", { EX_FREE_POOL_VECTOR, &free_pool_hook } },
{ "LocalAlloc", { LOCAL_ALLOC_VECTOR, &local_alloc_hook } }, { "LocalAlloc", { LOCAL_ALLOC_VECTOR, &local_alloc_hook } },
{ "LocalFree", { LOCAL_FREE_VECTOR, &local_free_hook } }, { "LocalFree", { LOCAL_FREE_VECTOR, &local_free_hook } },
{ "LoadLibraryA", { LOAD_LIBRARY_VECTOR, &load_library_hook } }, { "LoadLibraryA", { LOAD_LIBRARY_VECTOR, &load_library_hook } } };
{ "NtQuerySystemInformation", { NT_QUERY_SYSTEM_INFO_VECTOR, &query_system_info_hook } } };
}; };
} // namespace engine } // namespace engine

@ -213,80 +213,107 @@ namespace engine
return false; return false;
} }
auto img = reinterpret_cast< win::image_t<> * >( output.data() ); auto output_img = reinterpret_cast< win::image_t<> * >( output.data() );
auto sections = img->get_nt_headers()->get_sections(); auto sections = output_img->get_nt_headers()->get_sections();
auto section_cnt = img->get_file_header()->num_sections; auto section_cnt = output_img->get_file_header()->num_sections;
// { section virtual address -> vector of section offset to reloc }
std::map< std::uint32_t, std::vector< std::uint16_t > > new_relocs;
// search executable sections for MOV RAX, 00 00 00 00 00 00 00 00...
std::for_each( sections, sections + section_cnt, [ & ]( win::section_header_t &header ) { std::for_each( sections, sections + section_cnt, [ & ]( win::section_header_t &header ) {
if ( header.characteristics.mem_execute && !header.ptr_raw_data && !header.size_raw_data ) if ( header.characteristics.mem_execute )
{ {
auto result = output.data() + header.virtual_address; auto result = output.data() + header.virtual_address;
std::vector< std::uintptr_t > reloc_rvas;
do do
{ {
result = reinterpret_cast< std::uint8_t * >( xtils::um_t::get_instance()->sigscan( result = reinterpret_cast< std::uint8_t * >( xtils::um_t::get_instance()->sigscan(
result, header.virtual_size, MOV_RAX_0_SIG, MOV_RAX_0_MASK ) ); result,
header.virtual_size -
( reinterpret_cast< std::uintptr_t >( result ) -
( header.virtual_address + reinterpret_cast< std::uintptr_t >( output.data() ) ) ),
MOV_RAX_0_SIG, MOV_RAX_0_MASK ) );
if ( result )
{
result += 2; // advance ahead of the 0x48 0xB8...
// offset from section begin... // offset from section begin...
auto reloc_offset = ( reinterpret_cast< std::uintptr_t >( result ) + 2 ) - auto reloc_offset =
( reinterpret_cast< std::uintptr_t >( result ) ) -
reinterpret_cast< std::uintptr_t >( output.data() + header.virtual_address ); reinterpret_cast< std::uintptr_t >( output.data() + header.virtual_address );
reloc_rvas.push_back( reloc_offset ); new_relocs[ ( header.virtual_address + reloc_offset ) & ~0xFFFull ].push_back( reloc_offset );
}
} while ( result ); } while ( result );
}
header.ptr_raw_data = header.virtual_address;
header.size_raw_data = header.virtual_size;
} );
// determines if a relocation block exists for a given page...
static const auto has_reloc_page = [ & ]( std::uint32_t page ) -> bool {
auto img = reinterpret_cast< win::image_t<> * >( output.data() );
auto sections = img->get_nt_headers()->get_sections();
auto section_cnt = img->get_file_header()->num_sections;
auto basereloc_dir = img->get_directory( win::directory_id::directory_entry_basereloc ); auto basereloc_dir = img->get_directory( win::directory_id::directory_entry_basereloc );
auto reloc_dir = reinterpret_cast< win::reloc_directory_t * >( basereloc_dir->rva + output.data() ); auto reloc_dir = reinterpret_cast< win::reloc_directory_t * >( basereloc_dir->rva + output.data() );
win::reloc_block_t *reloc_block = &reloc_dir->first_block; win::reloc_block_t *reloc_block = &reloc_dir->first_block;
//
// assuming that the .reloc section is the last section in the entire module...
//
while ( reloc_block->base_rva && reloc_block->size_block ) while ( reloc_block->base_rva && reloc_block->size_block )
reloc_block = reloc_block->next(); {
if ( reloc_block->base_rva == page )
return true;
reloc_block->base_rva = header.virtual_address; reloc_block = reloc_block->next();
reloc_block->size_block = reloc_rvas.size() * sizeof win::reloc_entry_t;
} }
header.ptr_raw_data = header.virtual_address; return false;
header.size_raw_data = header.virtual_size; };
} );
return true;
}
void unpack_t::alloc_pool_hook( uc_engine *uc_ctx, unpack_t *obj ) // calc size to add new reloc info...
{ std::size_t resize_cnt = 0ull;
uc_err err; for ( const auto &[ reloc_rva, relocs ] : new_relocs )
std::uintptr_t rax, rdx; if ( !has_reloc_page( reloc_rva ) )
resize_cnt += sizeof( win::reloc_block_t ) + ( relocs.size() * sizeof( win::reloc_entry_t ) );
if ( ( err = uc_reg_read( uc_ctx, UC_X86_REG_RDX, &rdx ) ) ) // last block needs to contain 0 for block_rva and size_block...
{ if ( resize_cnt )
std::printf( "> failed to read RDX... reason = %d\n", rdx ); resize_cnt += sizeof win::reloc_block_t;
return;
}
auto size = ( ( rdx + PAGE_4KB ) & ~0xFFFull ); output.resize( output.size() + resize_cnt );
if ( ( err = uc_mem_map( uc_ctx, HEAP_BASE + obj->heap_offset, size, UC_PROT_ALL ) ) ) output_img = reinterpret_cast< win::image_t<> * >( output.data() );
auto basereloc_dir = output_img->get_directory( win::directory_id::directory_entry_basereloc );
auto reloc_dir = reinterpret_cast< win::reloc_directory_t * >( basereloc_dir->rva + output.data() );
basereloc_dir->size += resize_cnt;
for ( const auto &[ reloc_rva, relocs ] : new_relocs )
{ {
std::printf( "> failed to allocate memory... reason = %d\n", err ); if ( has_reloc_page( reloc_rva ) )
return; continue;
}
rax = HEAP_BASE + obj->heap_offset; win::reloc_block_t *reloc_block = &reloc_dir->first_block;
obj->heap_offset += size; while ( reloc_block->base_rva && reloc_block->size_block )
reloc_block = reloc_block->next();
if ( ( err = uc_reg_write( uc_ctx, UC_X86_REG_RAX, &rax ) ) ) reloc_block->base_rva = reloc_rva;
reloc_block->size_block = relocs.size() * sizeof( win::reloc_entry_t ) + sizeof uint64_t;
reloc_block->next()->base_rva = 0ull;
reloc_block->next()->size_block = 0ull;
for ( auto idx = 0u; idx < relocs.size(); ++idx )
{ {
std::printf( "> failed to write rax... reason = %d\n", err ); reloc_block->entries[ idx ].type = win::reloc_type_id::rel_based_dir64;
return; reloc_block->entries[ idx ].offset = relocs[ idx ];
} }
} }
return true;
void unpack_t::free_pool_hook( uc_engine *uc_ctx, unpack_t *obj )
{
// TODO
} }
void unpack_t::local_alloc_hook( uc_engine *uc_ctx, unpack_t *obj ) void unpack_t::local_alloc_hook( uc_engine *uc_ctx, unpack_t *obj )
@ -382,37 +409,6 @@ namespace engine
} }
} }
void unpack_t::query_system_info_hook( uc_engine *uc_ctx, unpack_t *obj )
{
uc_err err;
std::uintptr_t rcx, rdx, r8, r9;
if ( ( err = uc_reg_read( uc_ctx, UC_X86_REG_RCX, &rcx ) ) )
{
std::printf( "> failed to read reg... reason = %d\n", err );
return;
}
if ( ( err = uc_reg_read( uc_ctx, UC_X86_REG_RDX, &rdx ) ) )
{
std::printf( "> failed to read reg... reason = %d\n", err );
return;
}
if ( ( err = uc_reg_read( uc_ctx, UC_X86_REG_R8, &r8 ) ) )
{
std::printf( "> failed to read reg... reason = %d\n", err );
return;
}
if ( ( err = uc_reg_read( uc_ctx, UC_X86_REG_R9, &r9 ) ) )
{
std::printf( "> failed to read reg... reason = %d\n", err );
return;
}
std::printf( "> rcx = 0x%p, rdx = 0x%p, r8 = 0x%p, r9 = 0x%p\n", rcx, rdx, r8, r9 );
}
void unpack_t::uc_strcpy( uc_engine *uc_ctx, char *buff, std::uintptr_t addr ) void unpack_t::uc_strcpy( uc_engine *uc_ctx, char *buff, std::uintptr_t addr )
{ {
uc_err err; uc_err err;

Loading…
Cancel
Save