1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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;
}
|