├── .gitignore
├── LICENSE
├── README.md
└── interface_factory
├── Project8.sln
└── Project8
├── Project8.vcxproj
├── Project8.vcxproj.filters
├── Source.cpp
├── factory.cpp
├── factory.hpp
├── util.hpp
└── x86.hpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # interface-factory
2 | walks through modules and interfaces in the source engine
3 |
--------------------------------------------------------------------------------
/interface_factory/Project8.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.15
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project8", "Project8\Project8.vcxproj", "{103F0F2B-9DFD-4E28-9693-BAC1B6A83306}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Debug|x64.ActiveCfg = Debug|x64
17 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Debug|x64.Build.0 = Debug|x64
18 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Debug|x86.ActiveCfg = Debug|Win32
19 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Debug|x86.Build.0 = Debug|Win32
20 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Release|x64.ActiveCfg = Release|x64
21 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Release|x64.Build.0 = Release|x64
22 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Release|x86.ActiveCfg = Release|Win32
23 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {A47D7E12-B892-4555-8D21-BEC3CB980B61}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/interface_factory/Project8/Project8.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 15.0
23 | {103F0F2B-9DFD-4E28-9693-BAC1B6A83306}
24 | Project8
25 | 10.0.15063.0
26 |
27 |
28 |
29 | DynamicLibrary
30 | true
31 | v141
32 | MultiByte
33 |
34 |
35 | DynamicLibrary
36 | false
37 | v141
38 | true
39 | MultiByte
40 |
41 |
42 | DynamicLibrary
43 | true
44 | v141
45 | MultiByte
46 |
47 |
48 | DynamicLibrary
49 | false
50 | v141
51 | true
52 | MultiByte
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Level3
76 | Disabled
77 | true
78 |
79 |
80 |
81 |
82 | Level3
83 | Disabled
84 | true
85 |
86 |
87 |
88 |
89 | Level3
90 | MaxSpeed
91 | true
92 | true
93 | true
94 |
95 |
96 | true
97 | true
98 |
99 |
100 |
101 |
102 | Level3
103 | MaxSpeed
104 | true
105 | true
106 | true
107 |
108 |
109 | true
110 | true
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/interface_factory/Project8/Project8.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 |
26 |
27 | Source Files
28 |
29 |
30 | Source Files
31 |
32 |
33 | Source Files
34 |
35 |
36 |
--------------------------------------------------------------------------------
/interface_factory/Project8/Source.cpp:
--------------------------------------------------------------------------------
1 | #include "factory.hpp"
2 |
3 | bool __stdcall DllMain( HINSTANCE instance, ulong_t reason, void* reserved ) {
4 | switch ( reason ) {
5 | case DLL_PROCESS_ATTACH:
6 | DisableThreadLibraryCalls( instance );
7 | g_factory.dump_interface_list( );
8 |
9 | return true;
10 | break;
11 |
12 | default:
13 | return true;
14 | break;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/interface_factory/Project8/factory.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "factory.hpp"
4 |
5 | NAMESPACE_REGION( interface_factory )
6 |
7 | //iterate all exports inside of a module and find createinterface
8 | uintptr_t c_interface_manager::find_createinterface( void* module_ ) {
9 | IMAGE_DOS_HEADER* dos_header;
10 | IMAGE_NT_HEADERS* nt_headers;
11 | uintptr_t export_address;
12 | IMAGE_EXPORT_DIRECTORY* export_dir;
13 | const char* export_name;
14 | uintptr_t* names;
15 | uintptr_t* funcs;
16 | uint16_t* ords;
17 |
18 | dos_header = reinterpret_cast< decltype( dos_header ) >( uintptr_t( module_ ) );
19 | nt_headers = reinterpret_cast< decltype( nt_headers ) >( uintptr_t( module_ ) + dos_header->e_lfanew );
20 |
21 | export_address = nt_headers->OptionalHeader.DataDirectory[ 0 ].VirtualAddress;
22 | export_dir = reinterpret_cast< decltype( export_dir ) >( uintptr_t( module_ ) + export_address );
23 |
24 | if ( !export_dir->NumberOfFunctions )
25 | return uintptr_t{ };
26 |
27 | names = reinterpret_cast< uintptr_t* >( uintptr_t( module_ ) + export_dir->AddressOfNames );
28 | funcs = reinterpret_cast< uintptr_t* >( uintptr_t( module_ ) + export_dir->AddressOfFunctions );
29 |
30 | ords = reinterpret_cast< uint16_t* >( uintptr_t( module_ ) + export_dir->AddressOfNameOrdinals );
31 |
32 | if ( names && funcs && ords ) {
33 | for ( size_t i{ }; i < export_dir->NumberOfNames; ++i ) {
34 | export_name = reinterpret_cast< const char* >( uintptr_t( module_ ) + names[ i ] );
35 | if ( !strcmp( export_name, "CreateInterface" ) ) {
36 | return uintptr_t( module_ ) + funcs[ ords[ i ] ];
37 | }
38 | }
39 | }
40 |
41 | return uintptr_t{ };
42 | }
43 |
44 | c_interface_manager::c_interface_manager( ) {
45 | auto teb = reinterpret_cast< PTEB >( __readfsdword( uintptr_t( &static_cast< NT_TIB* >( nullptr )->Self ) ) );
46 | auto peb = teb->ProcessEnvironmentBlock;
47 |
48 | auto root = &peb->Ldr->InMemoryOrderModuleList;
49 | //iterate module list
50 | for ( auto entry = root->Flink->Flink->Flink->Flink; entry != root; entry = entry->Flink ) {
51 | PLDR_DATA_TABLE_ENTRY data_table;
52 | HMODULE module_base;
53 | uintptr_t create_interface_export;
54 | uintptr_t create_interface_;
55 | uintptr_t* list_iterator_ptr;
56 | interface_iterator_t* list_iterator;
57 |
58 | data_table = reinterpret_cast< PLDR_DATA_TABLE_ENTRY >( entry );
59 | module_base = reinterpret_cast< HMODULE >( data_table->Reserved2[ 0 ] );
60 | create_interface_export = find_createinterface( module_base );
61 |
62 | if ( !create_interface_export || !is_createinterface_export( create_interface_export ) ) {
63 | continue;
64 | }
65 |
66 | //find the createinterface function
67 | create_interface_ = follow_createinterface_export( create_interface_export );
68 | if ( !is_createinterface_fn( create_interface_ ) ) {
69 | continue;
70 | }
71 |
72 | //find the list iterator
73 | list_iterator_ptr = find_list_ptr( create_interface_ );
74 |
75 | //iterate the interface list
76 | for ( list_iterator = reinterpret_cast< interface_iterator_t* >(
77 | list_iterator_ptr );
78 | !!list_iterator;
79 | list_iterator = list_iterator->m_next
80 | ) {
81 | std::string name( list_iterator->m_name );
82 | std::string module_name( util::unicode_to_ascii(
83 | std::wstring( data_table->FullDllName.Buffer, data_table->FullDllName.Length ) ) );
84 |
85 | uintptr_t ptr = static_cast< uintptr_t( *)( ) >( list_iterator->m_create_fn )( );
86 |
87 | size_t version = [ & ]( ) {
88 | std::string ret( name );
89 | ret.erase( std::remove_if( ret.begin( ), ret.end( ),
90 | [ & ]( int i ) { return !::isdigit( i ); }
91 | ), ret.end( ) );
92 | return atoi( ret.c_str( ) );
93 | }( );
94 |
95 | m_interfaces.emplace_back( interface_data_t{ name, module_name, version, ptr } );
96 | }
97 | }
98 | }
99 |
100 | END_REGION
101 | interface_factory::c_interface_manager g_factory;
102 |
--------------------------------------------------------------------------------
/interface_factory/Project8/factory.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "util.hpp"
7 | #include "x86.hpp"
8 |
9 | NAMESPACE_REGION( interface_factory )
10 | struct interface_iterator_t {
11 | void* m_create_fn;
12 | char* m_name;
13 |
14 | interface_iterator_t* m_next;
15 | };
16 |
17 | inline auto follow_createinterface_export( uintptr_t export_ ) {
18 | /*
19 | .text:006F5F00 CreateInterface proc near
20 | .text:006F5F00 push ebp
21 | .text:006F5F01 mov ebp, esp
22 | .text:006F5F03 pop ebp
23 | .text:006F5F04 jmp sub_6F5E90
24 | */
25 | uintptr_t jmp = export_ + 0x4;
26 | uintptr_t jmp_target = jmp + *( uintptr_t* ) ( jmp + 0x1 ) + 0x5;
27 |
28 | return jmp_target;
29 | }
30 |
31 | inline auto find_list_ptr( uintptr_t createinterface ) {
32 | /*
33 | .text:006F5E90 push ebp
34 | .text:006F5E91 mov ebp, esp
35 | .text:006F5E93 push esi
36 | .text:006F5E94 mov esi, dword_2EEFDE4
37 | .text:006F5E9A push edi
38 | */
39 | auto iterator_ptr = **( uintptr_t*** ) ( createinterface + 0x6 );
40 |
41 | return iterator_ptr;
42 | }
43 |
44 | inline bool is_createinterface_export( uintptr_t export_ ) {
45 | return ( *( uint8_t* ) ( export_ ) == x86::encode_push_reg( x86::reg::ebp )
46 | && *( uint8_t* ) ( export_ + 4 ) == 0xe9
47 | && *( uint8_t* ) ( export_ + 9 ) == 0xcc
48 | && *( uint8_t* ) ( export_ + 10 ) == 0xcc );
49 | }
50 |
51 | inline bool is_createinterface_fn( uintptr_t fn_ ) {
52 | return ( *( uint8_t* ) ( fn_ ) == x86::encode_push_reg( x86::reg::ebp )
53 | && *( uint8_t* ) ( fn_ + 4 ) == 0x8b
54 | && *( uint8_t* ) ( fn_ + 10 ) == x86::encode_push_reg( x86::reg::edi ) );
55 | }
56 |
57 | class c_interface_manager {
58 | public:
59 | struct interface_data_t {
60 | std::string m_name;
61 | std::string m_module;
62 | size_t m_version;
63 | uintptr_t m_ptr;
64 |
65 | template < typename t > __forceinline t get( ) {
66 | return reinterpret_cast< t >( m_ptr );
67 | }
68 | };
69 |
70 | c_interface_manager( );
71 |
72 | //iterate the interface list to find our desired version
73 | template < typename t = void* >
74 | t find_interface( const std::string& module_, std::string name ) {
75 | //avoid finding interfaces with matching names
76 | if ( !::isdigit( name[ name.length() ] ) )
77 | name += "0";
78 |
79 | for ( auto& it : m_interfaces ) {
80 | if ( !it.m_module.compare( module_ )
81 | && !it.m_name.compare( name ) ) {
82 | printf( "%s version %u found in %s at 0x%08x\n",
83 | it.m_name.c_str(),
84 | it.m_version,
85 | it.m_module.c_str( ),
86 | it.m_ptr );
87 |
88 | return it.get< t >( );
89 | }
90 | }
91 |
92 | return t{ };
93 | }
94 |
95 | template < typename t = void* >
96 | t find_interface( std::string name ) {
97 | //avoid finding interfaces with matching names
98 | if ( !::isdigit( name[ name.length( ) ] ) )
99 | name += "0";
100 |
101 | for ( auto& it : m_interfaces ) {
102 | if ( strstr( it.m_name.c_str( ), name.c_str( ) ) ) {
103 | printf( "%s version %u found in %s at 0x%08x\n",
104 | it.m_name.c_str(),
105 | it.m_version,
106 | it.m_module.c_str( ),
107 | it.m_ptr );
108 |
109 | return it.get< t >( );
110 | }
111 | }
112 |
113 | return t{ };
114 | }
115 |
116 | void dump_interface_list( ) {
117 | std::fstream f( "dump.txt" );
118 | for ( auto& it : m_interfaces ) {
119 | char buf[ 200 ];
120 | sprintf_s( buf, 200, "%s version %u in %s at 0x%08x\n",
121 | it.m_name.c_str( ),
122 | it.m_version,
123 | it.m_module.c_str( ),
124 | it.m_ptr );
125 |
126 | f << buf;
127 | }
128 | }
129 |
130 | private:
131 | uintptr_t find_createinterface( void* module_ );
132 |
133 | std::vector< interface_data_t > m_interfaces;
134 | };
135 |
136 | END_REGION
137 |
138 | extern HMODULE g_dll;
139 | extern interface_factory::c_interface_manager g_factory;
140 |
--------------------------------------------------------------------------------
/interface_factory/Project8/util.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define NAMESPACE_REGION( x ) namespace x {
4 | #define END_REGION }
5 |
6 | //WEE WOO WEE WOO ITS THE DWORD POLICE
7 | using ulong_t = unsigned long;
8 | using uword_t = unsigned short;
9 |
10 | NAMESPACE_REGION( util )
11 |
12 | template < typename fn > __forceinline fn get_vfunc( void* classbase, int index ) {
13 | if ( !classbase ) return fn{ };
14 | return ( fn )( ( uintptr_t* )*( uintptr_t** )classbase )[ index ];
15 | }
16 |
17 | static __forceinline std::string unicode_to_ascii( const std::wstring& unicode ) {
18 | std::string ascii_str( unicode.begin( ), unicode.end( ) );
19 | return ascii_str;
20 | }
21 |
22 | static __forceinline std::wstring ascii_to_unicode( const std::string& ascii ) {
23 | std::wstring unicode_str( ascii.begin( ), ascii.end( ) );
24 | return unicode_str;
25 | }
26 |
27 | END_REGION
28 |
--------------------------------------------------------------------------------
/interface_factory/Project8/x86.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace x86
4 | {
5 | enum class reg : size_t {
6 | eax = 0,
7 | ecx,
8 | edx,
9 | ebx,
10 | esp,
11 | ebp,
12 | esi,
13 | edi
14 |
15 | /*
16 | x64:
17 | r8,
18 | r9,
19 | r10,
20 | r11,
21 | r12,
22 | r13,
23 | r14,
24 | r15*/
25 | };
26 |
27 | enum instruction : uint8_t {
28 | retn_imm16 = 0xc2,
29 | retn = 0xc3,
30 | fs = 0x64,
31 | //its big nigga season
32 | call = 0xff
33 | };
34 |
35 | __forceinline static uint32_t encode_mov_imm32( x86::reg dreg ) {
36 | return ( 0xb8 + ( size_t( dreg ) ) );
37 | }
38 |
39 | __forceinline static uint32_t encode_push_reg( x86::reg dreg ) {
40 | return ( 0x50 | ( ( size_t( dreg ) ) & 7 ) );
41 | }
42 |
43 | __forceinline static uint32_t encode_pop_reg( x86::reg dreg ) {
44 | return ( 0x58 | ( ( size_t( dreg ) ) & 7 ) );
45 | }
46 | };
47 |
--------------------------------------------------------------------------------