Injection Flow

This forum is for discussions on how to edit what can not be edited through the txt files, needless to say this isn't about battle net hacking.

Moderators: Nefarius, Havvoric

Garett_
Posts: 2
Joined: Mon May 29, 2023 4:32 am

Injection Flow

Post by Garett_ » Thu Jun 08, 2023 12:25 am

Hello, I am currently looking at the code of PlugY.

I would like to overwrite a diablo2 function and to achieve that, I have been researching what has currently been done with one of the functions was that overriden in order to enable a functionality. However, I can't quite grasp what is going on.

I would expect the core function to be duplicated somewhere else in memory, so that we can override the original one to call a new function with the same parameters.
That way, if we want to execute other statements instead of executing the original functions we could, and if we want to fallback the old code, that would also be a possibiliy.

When looking at the D2SpawnSuperUnique function, I see that it has the following definition :

Code: Select all

D2SpawnSuperUnique, (Game* ptGame, Room* ptRoom, DWORD zero1, DWORD x, DWORD y, DWORD minusOne, DWORD superuniqueID, DWORD zero2));//wrong param
Which appear to be defined at offset CDE20 (vary depending on the version)

But when it is time to inject the function override, the following is done :

Code: Select all

	DWORD pos = mem_seek R8(D2Game, 0000, 0000, 3F720, 4BCB1, ECF10, 41570, 25280, CFBD0, 1A4A4F);
	MEMC_REF4( V2SpawnSuperUnique , version_D2Game >= V114a ? (DWORD)caller_spawnDClone_114 : version_D2Game >= V111b ? (DWORD)caller_spawnDClone_111b : version_D2Game == V111 ? (DWORD)caller_spawnDClone_111 : (DWORD)spawnDClone);
Offset CFBD0 is used? I am not sure on what this is based on.

This will then inject the following assembly code which appear to simply be a redirect for the newer function :

Code: Select all

	PUSH EDX
	PUSH ECX
	PUSH DWORD PTR SS:[ESP+0x1C]
	PUSH DWORD PTR SS:[ESP+0x1C]
	PUSH DWORD PTR SS:[ESP+0x1C]
	PUSH EAX
	MOV EDX,DWORD PTR SS:[ESP+0x20]
	MOV ECX,DWORD PTR SS:[ESP+0x1C]
	CALL spawnDClone
	RETN 0x14
And then the new function calls the original function :

Code: Select all

DWORD FASTCALL spawnDClone(Game* ptGame, Room* ptRoom, DWORD p3, DWORD p4, DWORD p5, DWORD p6, DWORD monsterID, DWORD p8)
{
	if (WEactive && (ptGame->difficultyLevel == D2DM_HELL) && !DCloneSpawned)
	{
		DCloneSpawned=1;
		D2SpawnSuperUnique(ptGame,ptRoom,p3,p4,p5,p6,worldEventmonsterID,p8);
		return 0;//no minions
	}
	else
		return D2SpawnSuperUnique(ptGame,ptRoom,p3,p4,p5,p6,monsterID,p8);
}
Am I correct to assume that instead of doing any function duplication or anything like that, another function that always end up calling the D2SpawnSuperUnique has been found and the redirect has been placed at this location?

I am sorry, I am just trying to understand what's going on / how that function override was created.

Garett_
Posts: 2
Joined: Mon May 29, 2023 4:32 am

Re: Injection Flow

Post by Garett_ » Sat Jun 17, 2023 4:22 pm

Maybe it would be simpler to have a summary of the steps required in order to patch a d2 function?

I know programming although c++ isn't my strengh at all, I know how to use cheat engine / put breakpoint in the assemblies. But yeah, I know nothing about these memory patching concepts.

Return to “Code Editing”