@@ -368,7 +368,41 @@ namespace xlive
368368 patch_isdebugger (base, sz);
369369
370370 // -------------------------------------------------------------------
371- // Fix 2: NOP PEB.BeingDebugged pointer corruption
371+ // Fix 2: xlive-research PEVerifyHash bypass (xlive 3.5.95.0)
372+ //
373+ // Upstream patch:
374+ // 000F36B3: 8B FF 55 8B EC -> 31 C0 C2 0C 00
375+ //
376+ // This returns success from PEVerifyHash without touching the xlive
377+ // exports or replacing the dll, so normal GFWL/xlive behavior keeps
378+ // flowing through the retail implementation.
379+ {
380+ constexpr std::uintptr_t rva = 0x000F36B3 ;
381+ static const uint8_t expected[] = { 0x8B , 0xFF , 0x55 , 0x8B , 0xEC };
382+ static const uint8_t ret_success[] = { 0x31 , 0xC0 , 0xC2 , 0x0C , 0x00 };
383+
384+ if (rva + sizeof (expected) <= sz)
385+ {
386+ auto * const target = base + rva;
387+ if (!std::memcmp (target, expected, sizeof (expected)))
388+ {
389+ mem_write (target, ret_success, sizeof (ret_success));
390+ dbg (" patch [F2 PEVerifyHash]: applied at +0x%X" , static_cast <unsigned >(rva));
391+ ++patch_count;
392+ }
393+ else if (!std::memcmp (target, ret_success, sizeof (ret_success)))
394+ {
395+ dbg (" patch [F2 PEVerifyHash]: already applied" );
396+ }
397+ else
398+ {
399+ dbg (" patch [F2 PEVerifyHash]: signature mismatch at +0x%X" , static_cast <unsigned >(rva));
400+ }
401+ }
402+ }
403+
404+ // -------------------------------------------------------------------
405+ // Fix 3: NOP PEB.BeingDebugged pointer corruption
372406 {
373407 static const uint8_t pat[] = {
374408 0x81 ,0xEF ,0x35 ,0x01 ,0x00 ,0x00 ,
@@ -550,4 +584,4 @@ namespace xlive
550584
551585#ifdef DEBUG
552586// REGISTER_COMPONENT(xlive::component)
553- #endif
587+ #endif
0 commit comments