Blizzhackers

Home of the Dupe since 2001

* Login   * Register    * FAQ    * Search

Join us on IRC: #bh@irc.synirc.net (or Mibbit Web IRC)


It is currently Wed May 24, 2017 1:30 am


All times are UTC [ DST ]





Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: 1.14a Offset Updates
PostPosted: Sun Mar 20, 2016 7:58 am 
 
Moderator
Moderator
User avatar

Joined: Thu Dec 09, 2004 6:49 pm
Location: L1 Cache (Data & Instruction)
In the spirit of teamwork and learning, I started a spreadsheet for this work:

https://docs.google.com/spreadsheets/d/ ... edit#gid=0

I only added about 20 functions so far, but I have included the real 1.13d address after the offset to make looking them up easier. I will also add the 1.14a function pointers that I discover (1 so far).

I tried to look up a lot of functions by searching for ASM matches but the new functions are quite altered. The only way I found the CloseNpcInteract pointer was by putting a breakpoint in ollydbg on some 200+ functions while messing around in game. The prospect of finding all the pointers this way is nauseating.


Since I see we have some people interested in making changes I thought I'd make a sticky appropriate to the task.

Good luck with all this, if you thought CloseNPCInteract was bad, have fun working out the IsScrollingText routine. I only hope for your sake that they're using the same basic hashtable implementation!

I'm not sure what tools people have used in the past. My understanding is that people were using some combination of IDA Pro and fuzzy matching to find similar functions. Not sure if the code has changed so much as to make that impossible now. From what vague reading I've done so far it sounds like the code might even have a new compiler which would likely mean those techniques are dead :(.

Feel free to post all your offsets in here. Feel obligated not to flame people!

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Sun Mar 20, 2016 2:23 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
It's much simpler and Faster to find the relevant functions that comparing 2 patches. Meaning you need to sort pointers in connection to each other and make notes.(copy the table!)
The UI related stuff always points to the UITable. DLLbased/Alphabetical sorting never went well. IIRC some 1.13c versions of stings mh for mod servers had the pointers sorted in a proper way.

Ie find the CreateControlfunction and you have several other Controlfunctions follow them and you got all the contol stuff.

If you need to find Controlvariables just breakpoint the find CreateControl function to get the Variablepointers to relevant controls.

In Terms of controls you won't find most "Push Offset VarAddress" Blizzard cut the functions into pieces and uses a few pointers pointing to the Variablespointers to save space.

But IIRC D2bs never used those pointers

Another problem that appeared is that LTO and WPO created some custom calling convetions, so you have to write a few stubs or change existing ones.


Quote:
Not sure if the code has changed so much as to make that impossible now.

It's impossible to use a script, because you could easily identify several stdcalled functions by "sub esp, hex" and the same structure.

Some former ordinalfunctions ie storm are strictly sorted.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Sun Mar 20, 2016 10:17 pm 
 
User
User

Joined: Fri Mar 16, 2012 12:14 am
That's a great point about keeping track of the connections. While finding the few pointers I was able to find I had it in the back of my head that it could be useful to map that out.

This is mostly way over my head but it was pretty cool to spend enough time thinking about it to find a few pointers. I'll probably try and map out the connections in 1.13d a bit and see if that can take me somewhere.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Mon Mar 21, 2016 9:13 pm 
 
Moderator
Moderator
User avatar

Joined: Thu Dec 09, 2004 6:49 pm
Location: L1 Cache (Data & Instruction)
Quote:
Not sure if the code has changed so much as to make that impossible now.

It's impossible to use a script, because you could easily identify several stdcalled functions by "sub esp, hex" and the same structure.

Some former ordinalfunctions ie storm are strictly sorted.


If you have sufficient context and the generated code basically fills the same template (call locations might change and whatnot, but the operations performed within the function are the same) then it's actually quite reasonable to do this. I'm not exactly sure how the comparison scripts work, I just know they exist and they are extremely efficient. With the push of a button usually 80-90% of the functions were found in a new patch. The problem in this case is the code inside the functions has likely changed enough that this won't work anymore. It sounds like they've completely redone things and I wouldn't be surprised if the compiler has changed which makes this method basically useless (it's looking at opcodes rather then behavior basically).

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Mon Mar 21, 2016 11:39 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
It was reasonable because Blizzard has barely touched several libraries. The majority changes were in the d2client.
Storm and Fog were ancient you didn't even have to change the ordinals.


Those scripts are Array of Byte scans.

They look for certain opcode patterns and leave some bytes undefined ie a call gets scanned as E8 XX XX XX XX and return the matching adresses.
You also write them down once you find what you wanted.


They haven't redone everything yet or they were afraid to mess up more critical functions, clean up and remove reduncancy.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 2:55 pm 
 
User
User

