From 7ccb819f867493f8ec202ea3b39c94c198c64584 Mon Sep 17 00:00:00 2001 From: JustSomePwner Date: Thu, 30 Aug 2018 14:01:54 +0200 Subject: first --- loader/syscall.h | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 loader/syscall.h (limited to 'loader/syscall.h') diff --git a/loader/syscall.h b/loader/syscall.h new file mode 100644 index 0000000..0f608ba --- /dev/null +++ b/loader/syscall.h @@ -0,0 +1,167 @@ +#pragma once +#include + +#include "x86.h" + +using ulong_t = unsigned long; + +constexpr bool is86 = sizeof( uintptr_t ) == sizeof( uint32_t ); + +class c_syscalls { +protected: + std::unordered_map< std::string, std::pair< uint16_t, uint16_t > > m_syscalls; + + // 16 is very arbitrary... but whatever + // if something crashes this is why + __forceinline size_t syscall_wrapper_size( uint8_t* funptr, uint16_t *ret_c_out ) { + for ( size_t offset{ }; offset < 0x30; offset++ ) { + if ( funptr[ offset ] == x86::instruction::retn ) { + if ( ret_c_out ) + *ret_c_out = 0; + + return offset + 1; + } + else if ( funptr[ offset ] == x86::instruction::retn_imm16 ) { + if ( ret_c_out ) + *ret_c_out = *( uint16_t * )( &funptr[ offset + 1 ] ); + + return offset + 3; + } + } + return 0; + } + + __forceinline bool is_syscall( uint8_t* funptr, size_t func_size ) { + const uint32_t encoded_opcode = x86::encode_mov_imm32( x86::reg::eax ); + + if ( /*is86*/ true ? funptr[ 0 ] != encoded_opcode : !( funptr[ 0 ] == 0x4c && funptr[ 1 ] == 0x8b && funptr[ 2 ] == 0xd1 ) ) + return false; + + for ( size_t offset{ }; offset < func_size; offset++ ) { + if ( true /*is86*/ ) { + if ( ( funptr[ offset ] == x86::instruction::fs && // win7 + funptr[ offset + 1 ] == x86::instruction::call ) || + + ( funptr[ offset ] == x86::instruction::call && // win10 + funptr[ offset + 1 ] == 0xd2 /*call edx*/ ) ) + + return true; + + } + + else { + if ( funptr[ offset ] == 0x0f && // win7 + win10 + funptr[ offset + 1 ] == 0x05 ) + return true; + } + } + + return false; + } + + __forceinline uint16_t get_syscall_index( uintptr_t func_addr, std::ptrdiff_t *stub_offset = nullptr, uint16_t *ret_c_out = nullptr ) { + uint8_t* ubp_addr = reinterpret_cast< uint8_t* >( func_addr ); + uint16_t ret_c{ }; + size_t wrapper_size = syscall_wrapper_size( ubp_addr, &ret_c ); + + if ( ret_c_out ) + *ret_c_out = ret_c; + + wrapper_size = ( wrapper_size ) ? wrapper_size : 16; + + if ( is_syscall( ubp_addr, wrapper_size ) ) { + // mov eax, imm32 + const uint32_t encoded_opcode = x86::encode_mov_imm32( x86::reg::eax ); + + for ( size_t offset{ }; offset < wrapper_size; offset++ ) { + if ( *reinterpret_cast< uint8_t* >( func_addr + offset ) == encoded_opcode ) { + if ( stub_offset ) + *stub_offset = offset; + + return ( *reinterpret_cast< uint16_t* >( func_addr + offset + 1 ) ); + } + } + } + + return 0; + } + + std::pair< uint8_t*, size_t > m_shellcode_stub; + void *m_call_table; +public: + + __forceinline ~c_syscalls( ) { + if ( m_call_table ) + delete[ ] m_call_table; + + if ( m_shellcode_stub.first ) + delete[ ] m_shellcode_stub.first; + } + + __forceinline c_syscalls( ) : + m_syscalls{ }, m_shellcode_stub{ } { + + init( ); + + // b1gr0fl + m_call_table = new char[ 0x100000 ]; + util::set( m_call_table, 0, 0x100000 ); + + if ( true /*x86*/ ) { + for ( auto& syscall : m_syscalls ) { + void *stub_addr = ( void* )( uintptr_t( m_call_table ) + ( syscall.second.first * m_shellcode_stub.second ) ); + util::copy( stub_addr, m_shellcode_stub.first, m_shellcode_stub.second ); + + std::ptrdiff_t index_offset{ }; + get_syscall_index( ( uintptr_t )stub_addr, &index_offset ); + + auto stub_return = ( uint16_t * )( uintptr_t( stub_addr ) + m_shellcode_stub.second - 2 ); + *stub_return = syscall.second.second; + + *( uint32_t * )( uintptr_t( stub_addr ) + index_offset + 1 ) = ( syscall.second.first ); + + } + } + } + + __forceinline void init( ) { + uint32_t index; + uint16_t ret_c{ }; + + if ( g_nt.m_exports.empty( ) ) { + g_nt.dump_exports( ); + } + + for ( const auto& exp : g_nt.m_exports ) { + index = get_syscall_index( exp.second, nullptr, &ret_c ); + + if ( index ) { + m_syscalls[ exp.first ].first = index; + m_syscalls[ exp.first ].second = ret_c; + + if ( !m_shellcode_stub.first ) { + m_shellcode_stub.second = syscall_wrapper_size( reinterpret_cast< uint8_t* >( exp.second ), &ret_c ); + + m_shellcode_stub.first = new uint8_t[ m_shellcode_stub.second ]; + + m_syscalls[ exp.first ].second = ret_c; + + util::copy( m_shellcode_stub.first, reinterpret_cast< void* >( exp.second ), m_shellcode_stub.second ); + } + } + } + } + + template< typename t = void* > + __forceinline t get_syscall_func( std::string name ) { + return ( t )( GetProcAddress( GetModuleHandleA( "ntdll.dll" ), name.c_str( ) ) ); + } + + __forceinline uint16_t get_syscall( std::string name ) { + return m_syscalls[ name ].first; + } + + __forceinline auto& get_syscalls( ) { + return m_syscalls; + } +}; \ No newline at end of file -- cgit v1.2.3