summaryrefslogtreecommitdiff
path: root/src/csgo/interface.h
blob: 62afb4acc79ebb27ed215c4af1fa312b15298576 (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
//|_   _   _.     _  ._  |_   _.  _ |
//| | (/_ (_| \/ (/_ | | | | (_| (_ |<

#pragma once
#include "../process.h"
#include "../util.h"
#include "../typedef.h"

struct IFACE_ENTRY {
  U32     ptr;
  STR<64> name;
  U32     module;
  STR<64> module_name;
};

struct IFACE_REG {
  void*       create_fn;
  const char* name;
  U32         next;
};

inline bool iface_is_createinterface_export( PROCESS32* proc, U32 exp ) {
  U8 buf[12];

  proc->read( exp, buf, 12 );

  return(
    buf[0] == 0x55 &&
    buf[4] == 0xe9 &&
    buf[9] == 0xcc &&
    buf[10] == 0xcc
  );
}

inline bool iface_is_createinterface( PROCESS32* proc, U32 fn ) {
  U8 buf[12];

  proc->read( fn, buf, 12 );

  return (
    buf[0] == 0x55 &&
    buf[4] == 0x8b &&
    buf[10] == 0x57
  );
}

inline U32 iface_follow_createinterface( PROCESS32* proc, U32 exp ) {
  U32 jmp = exp + 0x4;
  U32 rel = proc->read<U32>( jmp + 0x1 );

  return jmp + rel + 0x5;
}

inline U32 iface_get_list( PROCESS32* proc, U32 exp ) {
  return proc->read<U32>( proc->read<U32>( exp + 0x6 ) );
}

static VECTOR< IFACE_ENTRY > srceng_get_interfaces( PROCESS32* proc ) {
  VECTOR< MODULE_EXPORT64 > exports;
  VECTOR< MODULE_ENTRY >    modules;
  VECTOR< IFACE_ENTRY >     ifaces;
  MODULE_EXPORT64*          create_interface_export;
  U32                       create_interface;

  modules = proc->dump_modules32();
  for( auto& module : modules ) {
    create_interface_export = 0;
    exports = module_get_exports( (U32)module.base, proc->get_base() );

    for( auto& it : exports ) {
      if( fnv1a( it.name ) == "CreateInterface"fnv &&
        iface_is_createinterface_export( proc, (U32)it.base )
      ) {
        create_interface_export = &it;
        break;
      }
    }

    if( !create_interface_export )
      continue;

    create_interface = iface_follow_createinterface( proc, (U32)create_interface_export->base );
    if( !create_interface || !iface_is_createinterface( proc, create_interface ) )
      continue;

    U32 list_ptr  = iface_get_list( proc, create_interface );
    if( !list_ptr )
      continue;
    
    IFACE_REG reg = proc->read<IFACE_REG>( list_ptr );
    STR<64> name{};
    do {
      memset( name.data, 0, 64 );
      proc->read( (U32)reg.name, name.data, 64 );
      name.data[63] = 0;

      IFACE_ENTRY e;
      e.module = (U32)module.base;
      e.module_name = module.name;
      e.name = name;
      e.ptr = proc->read<U32>( (U32)(reg.create_fn) + 0x1 );
    
      ifaces.push_back( e );

      reg = proc->read<IFACE_REG>( reg.next );
    } while( list_ptr != reg.next && reg.next );
  }

  return ifaces;
}