Joined: Wed Oct 01, 2003 10:24 pm
Here the patches I think I've found, along with the 1.14c ASM stubs, however from what I could tell not many of these stubs changed very much. Someone mentioned that due to the new orginization we'll need a stub for every intercept? So this list is now very imcomplete?

At this point my biggest problem is that many d2bs pointers are not included in the pointers list but rather defined randomly in the JSUnit code or elsewhere. D2Bot# also has a few un-updateable pointers hardcoded into it. I tried to change the offsets, but that would require changing the entire GetDllOffset sub which requires the source >_<


I posted all of the 1.14b offsets I found in the d2hacking development thread, a number of them are incorrect and almost all of them are untested.


NOTE: The offsets are game.exe offsets, i didnt update the GetDllOffset params.
PatchHook Patches[] = {
   {PatchCall,   GetDllOffset("D2Client.dll", 0x7864f),   (DWORD)GameInput_Intercept,            5},//1.14c //1.14b: 0047864F
   {PatchJmp,   GetDllOffset("D2Client.dll", 0x52972),   (DWORD)GameDraw_Intercept,            6},//1.14c //1.14b: 00452972
   {PatchCall,   GetOffset("D2Client.dll", 0x1284e1),   (DWORD)GamePacketReceived_Intercept,   5},//1.14c //1.14b: 005288F1
   {PatchJmp,  GetOffset("D2Client.dll", 0x128450),   (DWORD)GamePacketSent_Interception,      6},//1.14c //1.14b: 00528860
   {PatchCall,   GetOffset("D2Client.dll", 0x5e51e),   (DWORD)GetSelectedUnit_Intercept,      5},//1.14c //1.14b: 0045E51E
   {PatchJmp,   GetOffset("D2Client.dll", 0x59c15),   (DWORD)PlayerAssignment_Intercept,      5},//1.14c //1.14b: 00459C15
   {PatchBytes,GetOffset("D2Client.dll", 0x63f90),   (DWORD)0xc3,                     1},//1.14c //1.14b: 00463F90
   {PatchCall, GetOffset("D2Client.dll", 0x4fe26),   (DWORD)GameActChange_Intercept,         5},//1.14c //1.14b: 0044FE26
   {PatchJmp,  GetOffset("D2Client.dll", 0x51e9f),   (DWORD)GameActChange2_Intercept,      5},//1.14c //1.14b: 00451E9F
   {PatchCall, GetOffset("D2Client.dll", 0x4ac5d),   (DWORD)GameLeave_Intercept,            5},//1.14c: 0047D6A0
   {PatchCall,   GetOffset("D2Client.dll", 0x5ce90),   (DWORD)GameAttack_Intercept,         5},//1.14c: 0045CE90

//   {PatchCall,   GetOffset("D2Client.dll", 0xA7364),   (DWORD)AddUnit_Intercept,            5},
//   {PatchCall,   GetOffset("D2Client.dll", 0xA6F25),   (DWORD)RemoveUnit_Intercept,         9},

   // this patch needs a constant in ChatPacketRecv_Interception updated also
   {PatchCall, GetOffset("BNCLIENT.DLL", 0x119f7c),   (DWORD)ChatPacketRecv_Interception,     5},//1.14c: 0051A38C

   {PatchCall,   GetOffset("D2Multi.dll", 0x40c64),   (DWORD)Whisper_Intercept,            7},//1.14b: 00440C64
   {PatchCall, GetOffset("D2Multi.dll", 0x3e751),   (DWORD)ChannelInput_Intercept,         5},//1.14b: 0043E751
   
   //{PatchCall,   GetOffset("D2Multi.dll", 0x14A9A),   (DWORD)ChannelWhisper_Intercept,      5},//1.13d //not used
   //{PatchJmp,   GetOffset("D2Multi.dll", 0x14BE0),   (DWORD)ChannelChat_Intercept,         6},//1.13d
   //{PatchJmp,   GetOffset("D2Multi.dll", 0x14850),   (DWORD)ChannelEmote_Intercept,         6},//1.13d
   
   {PatchCall,   GetOffset("D2Win.dll", 0xf706d),      (DWORD)GameDrawOOG_Intercept,         5},//1.14c: 004F706D

   {PatchCall,   GetOffset("D2CMP.dll", 0x207f35),      (DWORD)GameCrashFix_Intercept,         10},//1.14c: 00608345
   
   //{PatchCall,   GetOffset("D2MCPClient.dll", 0x6297), (DWORD)RealmPacketRecv_Interception, 5},
   
   {PatchCall, GetOffset("Fog.dll", 0x4343),      (DWORD)LogMessageBoxA_Intercept,      6},//1.14b: 00404343
};

PatchHook Conditional[] = {
   {PatchJmp,   GetOffset("BNCLIENT.DLL",0x120b35),   (DWORD)ClassicSTUB,      5}, //1.14b: 00520F45
   {PatchJmp,   GetDllOffset("BNCLIENT.DLL",0x120e46),   (DWORD)LodSTUB,         5} //1.14b: 00521256
};


