summaryrefslogtreecommitdiff
path: root/src/cs2/iface.h
blob: 61cd91ced92239fed44c71aaedfd199da3ddd316 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#pragma once

#include "../process64.h"

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

struct IFACE_REG {
  U64 create_fn;
  U64 name;
  U64 next;
};

inline bool iface_is_createinterface_export( PROCESS64* p, U64 exp ) {
  U8 data[64];
  p->read( exp, data, 64 );

  // mov r9, cs:iface_list
  // mov r10, rdx
  return
    data[0] == 0x4c && data[1] == 0x8b && data[2] == 0x0d &&
    data[7] == 0x4c && data[8] == 0x8b && data[9] == 0xd2;
}

inline U64 iface_get_list( PROCESS64* p, U64 createiface ) {
  U8 data[64];
  p->read( createiface, data, 64 );

  U32 off = *(U32*)&data[3];
  U64 list = createiface + off + 7;

  return p->read<U64>( list );
}

inline U64 iface_get_address( PROCESS64* p, U64 create_fn ) {
  U8 data[64];
  p->read( create_fn, data, 64 );

  U32 off = *(U32*)&data[3];
  U64 addr = create_fn + off + 7;

  return addr;
}

inline U64 iface_get_createinterface( PROCESS64* p, U64 module ) {
  VECTOR<MODULE_EXPORT64> exports = module_get_exports64( module, p->get_base() );
  for( auto& it : exports ) {
    if( fnv1a( it.name ) == "CreateInterface"fnv )
      return it.base;
  }

  return {};
}

inline VECTOR<IFACE_ENTRY> iface_dump_module( PROCESS64* p, MODULE_ENTRY module ) {
  VECTOR<IFACE_ENTRY> entries;
  U64 createiface, list, head, prev;
  IFACE_REG reg;

  createiface = iface_get_createinterface( p, module.base );
  if( !createiface )
    return entries;

  if( !iface_is_createinterface_export( p, createiface ) )
    return entries;

  list = iface_get_list( p, createiface );
  if( !list )
    return entries;

  head = list;
  prev = 0;
  p->read( head, &reg, sizeof( IFACE_REG ) );

  for( ;; ) {
    IFACE_ENTRY entry;
    p->read( reg.name, entry.name.data, 64 );

    U64 ptr = iface_get_address( p, reg.create_fn );
    
    entry.ptr = ptr;
    entry.module = module.base;
    entry.module_name = module.name;
    entries.push_back( entry );

    if( reg.next == head || reg.next == prev || !reg.next )
      break;

    prev = reg.next;
    p->read( reg.next, &reg, sizeof( IFACE_REG ) );
  }

  return entries;
}

inline VECTOR<IFACE_ENTRY> iface_get_all( PROCESS64* p ) {
  VECTOR<IFACE_ENTRY> entries;

  VECTOR<MODULE_ENTRY> modules = p->dump_modules();
  for( auto& it : modules ) {
    VECTOR<IFACE_ENTRY> module_entries = iface_dump_module( p, it );
    entries.insert( entries.end(), module_entries.begin(), module_entries.end() );
  }

  return entries;
}
  
inline void iface_dump_to_file( PROCESS64* p ) {
  VECTOR<IFACE_ENTRY> entries = iface_get_all( p );

  static STR<9999999> output;
  memset( output, 0, sizeof( output.data ) );

  for( auto& it : entries ) {
    U64 off = it.ptr - it.module;
    
    sprintf( output, "%siface: %s @%s+0x%llx [0x%llx]\n", output.data, it.name.data, it.module_name.data, off, it.ptr );
  }

  u_write_to_file( output.data, "interfaces.txt" );
}