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
|
// Copyright 2020-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#ifndef MUMBLE_MUMBLE_PLUGIN_SE_COMMON_
#define MUMBLE_MUMBLE_PLUGIN_SE_COMMON_
typedef std::map< std::string, procptr_t > Interfaces;
struct InterfaceReg {
uint32_t createFunction;
uint32_t name;
uint32_t next;
};
static Interfaces getInterfaces(const procptr_t module) {
Interfaces interfaces;
// s_pInterfaceRegs is exported on Linux
auto s_pInterfaceRegs = proc->exportedSymbol("s_pInterfaceRegs", module);
if (!s_pInterfaceRegs) {
const auto CreateInterface = proc->exportedSymbol("CreateInterface", module);
if (CreateInterface == 0) {
return interfaces;
}
bool jmpOnly;
if (proc->peek< uint8_t >(CreateInterface) == 0xE9) {
// Left 4 Dead:
// E9 ?? ?? ?? ?? jmp CreateInterface_0
jmpOnly = true;
} else {
// Other games:
// 55 push ebp
// 8B EC mov ebp, esp
// 5D pop ebp
// E9 ?? ?? ?? ?? jmp CreateInterfaceInternal
jmpOnly = false;
}
const auto jmpTarget = proc->peek< int32_t >(CreateInterface + (jmpOnly ? 1 : 5));
const auto jmpInstructionEnd = CreateInterface + (jmpOnly ? 5 : 9);
const auto CreateInterfaceInternal = jmpInstructionEnd + jmpTarget;
// Left 4 Dead:
// 56 push esi
// 8B 35 ?? ?? ?? ?? mov esi, s_pInterfaceRegs
// 85 F6 test esi, esi
// 57 push edi
//
// Other games:
// 55 push ebp
// 8B EC mov ebp, esp
// 56 push esi
// 8B 35 ?? ?? ?? ?? mov esi, s_pInterfaceRegs
if (proc->peek< uint16_t >(CreateInterfaceInternal + (jmpOnly ? 1 : 4)) != 0x358B) {
return interfaces;
}
s_pInterfaceRegs = proc->peek< uint32_t >(CreateInterfaceInternal + (jmpOnly ? 3 : 6));
}
auto iface = proc->peek< InterfaceReg >(proc->peekPtr(s_pInterfaceRegs));
do {
const auto name = proc->peekString(iface.name);
const auto address = proc->peek< uint32_t >(iface.createFunction + (isWin32 ? 1 : 2));
interfaces.insert(Interfaces::value_type(name, address));
} while (iface.next && proc->peek(iface.next, iface));
return interfaces;
}
static procptr_t getInterfaceAddress(const std::string &name, const Interfaces &interfaces) {
const auto iface = interfaces.find(name);
if (iface == interfaces.end()) {
return 0;
}
return iface->second;
}
#endif
|