void __declspec(naked) RealmPacketRecv_Interception()
{
   __asm //1.14c unused
   {
      LEA ECX,DWORD PTR SS:[ESP+4]
      PUSHAD
      CALL RealmPacketRecv
      CMP EAX, 0
      POPAD
      JE Block
      CALL EAX
Block:
      RETN
   }
}

void __declspec(naked) GamePacketReceived_Intercept()
{
   __asm //unchanged for 1.14c?
   {
      pop ebp;
      pushad;

      call GamePacketReceived;
      test eax, eax;

      popad;
      jnz OldCode;

      mov edx, 0;

OldCode:
      call D2NET_ReceivePacket_I;

      push ebp;
      ret;
   }
}

void __declspec(naked) GamePacketSent_Interception()
{
   __asm //1.14c may need heavy rewrite
   {
      pushad;
      mov ecx, [esp + 0x2C];
      mov edx, [esp + 0x24];
      call GamePacketSent;
      test eax, eax;
      popad;
      jnz send;
      mov [esp + 0x4], 0;
send:
      //jmp D2NET_SendPacket; //dont want to call our own intercept and were intercepting on the actual func now
   }
}

void __declspec(naked) GameDraw_Intercept()
{
   __asm
   {
      call GameDraw; //1.14c but this now jmps to gamedraw at the end anyway, so this may not be neccessary...?

      POP EBP
      POP EBX
      ADD ESP, 8
      RETN 4
   }
}

void __declspec(naked) GameInput_Intercept()
{
   __asm { //1.14c no change
      pushad
      mov ecx, ebx
      call GameInput
      cmp eax, -1
      popad
      je BlockIt
      call D2CLIENT_InputCall_I
      ret

BlockIt:

      xor eax,eax
      ret
   }
}

UnitAny* GetSelectedUnit_Intercept(void)
{
   //1.14c may need major changes... not sure

   if(Vars.bClickAction)
   {
      if(Vars.dwSelectedUnitId)
      {
         UnitAny* pUnit = D2CLIENT_FindUnit(Vars.dwSelectedUnitId, Vars.dwSelectedUnitType);

         return pUnit;
      }

      return NULL;
   }

   return D2CLIENT_GetSelectedUnit();
}

VOID __declspec(naked) ChatPacketRecv_Interception()
{
        __asm //1.14c this is gonna have to be a jmp now, its no longer call eax but call a sub that i could make a pointer to ehhh
        {
                lea     edx, [esi+4]
                pushad
                mov     eax, edi
                mov     edx, esi

                call ChatPacketRecv
                //test eax, eax //this needs to be replaced with something to trigger the conditional but im not sure what
                popad

                je Block
                //call eax
         Block:
                ret
   }
}
void __declspec(naked) GameAttack_Intercept()
{
   __asm //1.14c unchanged..?
   {
      push ecx
      mov ecx, [esp+0xC]
      call GameAttack
      pop ecx

      cmp eax, -1
      je OldCode

      call D2CLIENT_GetSelectedUnit
      
      cmp eax, 0
      je OldCode

      mov [esp+0x0C], 1

OldCode:
      mov eax, [p_D2CLIENT_ScreenSizeY]
      mov eax, [eax]
      retn
   }
}

void __declspec(naked) PlayerAssignment_Intercept()
{
   __asm //1.14c unchanged
   {
      FNOP
      CALL D2CLIENT_AssignPlayer_I
      MOV ECX, EAX
      CALL GamePlayerAssignment
      RETN
   }
}

void __declspec(naked) GameCrashFix_Intercept()
{
   __asm //1.14c unchanged
   {
      CMP ECX, 0
      JE Skip
      MOV DWORD PTR DS:[ECX+0x10],EDX
Skip:
      MOV DWORD PTR DS:[EAX+0xC],0
      RETN
   }
}

void GameDrawOOG_Intercept(void)
{
   GameDrawOOG();
}

void __declspec(naked) GameActChange_Intercept(void)
{
   __asm //1.14c im not sure about this...
   {
      POP EAX // hopefully this is the same
      PUSH ESI //1.14C
      XOR ESI, ESI
      CMP [Vars.bChangedAct], 0
      MOV [Vars.bChangedAct], 0
      JMP EAX
   }
}

void __declspec(naked) GameActChange2_Intercept(void)
{
   __asm //1.14c updated
   {
      MOV [Vars.bChangedAct], 1
      retn
   }
}

void __declspec(naked) GameLeave_Intercept(void)
{
   __asm //1.14c no change?
   {
      call GameLeave
      jmp D2CLIENT_GameLeave_I
   }
}

void __declspec(naked) ChannelInput_Intercept(void)
{
   __asm //1.14c
   {
      push ecx
      mov ecx, esi

      call ChannelInput

      test eax, eax
      pop ecx

      jz SkipInput
      mov eax, dword ptr[esp+4]
      push eax
      call D2MULTI_ChannelInput_I

SkipInput:
      ret 4
   }
}

VOID __declspec(naked) __fastcall ClassicSTUB()
{
   //1.14c no change?
   *p_BNCLIENT_ClassicKey = Vars.szClassic;
   __asm{
      
      jmp BNCLIENT_DClass;
   }
   
}

VOID __declspec(naked) __fastcall LodSTUB()
{
   //1.14c no change?
   *p_BNCLIENT_XPacKey = Vars.szLod;
   __asm{
      
      jmp BNCLIENT_DLod;
   }
   
}

int WINAPI LogMessageBoxA_Intercept(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption,
    UINT uType)
{ // 1.14b unchanged
   char* dllAddrs;

   Log("Error message box, caption: \"%s\", message:\n%s\n%s", lpCaption,
      lpText, dllAddrs = DllLoadAddrStrs());

   free(dllAddrs);

   return MessageBoxA(hWnd, lpText, lpCaption, uType);
}

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 4:53 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
All you need to do on the oogs is to remove/fix cachefix, multiload and rdblocker.
Just use reflector+reflexil.
In bobodes case d2data.vb is obfuscated but it's not difficult to obtain the code.


The pointers are all defined in d2ptrs most are used in the Js functions.

Either you need to be certain what you are doing or you need to test them.
You need to understand the purpose of the function/patch.

Look IE at the GameActChange2 patch and see what would happen if you patch 5 bytes there?


FYI -0x410 -0x1000 and -0x10B8 are the only changes you have to 114b most of it is unchanged.

114 had several calling convention changed regarding clientfunctions.

Look at the stack check if your stub still uses the data it needs.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 7:18 pm 
 
User
User

Joined: Wed Oct 01, 2003 10:24 pm
I guess what I meant was that there other offsets that are used that arn't pointers used for read and writing to memory. I didn't look much further cause once I found other uses of GetDllOffset I got a bit frustrated.

I've been updating d2bot, however have been running into some rather fundamental problems with it's basic dll loading sequence. Seems totally borked when I decompile it. Even if I do fix what I have releasing it would be awkward without the support of noah.

GameActChange2 patch.... I was making that a jmp now as opposed to a call I think, that's why it says 5 and not 6, I had only changed the PatchCall to a PatchJmp but hadn't followed up.

There is a lot to learn.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 7:48 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
You talk about the InventoryDumping 2 of those are pointers.

What you also need to update are the MPQstats that's it for D2BS.


You patch into another function! You mustn't do that.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 8:23 pm 
 
User
User

Joined: Wed Oct 01, 2003 10:24 pm
Er I do? I know I'm patching on the retn, but if it's a jmp won't the retn just be moved to the line below?

My launcher uses detours so it's a lot easier than this crazy d2bs intercept system....

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 8:32 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
I am talking about the original code not the Stub.

You change the opcodes of the next function resulting in a crash once that function gets called.

You were patching a ret and int3 before. There was no problem.
Now you patch into the next function and there is a big problem

That's why you should understand the concepts of dllinjection, memoryediting and asm first before you attempt to do stuff.
Comparing doesn't get you far.

Once you understood that you will easily understand what you did wrong.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 8:44 pm 
 
User
User

Joined: Wed Oct 01, 2003 10:24 pm
Ay I am to.... I thought that d2bs intercept system treated calls and jmps differently... I was wrong.

Why doesn't d2bs use detours? To heavy for a dll that's injected?


Eitherhow, it seem's the easiest way to fix this is to add an intercept method that saves the oldcode as the last instruction.... I really thought thats what it was already doing for jmps, yeesh.

Oh well!

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 8:47 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
The most simple way is to patch the beginning of a function and check the parameters if there are any.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 9:11 pm 
 
User
User

Joined: Wed Oct 01, 2003 10:24 pm
Ohhh that makes sense since I can just toss the registers around the same way they do even if I overwrite them.... hmmmm.

But d2bs intercepts are rarely on the function and at some specific line in the function instead -- im guessing because the data it needs isn't set until that line. That was the only difficulty that came to mind with using trampolines instead of intercepts.

Top
 Profile  
 Post subject: Re: 1.14a Offset Updates
PostPosted: Thu May 19, 2016 9:58 pm 
 
User
User

Joined: Tue Mar 01, 2005 8:31 pm
It's because of convenience.

If you check the actchange intercepts all they do is set a var to 0/1 actually the hook's aren't needed since you hook the GS Send/Receive Packet as well you can just check if you receive an unload/load act packets.

There is a lot of code which can be optimized.

IE you could stop using D2's memory pool and improve memory management.

Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron