summaryrefslogtreecommitdiff
path: root/src/disasm.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/disasm.h')
-rw-r--r--src/disasm.h111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/disasm.h b/src/disasm.h
new file mode 100644
index 0000000..8c12c9a
--- /dev/null
+++ b/src/disasm.h
@@ -0,0 +1,111 @@
+//|_ _ _. _ ._ |_ _. _ |
+//| | (/_ (_| \/ (/_ | | | | (_| (_ |<
+
+#pragma once
+#pragma warning( disable: 4102 )
+
+#include "util.h"
+#include "asmutil.h"
+#include "x86.h"
+
+#define DISASM_SIG() _DISASM_SIG1( __COUNTER__ )
+#define _DISASM_SIG1( x ) _DISASM_SIG( x )
+#define _DISASM_SIG( x ) \
+ db( 0xeb ) db( 0x10 ) db( 0x66 ) db( 0xb8 ) db( 0x39 ) db( 0x1b ) \
+ __asm mov eax, ##x __asm mov eax, ##x^(##x/2) db( 0xcc ) db( 0xcc )
+
+
+struct DISASM_INFO {
+ U8* func_start;
+ U32 func_length;
+ U8* sig_ptr;
+ I32 check;
+};
+
+const I32 DISASM_SIG_LENGTH = 18;
+
+U8* disasm_get_wrapper_target( void* funptr ) {
+ U8* func = (U8*)funptr;
+
+ if( func[0] != 0xe9 || func[5] != 0xe9 )
+ return 0;
+
+ U32 jmp_rel = *(U32*)( &func[1] );
+ return (U8*)( funptr ) + jmp_rel + 5;
+}
+
+U8* disasm_find_sig_end( void* funptr, int* out_checknr = 0 ) {
+ static const char* signature_str = "eb 10 66 b8 39 1b b8 ? ? ? ? b8 ? ? ? ? cc cc";
+ U8 *ret = 0, *ptr = (U8*)funptr;
+ U32 sig_size;
+ U8* sig_bytes = u_parse_signature( signature_str, &sig_size );
+
+ for( U16 i = 0; i < 64; ++i ) {
+ if( u_binary_match( ptr + i, sig_bytes, sig_size ) ) {
+ ret = ptr + i; break;
+ }
+ }
+
+ free( sig_bytes );
+ if( !ret )
+ return 0;
+
+ I32* check1 = (I32*)( ret + 7 );
+ I32* check2 = (I32*)( ret + 12 );
+ if( out_checknr )
+ *out_checknr = *check1;
+
+ if( *check2 == ( (*check1) ^ (*check1 / 2) ) )
+ return ret;
+
+ return 0;
+}
+
+U8* disasm_find_ret_instruction( void* funptr ) {
+ U8* ptr = (U8*)funptr;
+
+ for( U16 i = 0; i < 64; ++i ) {
+ if( ptr[i] == RET_FAR
+ || ptr[i] == RET_NEAR
+ || ptr[i] == RET_FAR_IMM16
+ || ptr[i] == RET_NEAR_IMM16 ) {
+ return ptr + i;
+ }
+ }
+
+ return 0;
+}
+
+void disasm_print( DISASM_INFO disasm ) {
+ for( U32 i = 0; i < disasm.func_length; ++i ) {
+ if( !( i % 8 ) )
+ con_print( CONFG_RED, "\n0x%08x : ", (U32)(disasm.func_start + i) );
+
+ con_print( CONFG_WHITE, "%02x ", disasm.func_start[i] );
+ }
+ con_print( CONFG_WHITE, "\n" );
+}
+
+DISASM_INFO disasm_function( void* func ) {
+ DISASM_INFO ret{};
+ I32 checknr;
+ U8* signature = disasm_find_sig_end( func, &checknr );
+ if( !signature ) {
+ U8* wrapper_target = disasm_get_wrapper_target( func );
+ if( !wrapper_target )
+ return ret;
+
+ return disasm_function( wrapper_target );
+ }
+
+ U8* ret_byte = disasm_find_ret_instruction( func );
+ if( !ret_byte )
+ return ret;
+
+ ret.func_start = (U8*)func;
+ ret.func_length = ret_byte - (U8*)func + 1;
+ ret.check = checknr;
+ ret.sig_ptr = signature;
+
+ return ret;
+} \ No newline at end of file