-
Member
LUA function sorcery
I apologize in advance if this is a retarded question, I'm a scrub that's trying to learn and I haven't slept much in the past few days as I've been obsessively working on this. In short, I'm playing with a few things and at the moment I'm able to successfully register new LUA functions and call them from in game. Cool. My next goal was to pass the entity/object list to the game the same way Firehack does, which is where I've been stuck for the last 2 days.
I can pass the entity addresses to the LUA stack and retrieve them in game, but I'm losing my shit completely trying to understand how can I pass these addresses as parameters to other functions (UnitName, UnitCanAttack etc.) the way Firehack does. Can't comprehend what type of wizardry is allowing this to take place.
-
Active Member
You will either have to detour the get unit by token function and parse object pointers or pass unit ids to lua instead of pointers
-
Member
What do you mean by unit IDs? I attempted entity IDs at entity+0x24 but that didn't seem to work.
-
Active Member
See this page for what I meant by unit id UnitId | WoWWiki | Fandom powered by Wikia.
You would have to figure out which unit id your object is, and not every object has an applicable unitid. If you were going to do it this way you might as well just use lua by itself. The best way to go about what you are trying to do is to hook GetGUIDFromToken.
-
Member
Much appreciated, I haven't quite gotten it working yet but I'm on the right track now.
-
I'm doing it in FH by hooking Script_GetGUIDFromToken, which is the function that resolves unit IDs into GUIDs, and making it so if a pointer is passed as a unit ID it'll be translated into the GUID.
-
Member
Makes perfect sense now. I was slamming my head against a wall last night trying to understand why it wasn't working. Thanks guys 
Update:
So working on this further, I've found the function and am attempting to hook it. I'm using DarthTon's Blackbone library but my game keeps crashing...
struct WoWGUID
{
uint8_t Data[16];
};
bool __fastcall myHookFunc(const char*& token, WoWGUID& guid, bool& b1, bool& b2)
{
MessageBoxA(NULL, token, "", MB_OK);
return true;
}
-------------------------------------------------------------------------------------
typedef bool(__fastcall *token2guid)(const char*, WoWGUID, bool, bool);
DWORD_PTR funcAddr = (wowBaseAddr + 0x650360);
token2guid TokenGUIDFunc = (token2guid)funcAddr;
blackbone:

etour<token2guid> det;
det.Hook(TokenGUIDFunc, &myHookFunc, blackbone::HookType::HWBP,blackbone::CallOrder::HookFirst, blackbone::ReturnMethod::UseOriginal);
First message box immediately after injection containing token "player", followed by a crash with an access violation error. Not quite sure what's throwing that. Would someone enlighten a polite scrub? :confused: I also attempted an inline hook just to see if it would work, but it doesn't seem to be writing anything to memory.
Last edited by uncledolan; 11-22-2016 at 06:27 AM.
-
Member
I'm a retard, I wasn't checking if token was null.
Edit: Can't seem to make hook function work properly. Added a messagebox to see if token was passing properly and it throws another access violation. I'm returning false every time to not throw the previous error.
bool __fastcall myHookFunc(const char*& token, WoWGUID& guid, bool& b1, bool& b2)
{
if (token)
{
MessageBoxA(NULL, token, "", MB_OK);
return false;
}
else
{
return false;
}
}

