-
[Retail] BFA 8.3.7.35284 Offsets
Spend the last 2 days learning about pattern scanning and implementing my own pattern scanning system. Learned quite a bit about assembly, especially regarding relative addressing
Here are the results of my experiments None of these have been verified yet.
Code:
FrameScript_Initialize: 52F850
FrameScript_GetContext: 52F090
FrameScript_RegisterFunction: 52FA30
Script_GetGUIDFromToken: 16C0760
Script_GetGUIDFromToken_Wrapper: 16C0720
ClntObjMgrEnumVisibleObjects: FE8270
ClntObjMgrEnumVisibleObjectsPtr: FE82F0
ClntObjMgrGetCurrent: FEF7E0
ClntObjMgrIsValid: FEFFA0
ClntObjMgrObjectPtr: 11B8950
CActorManager__Get: DE0850
CActorManager__GetActorUnit: DE0930
ClientServices__GetCharacterName: 1C6A80
CGGameObject_C__GetName: E41E60
CGUnit_C__GetDisplayedHealth: DA0970
CGUnit_C__GetUnitNameExposed: DA6E10
luaL_error: 1A00980
lua_getfield: 1DEE90
lua_gettable: 1DEF80
lua_gettop: 1DEFB0
lua_insert: 1DF110
lua_isfunction: 1DF230
lua_isnumber: 1DF260
lua_isstring: 1DF290
lua_pushboolean: 1DF5C0
lua_pushcclosure: 1DF5F0
lua_pushguid: 5356F0
lua_pushinteger: 1DF760
lua_pushnil: 1DF830
lua_pushnumber: 1DF850
lua_pushstring: 1DF870
lua_rawset: 1DFBB0
lua_settop: 1E0200
lua_toboolean: 1E03E0
lua_tolstring: 1E04C0
lua_tonumber: 1E0440
lua_type: 1E0670
s_CharacterName: 294C5B8
s_curMgr: 2A4BE60
s_luaContext: 29B2928
s_luaThreadId: 29B2930
CGUnit_C->PredictedHealth: 1378
CGUnit_C->Health: 1588
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Post Thanks / Like - 3 Thanks
-
Member
Is it based on Descriptors or idc script?
-
I'm not sure what you mean. The project uses neither existing data (Descriptors aren't a thing anymore, I thought?) nor IDA.
The project is written in C# .net 5 and it uses the c# bindings for capstone. I'm using IDA compatible byte sequence patterns and a crude FindPattern implementation. Some of the things that I want to find cant be easily extracted using just patterns - especially when blizzards compiler decides to use different registers for a given instruction, but that's where capstone comes in
It's still a rather messy project, but it already speeds up the update process a lot.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Originally Posted by
xalcon
It's still a rather messy project, but it already speeds up the update process a lot.
Any chance you plan to share some points on how you accomplished this? Currently, BinDiff takes more than an hour for me to diff/load-symbols and it always misses some stuff.
I also have these for lua in case anyone needs..
Code:
FrameScriptGetText = 0x532970;
FrameScriptExecute = 0x52EA60;
Last edited by GlittPrizes; 07-27-2020 at 07:55 AM.
-
There isnt really much to share. There is a handy plugin for IDA (SigMaker) that allows you to easily create signatures from code fragments and xrefs. For the stuff that sigmaker couldn't get reliable signatures (i.e. for short functions that are padded with garbage opcodes) I've build the patterns by hand and added some disassembly logic via capstone.
You could probably use Projects . Ian / WoWOffsetDumper . GitLab as a stepping stone. I was thinking about using it, but the pattern scanning library (clepta) is lacking docs so I just googled a bunch about this topic and wrote my own scanner. The most work was generating all the signatures and checking them across multiple versions of wow to ensure they are somewhat reliable.
But on a different topic: Did anyone do some work on the object structures? I've taken a closer look at the unit structures and found quite a few things.
Here is an incomplete kaitai struct definition of the CGObject_C and CGUnit_C data structures. It's still missing a lot of stuff, but I'll keep adding things when I find new stuff. If anyone has a better solution to dissect memory structures (with support for custom data types and possibly custom debug representations), hit me up. Kaitai is a bit clunky but it's much better than cheat engine or reclass imo.
I've made this on 8.3.0.34963 but after a quick check it still seem to be the same in 8.3.7.35284 (but I've not fully verified that yet, I need to update my trinity core)
https://hastebin.com/puyiconugi.yaml
Kaitai Struct WebIDE: Kaitai Web IDE
example unit dumps, just load them with the kaitai struct definition into the web ide (Don't get your hopes too high, those dumps are from a BFA trinity core private server :P):
http://xalcon.net/files/ActivePlayer...5_Veliline.bin
http://xalcon.net/files/ActivePlayer...Lillianore.bin
http://xalcon.net/files/Unit_Unit_20...20Sentinel.bin
http://xalcon.net/files/Unit_Unit_20...ng%20Dummy.bin
http://xalcon.net/files/Unit_Unit_20...ana%20Wyrm.bin
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Post Thanks / Like - 3 Thanks
-
Member
Originally Posted by
hycolyte
Any chance you plan to share some points on how you accomplished this? Currently, BinDiff takes more than an hour for me to diff/load-symbols and it always misses some stuff.
I also have these for lua in case anyone needs..
Code:
FrameScriptGetText = 0x532970;
FrameScriptExecute = 0x52EA60;
"FrameScript_Execute", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 56 48 83 EC 70 83 05 ? ? ? ?"
"FrameScript_GetText", "40 55 57 41 54 41 56 41 57 48 83 EC 20 48 8D 6C 24 20 4C 8B F9 48 89 5D 38 8B 0D ? ? ? ?"
-
Member
When I add
baseArmor:
pos: (0x1838-0xA8)
type: u4
It will
Parse error: undefined
Call stack: undefined ReferenceError: WowUnit is not defined
I know the reason, can’t have capital letters
Thank you for sharing
Code:
basearmor:
pos: (0x1838 - 0xA8)
type: u4
negbuffarmor:
pos: (0x1854 - 0xA8)
type: u4
money:
pos: (0x3DD8 - 0xA8)
type: u4
currentxp:
pos: (0x3DE0 - 0xA8)
type: u8
maxxp:
pos: (0x3DE4 - 0xA8)
type: u8
Last edited by 34D; 07-27-2020 at 09:25 PM.
-
Member
Great to see some BFA activity!
-
Originally Posted by
xalcon
Code:
lua_tolstring: 1E04C0
Is there also just a regular lua_tostring? I've been trying to get the arguments passed into custom scripts, but it doesn't work for me with using lua_tolstring on the state.
edit: I guess I'm looking for something like this
Code:
const char *lua_tostring (lua_State *L, int index);
Equivalent to lua_tolstring with len equal to NULL.
Last edited by GlittPrizes; 08-02-2020 at 07:59 AM.
-
Originally Posted by
hycolyte
Is there also just a regular lua_tostring? I've been trying to get the arguments passed into custom scripts, but it doesn't work for me with using lua_tolstring on the state.
edit: I guess I'm looking for something like this
Code:
const char *lua_tostring (lua_State *L, int index);
Equivalent to lua_tolstring with len equal to NULL.
Technically, no there is no lua_tostring. The lua_tostring you can see in the docs is just a macro around lua_tolstring.
Code:
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
There are quite a few lua functions that are just macros and therefore got inlined by the compiler.
I.e. for most lua_is* functions you only need lua_type (exceptions are isnumber, isstring, iscfunction and isuserdata).
See Lua 5.1.5 source code - lua.h for a full list
Code:
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Post Thanks / Like - 1 Thanks
GlittPrizes (1 members gave Thanks to xalcon for this useful post)
-
Originally Posted by
xalcon
Technically, no there is no lua_tostring. The lua_tostring you can see in the docs is just a macro around lua_tolstring.
Code:
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
There are quite a few lua functions that are just macros and therefore got inlined by the compiler.
I.e. for most lua_is* functions you only need lua_type (exceptions are isnumber, isstring, iscfunction and isuserdata).
See
Lua 5.1.5 source code - lua.h for a full list
Code:
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
I'm starting to get a better understanding after diffing 5.1 and reading the documentation. I'm still a little confused how to use lua_gettop properly, but I can work around it for most things for now. Here are some of my notes:
- If you patch invalid ptr just detach a thread to call FSExecute and yield while the handle is not zero (I was using a WndProc trap with an enum state to fire Ex from the main thread, but that becomes tricky with custom scripts with sleeps)
- If you are just going to work with the player, it's target, and just a few objects in general then register a script to iterate over the objects just once. That way you don't have to have an open process to keep updating objects
- Use lua_pushnumber, lua_pushstring, etc to populate the stack and return the amount of returns
- Make a IsPlayerNull() function helper to iterate the objects and grab the player pointer if it's null, then it's safe to use the vtable/ptr as arguments in your other scripts
- Use lua_tonumber, lua_tostring, etc to grab arguments from the luaState
- C_Timer operates from a different address space than your custom scripts, so you need to make a homebrew timer. It should just pass a function instead of a string. I'm not necessarily doing this right, and the server is down so I can't test. However, it will resemble something like this:
Code:
int LuaScript::ExecuteAfterMS(int64_t luaState)
{
auto sleepTime = GameMethods::ToNumber(luaState, 1);
auto command = GameMethods::ToLString(luaState, 2, nullptr) + "()";
if(sleepTime <= 0)
return 1;
thread executeThread ([=]()
{
Sleep(sleepTime);
GameMethods::Execute(command);
return 0;
});
executeThread.detach();
auto hThread = executeThread.native_handle();
while(hThread)
this_thread::yield;
return 1;
}
Register:
Code:
case WM_USER_TICK:
if(!luaRegistered)
{
luaRegistered = true;
LuaScript::RegisterHandler("myTimer", LuaScript::ExecuteAfterMS);
LuaBase::PushLua();
}
return false;
Usage:
Code:
myTimer(1000, 'funcToCall')
p.s. Sorry to my Discord buddies for dipping on the group. I must be on my period or something cuz I'm the world's biggest flake over and overr.:confused:
Last edited by GlittPrizes; 08-04-2020 at 11:09 AM.
-
Originally Posted by
StillAVirgin64
I'm starting to get a better understanding after diffing 5.1 and reading the documentation. I'm still a little confused how to use lua_gettop properly, but I can work around it for most things for now.
lua_gettop returns the number of elements on the lua stack. It is useful if you want your c function to be called with an abitrary amount of arguments since it allows you to determine how many things are on the stack. Other than that, there arent many usecases for lua_gettop. You can use it to make sure you dont leak things on the stack. I.e. if you call lua_getglobal/getfield and you don't use a function that automatically pops the value (lua_pop, lua_pcall) from stack, you will crash or cause undefined behavior - but thats something that i would categorize as debugging aid rather than actual production code.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK