blob: 0e7bc03596dc595eb384611bd122b6a3b6139fea (
plain)
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
|
#include "factory.hpp"
#ifndef IFACE_DLLMAIN
#include "fnv.hpp"
#include <algorithm>
NAMESPACE_REGION( factory )
NAMESPACE_REGION( interfaces )
//iterate all exports inside of a module and find createinterface
uintptr_t c_interface_manager::find_createinterface( void* module_ ) {
IMAGE_DOS_HEADER* dos_header;
IMAGE_NT_HEADERS* nt_headers;
uintptr_t export_address;
IMAGE_EXPORT_DIRECTORY* export_dir;
const char* export_name;
uintptr_t* names;
uintptr_t* funcs;
uint16_t* ords;
uint32_t export_hash;
dos_header = reinterpret_cast< decltype( dos_header ) >( uintptr_t( module_ ) );
nt_headers = reinterpret_cast< decltype( nt_headers ) >( uintptr_t( module_ ) + dos_header->e_lfanew );
//find addresses of functions from nt headers
export_address = nt_headers->OptionalHeader.DataDirectory[ 0 ].VirtualAddress;
export_dir = reinterpret_cast< decltype( export_dir ) >( uintptr_t( module_ ) + export_address );
if ( !export_dir->NumberOfFunctions )
return uintptr_t{ };
names = reinterpret_cast< uintptr_t* >( uintptr_t( module_ ) + export_dir->AddressOfNames );
funcs = reinterpret_cast< uintptr_t* >( uintptr_t( module_ ) + export_dir->AddressOfFunctions );
ords = reinterpret_cast< uint16_t* >( uintptr_t( module_ ) + export_dir->AddressOfNameOrdinals );
if ( names && funcs && ords ) {
//iterate the exports
for ( size_t i{ }; i < export_dir->NumberOfNames; ++i ) {
export_name = reinterpret_cast< const char* >( uintptr_t( module_ ) + names[ i ] );
export_hash = hash::fnv1a( export_name );
if ( export_hash == fnv( "CreateInterface" ) ) {
return uintptr_t( module_ ) + funcs[ ords[ i ] ];
}
}
}
return uintptr_t{ };
}
c_interface_manager::c_interface_manager( ) {
auto teb = reinterpret_cast< PTEB >( __readfsdword( uintptr_t( &static_cast< NT_TIB* >( nullptr )->Self ) ) );
auto peb = teb->ProcessEnvironmentBlock;
auto root = &peb->Ldr->InMemoryOrderModuleList;
//iterate module list
for ( auto entry = root->Flink->Flink->Flink->Flink; entry != root; entry = entry->Flink ) {
PLDR_DATA_TABLE_ENTRY data_table;
HMODULE module_base;
uintptr_t create_interface_export;
uintptr_t create_interface_;
uintptr_t* list_iterator_ptr;
interface_iterator_t* list_iterator;
data_table = reinterpret_cast< PLDR_DATA_TABLE_ENTRY >( entry );
module_base = reinterpret_cast< HMODULE >( data_table->Reserved2[ 0 ] );
create_interface_export = find_createinterface( module_base );
if ( !create_interface_export || !is_createinterface_export( create_interface_export ) ) {
continue;
}
//find the createinterface function
create_interface_ = follow_createinterface_export( create_interface_export );
if ( !is_createinterface_fn( create_interface_ ) ) {
continue;
}
//find the list iterator
list_iterator_ptr = find_list_ptr( create_interface_ );
//iterate the interface list
for ( list_iterator = reinterpret_cast< interface_iterator_t* >(
list_iterator_ptr );
!!list_iterator;
list_iterator = list_iterator->m_next
) {
std::string name( list_iterator->m_name );
std::string module_name( util::unicode_to_ascii(
std::wstring( data_table->FullDllName.Buffer, data_table->FullDllName.Length ) ) );
uintptr_t ptr = static_cast< uintptr_t( *)( ) >( list_iterator->m_create_fn )( );
size_t version = [ & ]( ) {
std::string ret( name );
ret.erase( std::remove_if( ret.begin( ), ret.end( ),
[ & ]( int i ) { return !::isdigit( i ); }
), ret.end( ) );
return atoi( ret.c_str( ) );
}( );
m_interfaces.emplace_back( interface_data_t{ name, module_name, version, ptr } );
}
}
}
END_REGION
END_REGION
#endif
|