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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
#pragma once
#include <memory>
#include <Windows.h>
#include <winternl.h>
#include <fstream>
#include "vmt.hpp"
#include "util.hpp"
#include "x86.hpp"
#include "console.hpp"
//IFACE_DLLMAIN - interfaces are passed through dllmain and below code doesnt need to be ran
#ifndef _DEBUG
#define IFACE_DLLMAIN
#endif
#ifdef IFACE_DLLMAIN
#include "iface_dllmain_impl.hpp"
#else
NAMESPACE_REGION( factory )
namespace interfaces
{
struct interface_iterator_t {
void* m_create_fn;
char* m_name;
interface_iterator_t* m_next;
};
inline auto follow_createinterface_export( uintptr_t export_ ) {
/*
.text:006F5F00 CreateInterface proc near
.text:006F5F00 push ebp
.text:006F5F01 mov ebp, esp
.text:006F5F03 pop ebp
.text:006F5F04 jmp sub_6F5E90
*/
uintptr_t jmp = export_ + 0x4;
uintptr_t jmp_target = jmp + *( uintptr_t* )( jmp + 0x1 ) + 0x5;
return jmp_target;
}
inline auto find_list_ptr( uintptr_t createinterface ) {
/*
.text:006F5E90 push ebp
.text:006F5E91 mov ebp, esp
.text:006F5E93 push esi
.text:006F5E94 mov esi, dword_2EEFDE4
.text:006F5E9A push edi
*/
auto iterator_ptr = **( uintptr_t*** )( createinterface + 0x6 );
return iterator_ptr;
}
inline bool is_createinterface_export( uintptr_t export_ ) {
return *( uint8_t* )( export_ ) == x86::encode_push_reg( x86::reg::ebp )
&& *( uint8_t* )( export_ + 4 ) == 0xe9
&& *( uint8_t* )( export_ + 9 ) == 0xcc
&& *( uint8_t* )( export_ + 10 ) == 0xcc;
}
inline bool is_createinterface_fn( uintptr_t fn_ ) {
return *( uint8_t* )( fn_ ) == x86::encode_push_reg( x86::reg::ebp )
&& *( uint8_t* )( fn_ + 4 ) == 0x8b
&& *( uint8_t* )( fn_ + 10 ) == x86::encode_push_reg( x86::reg::edi );
}
class c_interface_manager {
public:
struct interface_data_t {
std::string m_name;
std::string m_module;
size_t m_version;
uintptr_t m_ptr;
template < typename t > __forceinline t get( ) {
return reinterpret_cast< t >( m_ptr );
}
};
c_interface_manager( );
//iterate the interface list to find our desired version
template < typename t = void* >
t find_interface( const std::string& module_, std::string name ) {
//avoid finding interfaces with matching names
if( !::isdigit( name[ name.length( ) - 1 ] ) )
name += "0";
for( auto& it : m_interfaces ) {
if( !it.m_module.compare( module_ )
&& !it.m_name.compare( name ) ) {
g_con->print( xors( "%s version %u found in %s at 0x%08x\n" ),
name.c_str( ),
it.m_version,
it.m_module.c_str( ),
it.m_ptr );
return it.get< t >( );
}
}
g_con->print( xors( "%s not found\n" ), name.c_str( ) );
return t{ };
}
template < typename t = void* >
t find_interface( std::string name ) {
//avoid finding interfaces with matching names
if( !::isdigit( name[ name.length( ) - 1 ] ) )
name += '0';
for( auto& it : m_interfaces ) {
if( strstr( it.m_name.c_str( ), name.c_str( ) ) ) {
g_con->print( xors( "%s version %u found in %s at 0x%08x\n" ),
name.c_str( ),
it.m_version,
it.m_module.c_str( ),
it.m_ptr );
return it.get< t >( );
}
}
g_con->print( xors( "%s not found\n" ), name.c_str( ) );
return t{ };
}
void dump_interface_list( ) {
for( auto& it : m_interfaces ) {
g_con->print( xors( "%s version %u in %s at 0x%08x\n" ),
it.m_name.c_str( ),
it.m_version,
it.m_module.c_str( ),
it.m_ptr );
}
}
private:
uintptr_t find_createinterface( void* module_ );
std::vector< interface_data_t > m_interfaces;
};
}
END_REGION
#endif
extern HMODULE g_dll;
extern factory::interfaces::c_interface_manager g_factory;
|