-
Corporal
Originally Posted by
nengonon
Hi guys I'm not sure how PQR works internally but is there any way to get it to work with this build(actually for elysium server)?
Here's an example of the needed offsets:
<CurrentWoWVersion>5875</CurrentWoWVersion>
<WoWVersionOffset>0x00837C0</WoWVersionOffset>
<PlayerName>0x827D88</PlayerName>
<PlayerClass>0x879E89</PlayerClass>
<GetCurrentKeyBoardFocus>0x9CE474</GetCurrentKeyBoardFocus>
<GameState>0x00B4B424</GameState>
<Lua_DoStringAddress>0x419210</Lua_DoStringAddress>
<Lua_GetLocalizedTextAddress>0x3225E0</Lua_GetLocalizedTextAddress>
<Detour>0xBF0F0</Detour>
<Overwritten>55 8B EC 81 EC F8 00 00 00</Overwritten>
I would appreciate any tip on the matter
I'm pretty sure Lua_GetLocalizedText doesn't exist in this build so changing the offsets won't help, PQR code need to be modified to use FrameScript_GetText instead.
-
Post Thanks / Like - 1 Thanks
nengonon (1 members gave Thanks to NotJuJuBoSc for this useful post)
-
-
Member
Originally Posted by
nengonon
Hi guys I'm not sure how PQR works internally but is there any way to get it to work with this build(actually for elysium server)?
Here's an example of the needed offsets:
<CurrentWoWVersion>5875</CurrentWoWVersion>
<WoWVersionOffset>0x00837C0</WoWVersionOffset>
<PlayerName>0x827D88</PlayerName>
<PlayerClass>0x879E89</PlayerClass>
<GetCurrentKeyBoardFocus>0x9CE474</GetCurrentKeyBoardFocus>
<GameState>0x00B4B424</GameState>
<Lua_DoStringAddress>0x419210</Lua_DoStringAddress>
<Lua_GetLocalizedTextAddress>0x3225E0</Lua_GetLocalizedTextAddress>
<Detour>0xBF0F0</Detour>
<Overwritten>55 8B EC 81 EC F8 00 00 00</Overwritten>
I would appreciate any tip on the matter
Did you have any luck getting this to work? I'm also after a rotation bot, something like PQR would be perfect for 1.12.1.
-
Member
Originally Posted by
Lysolfs
WoW.exe + 0x0087BCD4 + 0x88 + 0x18 pointers to player guid
This is an old thread, but i think the correct is:
Base (wow.exe) + 0x0087BCD4 + 0x88 + 0x28
Last edited by Haugli92; 01-30-2017 at 02:48 AM.
-
Active Member
Hoping this will be useful to someone...
Here is a list of all of the buffs sorted alphabetically and uppercased with their matching ids. I tried to remove as many unused buffs as I could without going too far into it. Hopefully didn't remove any actual in use buffs.
552,ABOLISH DISEASE 2893,ABOLISH POISON 14253,ABOLISH POISON 12884,ACID - Pastebin.com
Personally i'm using this to identify buffs/debuffs on a unit/player.
-
Contributor
anyone happen to have the address of print locally ie DEFAULT_CHAT_FRAME:AddMessage("hi im here") <== the function that this calls trying to do everything without using wows lua api at all nvm got it
anyone know of a way to get quests already completed? thinking its not possible since ive searched everywhere and cant find it
Last edited by Icesythe7; 02-27-2017 at 11:41 PM.
-
Looking over the leaked NostReturns/Elysium core I found a warden test function, it looks like they are calling a function. Can they do that? Like if a user does not have DEP enabled and a server dev found a way to send some shell code could they execute it? Or even just send a moded warden module? 0x5ABE10 looks like a player dump function.
Code:
BigNumber n;
n.SetHexStr("01000200A0772400F08724006084240030872400040000409D41000101010010C0020001");
//sLog.outDebug("SERVER WARDEN: Initialize module
//uint32 callFunc = s_currentModule + 0x5CBC;
uint32 callFunc = 0x5ABE10;
callFunc = callFunc - 0x400000;
uint8 result[8];
result[0] = 0x01;
result[1] = 0x01;
result[2] = 0x00;
result[3] = (callFunc & 0x000000ff);
result[4] = (callFunc & 0x0000ff00) >> 8;
result[5] = (callFunc & 0x00ff0000) >> 16;
result[6] = (callFunc & 0xff000000) >> 24;
result[7] = 0x01;
// hex string -> byte[]
ByteBuffer buff_b, buff_c;
uint8* temp = n.AsByteArray(0, false);
buff_c.append(temp, 36);
buff_b << uint8(0x03);
buff_b << uint16(20);
buff_b << uint32(BuildChecksum(buff_c.contents(), 20));
buff_b.append(buff_c.contents(), 20);
buff_b << uint8(0x03);
buff_b << uint16(8);
buff_b << uint32(BuildChecksum(buff_c.contents() + 20, 8));
buff_b.append(buff_c.contents() + 20, 8);
buff_b << uint8(0x03);
buff_b << uint16(8);
buff_b << uint32(BuildChecksum(result, 8));
buff_b.append(result, 8);
// Encrypt with warden RC4 key.
EncryptData(const_cast<uint8*>(buff_b.contents()), buff_b.size());
WorldPacket pkt(SMSG_WARDEN_DATA, buff_b.size());
pkt.append(buff_b);
_session->SendPacket(&pkt);
Last edited by DarkLinux; 02-28-2017 at 01:35 AM.
-
Post Thanks / Like - 2 Thanks
-
That function is called 'ClientServices::Report' and it is used in submitting bug reports.
I imagine that the purpose of trying to call this was to get the computer information it included so as to generate a fingerprint to identify a computer despite account name and IP changes. Useful for tracking spammers etc.. It seems like they are sending it as part of the Warden module initialization packet which sets function pointers to various functions within the binary. DEP would not object. It will be an indirect call from an executable segment (the .text segment of the Warden module) to an executable segment (the .text section of wow.exe in this case). But this does not allow arbitrary code execution. At most it allows calling of an arbitrary function. Note however that if the prototype for the target function does not match the prototype for the function which that Warden module expects, it will likely corrupt the stack.
Edit: in this case it seems like it would corrupt the stack. The prototype for ClientServices::Report is:
Code:
bool __thiscall ClientServices::Report(int param, const char *category)
and the function pointer passed to Warden (assuming they use the same module everyone else does, which I'm sure they do) is invoked like this:
Code:
Warden:0D69319C 8B 8B 28 02 00 00 mov ecx, [ebx+228h]
Warden:0D6931A2 8B 9B EC 07 00 00 mov ebx, [ebx+7ECh]
Warden:0D6931A8 85 DB test ebx, ebx
Warden:0D6931AA 74 0C jz short loc_D6931B8
Warden:0D6931AC FF D3 call ebx
There is no argument pushed to the stack.
Edit 2: The start of ClientServices::Report seems like it is doing something manually to the stack. No idea what. It may actually work.
Last edited by namreeb; 02-28-2017 at 03:11 AM.
-
Post Thanks / Like - 3 Thanks
-
Right but if the server sent some code via a chat message (or some exploit), and they found the pointer to that message they could execute that code if DEP was not enabled. And like you posted, only if that shell code followed the calling convention of the Warden initialization call. Also where does warden do its module check? Do you need to send a valid warden module to make it call that function? Thanks!
--edit
ah I see, its warden doing the call.
Last edited by DarkLinux; 02-28-2017 at 03:27 AM.
-
Post Thanks / Like - 1 Thanks
Corthezz (1 members gave Thanks to DarkLinux for this useful post)
-
Originally Posted by
DarkLinux
Right but if the server sent some code via a chat message (or some exploit), and they found the pointer to that message they could execute that code if DEP was not enabled. And like you posted, only if that shell code followed the calling convention of the Warden initialization call. Also where does warden do its module check? Do you need to send a valid warden module to make it call that function? Thanks!
Oh, I understand what you're saying. But yes you're right that DEP would prevent that. Unless of course you could find a page of memory that is both writeable and executable and somehow make sure that what you sent to the client was written to that page.
Originally Posted by
DarkLinux
Also does anyone have the offset for that Warden initialization call? Going to hook it and check every call to see if its the same.
For that warden module, the handler for the opcode 3 message is offset 0x4E1E bytes from the start of the .text segment.
-
Post Thanks / Like - 1 Thanks
DarkLinux (1 members gave Thanks to namreeb for this useful post)
-
Let just hope no one finds such a page that the server can write to. Would really shake up the emu scene. At minimum everyone should double check they have DEP enabled. Time to see if the client has any character checks on quest text I guess it would be easy to detect warden looping over the itemDB/questDB.
-
Post Thanks / Like - 1 Thanks
tutrakan (1 members gave Thanks to DarkLinux for this useful post)
-
In case you didn't see it, I released some research I did into arbitrary Warden module signing in December/January: GitHub - namreeb/WardenSigning: Experimenting with Warden signature cracking
-
Yes I have looked over your repo on WardenSigning, really nice job, wish more came of it.
I am curious if anyone has a different version of fmod.dll (MD5 - B8D0CCE2CA1CC850C8C6F25A70D855E6). It looks to be the only module with a read/write/execute page. I think it would be a stretch to get wow to load a buffer for fmod with code and not have it crash. And then to find it and execute it.
-
Contributor
Originally Posted by
DarkLinux
I love you. I was looking for that kind of source for a long time.
-
Originally Posted by
DarkLinux
Yes I have looked over your repo on WardenSigning, really nice job, wish more came of it.
I am curious if anyone has a different version of fmod.dll (MD5 - B8D0CCE2CA1CC850C8C6F25A70D855E6). It looks to be the only module with a read/write/execute page. I think it would be a stretch to get wow to load a buffer for fmod with code and not have it crash. And then to find it and execute it.
Yes I noticed that the fmod .text segment is writeable. But even that doesn't help you because even fmod's own stack and heap would be in another page. You'd have to find a way to write to, and call, an arbitrary address. You could probably use the Warden memory reading function to find the base address of the fmod .text segment, though.
Edit: For general information, I think the way you'd have the highest chance of success to find something like this would be to look at the opcode handlers which write values to global variables offset by some parameter of the server's packet. For example MSG_RAID_TARGET_UPDATE, psuedo-code here:
Code:
int __stdcall Handler_MSG_RAID_TARGET_UPDATE(int _58, CDataStore *a2)
{
CDataStore *v2; // ebx@1
unsigned int v3; // esi@2
int v4; // ecx@3
CGObject_C *v5; // eax@4
unsigned __int64 v6; // ST04_8@9
CGObject_C *v7; // eax@9
int v8; // ecx@9
CGObject_C *v9; // eax@11
int a1; // [sp+4h] [bp-4Ch]@2
int a4[15]; // [sp+8h] [bp-48h]@3
unsigned __int64 a3; // [sp+44h] [bp-Ch]@8
char v14; // [sp+4Fh] [bp-1h]@1
v2 = a2;
CDataStore::Get8(a2, &v14);
if ( v14 )
{
qmemcpy(&a1, &dword_B71368, 0x40u);
memset(&dword_B71368, 0, 0x40u);
v3 = 0;
do
{
v4 = a4[2 * v3];
if ( v4 | *(&a1 + 2 * v3) )
{
v5 = ClntObjMgrObjectPtr(
8u,
"E:\\build\\buildWoW\\WoW\\Source\\Ui\\RaidInfo.cpp",
__PAIR__(v4, *(&a1 + 2 * v3)));
if ( v5 )
sub_608A90(v5);
}
++v3;
}
while ( v3 < 8 );
}
while ( !v2->VMT->IsRead(v2) )
{
CDataStore::Get8(v2, (_BYTE *)&a2 + 3);
CDataStore::Get64(v2, &a3);
if ( BYTE3(a2) < 8u )
{
HIDWORD(v6) = *(&dword_B7136C + 2 * BYTE3(a2));
LODWORD(v6) = *((_DWORD *)&dword_B71368 + 2 * BYTE3(a2));
v7 = ClntObjMgrObjectPtr(8u, "E:\\build\\buildWoW\\WoW\\Source\\Ui\\RaidInfo.cpp", v6);
v8 = BYTE3(a2);
*((_DWORD *)&dword_B71368 + 2 * v8) = a3;
*(&dword_B7136C + 2 * v8) = HIDWORD(a3);
if ( v7 )
sub_608A90(v7);
v9 = ClntObjMgrObjectPtr(8u, "E:\\build\\buildWoW\\WoW\\Source\\Ui\\RaidInfo.cpp", a3);
if ( v9 )
sub_608A90(v9);
}
}
FrameScript_SignalEvent(0x219u);
return 1;
}
Now if that 8 bit parameter were a 32 bit parameter, you could write 8 bytes at a time to any address larger than 0xB7136C, which would solve half the problem.
Last edited by namreeb; 02-28-2017 at 06:36 PM.