DInput8HookingExample icon indicating copy to clipboard operation
DInput8HookingExample copied to clipboard

Crashing when used on a protected app/game

Open anr2me opened this issue 1 year ago • 2 comments

https://github.com/pampersrocker/DInput8HookingExample/blob/b9b7e790fe0deb96c2c7884dcf5b3aac5a88c879/MinimalDInput8Hook/Hook.cpp#L36

On a protected app/program some of the Descriptor contains invalid value resulting to a crash due to access violation, seems to start with a Descriptor that is filled with zeroes (0x00)

Adding these lines should be able to prevent the crash.

                const char* ImportDLLName = (const char*)BaseAddress + Descriptor->Name;
		// On a packed/protected program, some of the descriptors might contains an invalid data (feels like exceeding the actual number of import descriptors), zero-filled Descriptor seems to be used as terminator.
		if (!Descriptor->Name || !Descriptor->FirstThunk)
			break;

anr2me avatar Jun 27 '23 15:06 anr2me

Thanks, have you tested if the rest of the array is safe, or it just stops from the offending entry? I am thinking of replacing the break; in your code with a continue to basically just skip the mangled entry.

pampersrocker avatar Jun 27 '23 16:06 pampersrocker

The rest of the descriptors after the one filled with all zeroes seems to contains random junk which is an invalid memory address and resulting to access violation when used on strcmp

i've tried using continue and still crashing, i even tried to wrapped it with try..catch but nothing useful being printed after the terminating descriptor (the one filled with all zeroes).

Printed using:

WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), ImportDLLName, (DWORD)strlen(ImportDLLName), nullptr, nullptr);
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), "\n", 1, nullptr, nullptr);

The Result was :

...
WINTRUST.dll
WLDAP32.dll
WS2_32.dll <-- this is the last valid name right before the one filled with all zeroes
MZ� <-- this is the descriptor right after the one filled with all zeroes
MZ�

PS: Might be better to check the whole content of the Descriptor whether it's all zeroes or not as termination indicator, instead of partially by field, like:

                unsigned char* mm = (unsigned char*)Descriptor;
		if ((*mm == 0) && memcmp(mm, mm + 1, sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1) == 0) 
			break;

anr2me avatar Jun 27 '23 16:06 anr2me