Edit 2: Unless I set CallOrder::NoOriginal I also still get the 0x000000000000 access violation. Ready to jump out of the window.
Last edited by uncledolan; 11-22-2016 at 10:00 AM.
-
Post Thanks / Like - 1 Thanks
Jadd (1 members gave Thanks to uncledolan for this useful post)
-
Contributor
Originally Posted by
l0l1dk
I'm doing it in FH by hooking Script_GetGUIDFromToken, which is the function that resolves unit IDs into GUIDs, and making it so if a pointer is passed as a unit ID it'll be translated into the GUID.
but when i passed guidptr to ClntObjMgrObjectPtr it always return 0 :\
guids still "two ulongs" struct?
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr ClntObjMgrObjectPtrDelegate(IntPtr guid, int unk);
private static ClntObjMgrObjectPtrDelegate ClntObjMgrObjectPtrHandler;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate bool GetGuidByKeywordDelegate(IntPtr token, int unk0, IntPtr guid, int unk1, int unk2);
private static GetGuidByKeywordDelegate GetGuidByKeywordHandler;
private static GetGuidByKeywordDelegate _GetGuidByKeyword;
GetGuidByKeywordHandler = Memory.Instance.RegisterDelegate<GetGuidByKeywordDelegate>(Main.Offsets["GetGuidByKeyword"]);
Memory.Instance.Detours.CreateAndApply(GetGuidByKeywordHandler, _GetGuidByKeyword = GetGuidByKeywordDetour, "GetGuidByKeywordDetour");
private static bool GetGuidByKeywordDetour(IntPtr token, int unk0, IntPtr guidptr, int unk1, int unk2)
{
string tokenstr = Marshal.PtrToStringAnsi(token);
if (tokenstr != null && tokenstr != string.Empty && tokenstr.All(Char.IsDigit))
{
if (!ObjectManager.IsInGame) return false;
Int32 ptr = 0;
Int32.TryParse(tokenstr, out ptr);
if (ptr > 0)
{
WoWGUID retguid = new WoWGUID(new IntPtr(ptr));
if (retguid == WoWGUID.Invalid) return false;
Marshal.StructureToPtr(retguid, guidptr, true);
return true;
}
return false;
}
return (bool)Memory.Instance.Detours["GetGuidByKeywordDetour"].CallOriginal(token, unk0, guidptr, unk1, unk2);
}
public static IntPtr GetUnitPtrByKeyword(string token)
{
IntPtr ret = IntPtr.Zero;
WoWGUID guid = new WoWGUID();
IntPtr guidptr = Marshal.AllocHGlobal(Marshal.SizeOf(guid));
IntPtr strptr = Marshal.StringToHGlobalAnsi(token);
_GetGuidByKeyword(strptr, 0, guidptr, 0, 0);
ret = ClntObjMgrObjectPtrHandler(guidptr, -1); // always 0 for "digit" token string
Marshal.FreeHGlobal(guidptr);
return ret;
}
Last edited by Wildbreath; 11-23-2016 at 09:43 AM.
-
Contributor
The game also has 2 functions GUIDtoString and GUIDFromString. When i did this I Used those functions to pass the object reference back and forth to my new functions as well as hooking the GetGUIDFromToken function
Code:
boolhookGetGUIDFromToken(constchar*&a1,WOWGUID&a2,bool&a3,bool&a4){
if (a1)
{
WOWGUID orig = WOWGUID();
int result = orig.fromString((char*)a1);
if (result != 0)
{
a2 = orig;
return true;
}
}
return false; }
to convert GUID or player,party,ect strings in my new functions i used this :
Code:
CGObject_C*GetUnitFromString(constchar*identifier){
CGObject_C* unit = (CGObject_C*)GetUnitFromName(identifier);
if (!unit)
{
WOWGUID orig = WOWGUID();
int result = orig.fromString((char*)identifier);
if (result != 0)
{
unit = ObjectMgr::GetObjectPtr(orig,TypeMask::TYPEMASK_OBJECT);
}
}
return unit; }
Hope it helps, Its old code not pretty by worked.
Edit: Blackbone help:
Code:
detGetGUIDByKeyword.Hook(oGetGUIDByKeyword, &hookGetGUIDFromToken, HookType::HWBP, CallOrder::HookLast, ReturnMethod::UseOriginal)
Last edited by aeo; 11-23-2016 at 01:58 PM.
-
Post Thanks / Like - 2 Thanks
-
Originally Posted by
Wildbreath
but when i passed guidptr to ClntObjMgrObjectPtr it always return 0 :\
guids still "two ulongs" struct?
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr ClntObjMgrObjectPtrDelegate(IntPtr guid, int unk);
private static ClntObjMgrObjectPtrDelegate ClntObjMgrObjectPtrHandler;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate bool GetGuidByKeywordDelegate(IntPtr token, int unk0, IntPtr guid, int unk1, int unk2);
private static GetGuidByKeywordDelegate GetGuidByKeywordHandler;
private static GetGuidByKeywordDelegate _GetGuidByKeyword;
GetGuidByKeywordHandler = Memory.Instance.RegisterDelegate<GetGuidByKeywordDelegate>(Main.Offsets["GetGuidByKeyword"]);
Memory.Instance.Detours.CreateAndApply(GetGuidByKeywordHandler, _GetGuidByKeyword = GetGuidByKeywordDetour, "GetGuidByKeywordDetour");
private static bool GetGuidByKeywordDetour(IntPtr token, int unk0, IntPtr guidptr, int unk1, int unk2)
{
string tokenstr = Marshal.PtrToStringAnsi(token);
if (tokenstr != null && tokenstr != string.Empty && tokenstr.All(Char.IsDigit))
{
if (!ObjectManager.IsInGame) return false;
Int32 ptr = 0;
Int32.TryParse(tokenstr, out ptr);
if (ptr > 0)
{
WoWGUID retguid = new WoWGUID(new IntPtr(ptr));
if (retguid == WoWGUID.Invalid) return false;
Marshal.StructureToPtr(retguid, guidptr, true);
return true;
}
return false;
}
return (bool)Memory.Instance.Detours["GetGuidByKeywordDetour"].CallOriginal(token, unk0, guidptr, unk1, unk2);
}
public static IntPtr GetUnitPtrByKeyword(string token)
{
IntPtr ret = IntPtr.Zero;
WoWGUID guid = new WoWGUID();
IntPtr guidptr = Marshal.AllocHGlobal(Marshal.SizeOf(guid));
IntPtr strptr = Marshal.StringToHGlobalAnsi(token);
_GetGuidByKeyword(strptr, 0, guidptr, 0, 0);
ret = ClntObjMgrObjectPtrHandler(guidptr, -1); // always 0 for "digit" token string
Marshal.FreeHGlobal(guidptr);
return ret;
}
I've got ClntObjMgrObjectPtr as:
Code:
void* (* ClntObjMgrObjectPtr)(SmartGUID GUID, uint32_t TypeFlags);
and SmartGUID as:
Code:
struct SmartGUID
{
uint64_t Low;
uint64_t High;
};
Here's a slightly simplified version of my Script_GetGUIDFromToken detour if it helps:
Code:
bool Script_GetGUIDFromToken_Detour (const char* Token, bool Unknown1, SmartGUID& GUID, bool Unknown2, bool Unknown3) noexcept
{
constexpr auto PointerLength = sizeof("0x") - 1 + sizeof(void*) * 2;
if (Token && strlen(Token) == PointerLength && Token[0] == '0' && Token[1] == 'x')
{
auto Pointer = reinterpret_cast<void*>(
#ifdef _WIN64
stoull
#else
stoul
#endif
(Token, nullptr, 0)
);
auto Object = GetObjectWithPointer(Pointer);
if (Object)
{
GUID = Object->GetGUID();
}
return Object != nullptr;
}
return Original(Token, Unknown1, GUID, Unknown2, Unknown3);
}
-
Post Thanks / Like - 1 Thanks
Wildbreath (1 members gave Thanks to l0l1dk for this useful post)
-
Member
Going to dive back into this once I'm home, you guys are amazing. Immensely appreciate the help.
-
Contributor
don't know what i'm doing wrong, but ClntObjMgrObjectPtr always return 0, even though the correct GUID (or pointer to GUID) pass 
tried to use callback of EnumVisibleObjects and use return value to pass as object pointer (i think pointer to GUID is game unit pointer, correct me if wrong) - but fail, functions alarmed about the write to protected memory -_-
-
Originally Posted by
Wildbreath
don't know what i'm doing wrong, but ClntObjMgrObjectPtr always return 0, even though the correct GUID (or pointer to GUID) pass

tried to use callback of EnumVisibleObjects and use return value to pass as object pointer (i think pointer to GUID is game unit pointer, correct me if wrong) - but fail, functions alarmed about the write to protected memory -_-
Is the Script_GetGUIDFromToken detour giving the correct GUIDs?
-
Contributor
yes... and it works for player, target and etc. but for "pointed" units fail