Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidebeatrici <davidebeatrici@gmail.com>2016-09-12 22:47:28 +0300
committerdavidebeatrici <davidebeatrici@gmail.com>2016-09-12 22:47:28 +0300
commit04dacb11cf0a88948083960cce911ba7ce42f11d (patch)
tree487930cebebdfeb547e9a6289f2da327ba6a5936 /plugins/wow
parentf064a8d03653b631dd55333f895ce164a2c908d8 (diff)
plugins/wow: Total revamp and support for the x64 executable.
Diffstat (limited to 'plugins/wow')
-rw-r--r--plugins/wow/wow.cpp438
1 files changed, 122 insertions, 316 deletions
diff --git a/plugins/wow/wow.cpp b/plugins/wow/wow.cpp
index 11c3bcfa4..1ef7a2708 100644
--- a/plugins/wow/wow.cpp
+++ b/plugins/wow/wow.cpp
@@ -3,355 +3,161 @@
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
-#include <stdint.h>
+#include "../mumble_plugin_win32_32bit.h" // Include standard plugin header.
+#include "../mumble_plugin_utils.h" // Include plugin header for special functions, like "escape".
-#include "../mumble_plugin_win32_32bit.h"
-
-struct guid {
- uint64_t first;
- uint64_t second;
-};
-
-procptr32_t p_playerBase;
-guid g_playerGUID;
-
-/*
- * To update visit http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing
- * and look for a thread called [WoW][TheVersion] Info Dump Thread.
- *
- * Where possible, I have included in the comments the different names some posters
- * call each value, to ease in upgrading. "[_]" means the value name may or may not
- * have an underscore in it depending on who's posting the offset.
- */
-static procptr32_t ptr_ClientConnection=0xFF0248; // ClientConnection or CurMgrPointer
-static procptr32_t off_ObjectManager=0x62C; // objectManager or CurMgrOffset
-static procptr32_t ptr_WorldFrame=0xEAF1F0; // Camera[_]Pointer, CameraStruct
-static procptr32_t off_CameraOffset=0x7610; // Camera[_]Offset
-static procptr32_t ptr_PlayerName=0xFF0288; // PlayerName
-static procptr32_t ptr_RealmName=0xFF0436; // RealmName
-
-static procptr32_t off_localGUID = 0xF8; // localGUID
-static procptr32_t off_firstObject = 0xD8; // firstObject
-static procptr32_t off_nextObject = 0x3C; // nextObject
-static procptr32_t off_objectGUID = 0x28;
-
-static procptr32_t off_unitpos = 0xAC0; // UnitOrigin
-static procptr32_t off_unitheading = 0xAD0; // UnitAngle
-static procptr32_t off_unitpitch = 0xAE0; // Not tracked, but probably off_unitheading + 0x10
-
-int getCStringN(procptr32_t ptr, char *buffer, size_t buffersize) {
- BOOL ok = peekProc(ptr, buffer, buffersize);
-
- /* safety net, just in case we didn't get a string back at all */
- buffer[buffersize-1] = '\0';
-
- if (ok) {
- return static_cast<int>(strlen(buffer));
- } else {
- return 0;
+static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
+ for (int i=0;i<3;i++) {
+ avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;
}
-}
-
-int getString(procptr32_t ptr, std::string &buffer) {
- char buf[1024];
- int bufLength;
-
- bufLength = getCStringN(ptr, buf, sizeof(buf));
- buffer = buf;
- return bufLength;
-}
-
-int getWString(procptr32_t ptr, std::wstring &buffer) {
- char buf[1024];
- int bufLength;
- wchar_t wbuf[1024];
- int wbufLength;
-
- bufLength = getCStringN(ptr, buf, sizeof(buf));
- wbufLength = MultiByteToWideChar(CP_UTF8, 0,
- buf, bufLength,
- wbuf, 1024);
- buffer.assign(wbuf, wbufLength);
-
- return wbufLength;
-}
+ // To update visit http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing
+ // and look for a thread called "[WoW] [Version] Release Info Dump Thread".
+ // http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/578228-wow-7-0-3-22522-release-info-dump-thread-post3584506.html#post3584506
+
+ // Avatar pointer
+ procptr32_t avatar_offset = peekProc<procptr32_t>(pModule + 0xDE545C); // "LocalPlayer" in the thread.
+ if (!avatar_offset) return false;
+
+ // Camera pointer
+ procptr32_t camera_base = peekProc<procptr32_t>(pModule + 0xEB9F1C); // "CameraStruct" in the thread.
+ if (!camera_base) return false;
+ procptr32_t camera_offset = peekProc<procptr32_t>(camera_base + 0x3264); // "CameraOffset" in the thread.
+ if (!camera_offset) return false;
+
+ // Realm pointer
+ procptr32_t realm_offset = peekProc<procptr32_t>(pModule + 0xF3AD7C); // Not available in the thread.
+ if (!realm_offset) return false;
+
+ // Memory addresses
+ procptr32_t state_address = 0xE5BB19; // "GameState" in the thread.
+ procptr32_t avatar_pos_address = 0xAF8; // "UnitOrigin" in the thread.
+ procptr32_t camera_pos_address = 0x08; // "CameraOrigin" in the thread.
+ procptr32_t camera_front_address = 0x14; // "CameraMatrix" in the thread.
+ procptr32_t camera_top_address = 0x2C; // "CameraMatrix" + 0x18.
+ procptr32_t avatar_heading_address = 0xB08; // "UnitAngle" in the thread.
+ procptr32_t realm_address = 0x384; // Not available in the thread.
+ procptr32_t player_address = 0xF3B088; // Not available in the thread.
+
+ // Boolean value to check if game addresses retrieval is successful
+ bool ok;
+ // Create containers to stuff our raw data into, so we can convert it to Mumble's coordinate system
+ float avatar_pos_corrector[3], camera_pos_corrector[3], avatar_heading, camera_front_corrector[3], camera_top_corrector[3];
+ // Char values for extra features
+ char state, player[50], realm[50];
+
+ // Peekproc and assign game addresses to our containers, so we can retrieve positional data
+ ok = peekProc(pModule + state_address, &state, 1) && // Magical state value: 1 when in-game, 0 when not.
+ peekProc(avatar_offset + avatar_pos_address, avatar_pos_corrector, 12) && // Avatar Position values (Z, -X and Y).
+ peekProc(camera_offset + camera_pos_address, camera_pos_corrector, 12) && // Camera Position values (Z, -X and Y).
+ peekProc(avatar_offset + avatar_heading_address, avatar_heading) && // Avatar heading.
+ peekProc(camera_offset + camera_front_address, camera_front_corrector, 12) && // Camera Front Vector values (Z, -X and Y).
+ peekProc(camera_offset + camera_top_address, camera_top_corrector, 12) && // Camera Top Vector values (Z, -X and Y).
+ peekProc(realm_offset + realm_address, realm) && // Realm name.
+ peekProc(pModule + player_address, player); // Player nickname.
+
+ // This prevents the plugin from linking to the game in case something goes wrong during values retrieval from memory addresses.
+ if (! ok)
+ return false;
-#ifdef _DEBUG
-void getDebug16(procptr32_t ptr) {
- unsigned char buf[16];
- BOOL ok = peekProc(ptr, &buf, sizeof(buf));
- if (ok) {
- printf("%08x: %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",
- ptr,
- buf[0], buf[1], buf[2], buf[3],
- buf[4], buf[5], buf[6], buf[7],
- buf[8], buf[9], buf[10], buf[11],
- buf[12], buf[13], buf[14], buf[15]
- );
- }
-}
+ // State
+ if (state != 1) { // If not in-game
+ context.clear(); // Clear context
+ identity.clear(); // Clear identity
+ // Set vectors values to 0.
+ for (int i=0;i<3;i++)
+ avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;
-void stringDebug(std::string &theString) {
- std::cout << "String length=" << theString.length() << " content=\"" << theString << "\" debug=";
- for (size_t i=0; i<theString.length(); i++) {
- if (i>0) {
- std::cout << " ";
- }
- std::cout << (unsigned int)theString[i];
- }
- std::cout << std::endl;
-}
-#endif
-
-procptr32_t getPlayerBase() {
- procptr32_t gClientConnection;
- procptr32_t sCurMgr;
- procptr32_t curObj;
- guid playerGUID;
- procptr32_t playerBase;
-
- procptr32_t nextObj;
- guid GUID;
-
- playerBase=0;
-
- gClientConnection=peekProc<procptr32_t>(pModule + ptr_ClientConnection);
- sCurMgr=peekProc<procptr32_t>(gClientConnection + off_ObjectManager);
- if (sCurMgr != 0) {
- playerGUID.first=peekProc<uint64_t>(sCurMgr+off_localGUID);
- playerGUID.second=peekProc<uint64_t>(sCurMgr+off_localGUID + 0x8);
- if (playerGUID.second != 0) {
- g_playerGUID.first = playerGUID.first;
- g_playerGUID.second = playerGUID.second;
-
- curObj=peekProc<procptr32_t>(sCurMgr+off_firstObject); // firstObject
- while (curObj != 0) {
- nextObj=peekProc<procptr32_t>(curObj + off_nextObject); // nextObject
- GUID.first=peekProc<uint64_t>(curObj + off_objectGUID);
- GUID.second=peekProc<uint64_t>(curObj + off_objectGUID + 0x8);
- if (playerGUID.first == GUID.first && playerGUID.second == GUID.second) {
- playerBase = curObj;
- break;
- } else if (curObj == nextObj) {
- break;
- } else {
- curObj = nextObj;
- }
- }
- }
+ return true; // This tells Mumble to ignore all vectors.
}
- return playerBase;
-}
-
-void getPlayerName(std::wstring &identity) {
- std::wstring playerName, realmName;
-
- getWString(pModule + ptr_PlayerName, playerName);
- getWString(pModule + ptr_RealmName, realmName);
-
- identity = playerName + L"-" + realmName;
- //printf("Name: %ls\n", identity.data());
- return;
-}
-
-void getCamera(float camera_pos[3], float camera_front[3], float camera_top[3]) {
- procptr32_t ptr1, ptr2;
- float buf[4][3];
-
- ptr1 = peekProc<procptr32_t>(pModule + ptr_WorldFrame);
- ptr2 = peekProc<procptr32_t>(ptr1+off_CameraOffset);
-
- peekProc(ptr2+0x08, buf, sizeof(buf));
-
- /* camera postition */
- camera_pos[0] = -buf[0][1];
- camera_pos[1] = buf[0][2];
- camera_pos[2] = buf[0][0];
-
- /* camera front vector */
- camera_front[0] = -buf[1][1];
- camera_front[1] = buf[1][2];
- camera_front[2] = buf[1][0];
-
- /* camera right vector */
-#if 0 /* gets calculated in mumble client */
- camera_right[0] = -buf[2][1];
- camera_right[1] = buf[2][2];
- camera_right[2] = buf[2][0];
-#endif
-
- /* camera top vector */
- camera_top[0] = -buf[3][1];
- camera_top[1] = buf[3][2];
- camera_top[2] = buf[3][0];
-}
-
-typedef class WowData {
- std::wstring nameAvatar;
- bool nameAvatarValid;
-
- guid playerGUID;
- procptr32_t pointerPlayerObject;
-
- public:
- WowData::WowData() {
- refresh();
- }
-
- void WowData::updateAvatarName() {
- getPlayerName(nameAvatar);
- if (!nameAvatar.empty()) {
- nameAvatarValid = true;
- } else {
- nameAvatarValid = false;
- }
- }
-
- std::wstring getNameAvatar() {
- if (!nameAvatarValid) {
- updateAvatarName();
- }
-
- return nameAvatar;
- }
-
- void refresh() {
- nameAvatarValid = false;
- }
-} WowData_t;
-
-WowData_t wow;
+ // Begin context
+ std::ostringstream ocontext;
-static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
- /* clear position */
- for (int i=0; i<3; i++) {
- avatar_pos[i]=avatar_front[i]=avatar_top[i]=camera_pos[i]=camera_front[i]=camera_top[i]=0.0;
+ // Realm
+ realm[sizeof(realm)-1] = 0; // NUL terminate queried C strings. We do this to ensure the strings from the game are NUL terminated. They should be already, but we can't take any chances.
+ escape(realm);
+ if (strcmp(realm, "") != 0) { // Set Realm string only if not empty
+ ocontext << " {\"Realm\": \"" << realm << "\"}"; // Set context with Realm's name
}
- /* are we still looking at the right object? */
- guid peekGUID, tempGUID;
- peekGUID.first=peekProc<uint64_t>(p_playerBase+0x30);
- peekGUID.second=peekProc<uint64_t>(p_playerBase+0x30+0x8);
- if (g_playerGUID.first != peekGUID.first || g_playerGUID.second != peekGUID.second) {
- /* no? Try to resynch to the new address. Happens when walking through portals quickly (aka no or short loading screen) */
- tempGUID.first = g_playerGUID.first;
- tempGUID.second = g_playerGUID.second;
- p_playerBase=getPlayerBase();
- if (tempGUID.first != g_playerGUID.first || tempGUID.first != g_playerGUID.first) {
- /* GUID of actor changed, likely a character and/or realm change */
- wow.refresh();
- }
- peekGUID.first=peekProc<uint64_t>(p_playerBase+0x28);
- peekGUID.second=peekProc<uint64_t>(p_playerBase+0x28+0x8);
- if (g_playerGUID.first != peekGUID.first || g_playerGUID.second != peekGUID.second) {
- /* no? we are still getting the expected GUID for our avatar, but we don't have it's current position */
- return true;
- }
- }
+ context = ocontext.str();
+ // End context
- context.clear();
- std::wstringstream identityStream;
- identityStream << wow.getNameAvatar();
- identity = identityStream.str();
-
- BOOL ok = true;
-
- // Wow stores as
- // North/South (+ North)
- // East/West (+ West)
- // Up/Down (+Up)
- // ... which isn't a right-hand coordinate system.
-
- float pos[3];
- ok = ok && peekProc(p_playerBase + off_unitpos, pos, sizeof(float)*3);
- if (! ok) {
- if (g_playerGUID.second == 0xffffffffffffffff) {
- return false;
- } else if (g_playerGUID.second == 0) {
- return true;
- } else {
- /* FIXME need a better way to mark PlayerBase invalid */
- g_playerGUID.first=0;
- g_playerGUID.second=0;
- return true; /* we got a good reference for an avatar, but no good position */
- }
+ // Begin identity
+ std::wostringstream oidentity;
+ oidentity << "{";
+
+ // Player
+ player[sizeof(player)-1] = 0; // NUL terminate queried C strings. We do this to ensure the strings from the game are NUL terminated. They should be already, but we can't take any chances.
+ escape(player);
+ if (strcmp(player, "") != 0) {
+ oidentity << std::endl;
+ oidentity << "\"Player\": \"" << player << "\""; // Set player nickname in identity.
+ } else {
+ oidentity << std::endl << "\"Player\": null";
}
- /* convert wow -> right hand coordinate system */
- avatar_pos[0] = -pos[1];
- avatar_pos[1] = pos[2];
- avatar_pos[2] = pos[0];
+ oidentity << std::endl << "}";
+ identity = oidentity.str();
+ // End identity
- float heading=0.0;
- ok = ok && peekProc(p_playerBase + off_unitheading, &heading, sizeof(heading));
- if (! ok)
- return false;
+ /*
+ Mumble | Game
+ X | Z
+ Y | -X
+ Z | Y
+ */
+ avatar_pos[0] = -avatar_pos_corrector[1];
+ avatar_pos[1] = avatar_pos_corrector[2];
+ avatar_pos[2] = avatar_pos_corrector[0];
- float pitch=0.0;
- ok = ok && peekProc(p_playerBase + off_unitpitch, &pitch, sizeof(pitch));
- if (! ok)
- return false;
+ camera_pos[0] = -camera_pos_corrector[1];
+ camera_pos[1] = camera_pos_corrector[2];
+ camera_pos[2] = camera_pos_corrector[0];
- /* TODO use yaw (heading) and pitch angles */
- /* FIXME sin/cos (heading) is right from the numbers, but (-heading) is right from the sound position */
- avatar_front[0]=-sin(heading);
- avatar_front[1]=0.0;
- avatar_front[2]=cos(heading);
+ avatar_front[0] = -sin(avatar_heading);
+ avatar_front[1] = 0.0f;
+ avatar_front[2] = cos(avatar_heading);
- // Dummy top vector, can't tilt your head sideways in wow.
- avatar_top[0]= 0.0;
- avatar_top[1]= 1.0;
- avatar_top[2]= 0.0;
+ avatar_top[2] = -1; // Dummy top vector, you can't tilt your head sideways in WoW.
- getCamera(camera_pos, camera_front, camera_top);
+ camera_front[0] = -camera_front_corrector[1];
+ camera_front[1] = camera_front_corrector[2];
+ camera_front[2] = camera_front_corrector[0];
- if (! ok)
- return false;
+ camera_top[0] = -camera_top_corrector[1];
+ camera_top[1] = camera_top_corrector[2];
+ camera_top[2] = camera_top_corrector[0];
- //printf("P %f %f %f -- %f %f %f \n", avatar_pos[0], avatar_pos[1], avatar_pos[2], avatar_front[0], avatar_front[1], avatar_front[2]);
- //printf("C %f %f %f -- %f %f %f \n", camera_pos[0], camera_pos[1], camera_pos[2], camera_front[0], camera_front[1], camera_front[2]);
+ return true;
+}
- // is it a unit length vector?
- if (fabs((avatar_front[0]*avatar_front[0]+avatar_front[1]*avatar_front[1]+avatar_front[2]*avatar_front[2])-1.0)>0.5) {
- // printf("F %f %f %f\n", front[0], front[1], front[2]);
- return false;
- }
+static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
- // are we around 0/0/0
- if ((fabs(avatar_pos[0])<0.1) && (fabs(avatar_pos[1])<0.1) && (fabs(avatar_pos[2])<0.1)) {
- // printf("P %f %f %f\n", avatar_pos[0], avatar_pos[1], avatar_pos[2]);
+ if (! initialize(pids, L"Wow.exe")) { // Retrieve game executable's memory address
return false;
}
- return true;
-}
+ // Check if we can get meaningful data from it
+ float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
+ std::wstring sidentity;
+ std::string scontext;
-static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
- if (! initialize(pids, L"Wow.exe"))
+ if (fetch(apos, afront, atop, cpos, cfront, ctop, scontext, sidentity)) {
+ return true;
+ } else {
+ generic_unlock();
return false;
-
- p_playerBase=getPlayerBase();
- if (p_playerBase != 0) {
- float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
- std::string context;
- std::wstring identity;
- if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity))
- return true;
}
-
- generic_unlock();
- return false;
}
static const std::wstring longdesc() {
- return std::wstring(L"Supports World of Warcraft 32-bit 6.2.2 (20490), with identity support.");
+ return std::wstring(L"Supports World of Warcraft (x86) with context and identity support."); // Plugin long description
}
-static std::wstring description(L"World of Warcraft 32-bit 6.2.2 (20490)");
-
-static std::wstring shortname(L"World of Warcraft");
+static std::wstring description(L"World of Warcraft (x86) version 7.0.3.22566"); // Plugin short description
+static std::wstring shortname(L"World of Warcraft"); // Plugin short name
static int trylock1() {
return trylock(std::multimap<std::wstring, unsigned long long int>());