diff --git a/KIOUHook.h b/KIOUHook.h index c54547d..2c7343b 100644 --- a/KIOUHook.h +++ b/KIOUHook.h @@ -40,7 +40,15 @@ // Single observer-dispatcher slot. Every CAVE_OBSERVER cave loads this // pointer, BLRs it with W6 = hook_id, and routes through dispatch_one. -#define KIOU_HOOK_OBSERVER_SLOT_RVA 0x8F90C80 +// +// Placement: sits inside __DATA.__common just past the entry-slot table +// capacity (ENTRY_SLOT_BASE_RVA + ENTRY_SLOT_CAPACITY * 8 = 0x091E92B8). +// The old 0x8F90C80 landed in __DATA.__bss, which UnityRuntime / il2cpp +// overwrites during lazy init — publishing dispatch_one there survived +// startup but got clobbered before the first observer fire, so the cave +// BLR X16 jumped to garbage and crashed with a PC alignment fault. See +// recipes/v1_0_2.py for the __common vs __bss note. +#define KIOU_HOOK_OBSERVER_SLOT_RVA 0x091E92B8 // Entry-cave slot table. Slot N at +N*8 holds the function pointer the // CAVE_ENTRY cave BLRs directly (no dispatcher). diff --git a/recipes/__init__.py b/recipes/__init__.py index 8541a59..1fdeaeb 100644 --- a/recipes/__init__.py +++ b/recipes/__init__.py @@ -60,6 +60,9 @@ assert _v.ENTRY_SLOT_BASE_RVA + ENTRY_SLOT_CAPACITY * 8 <= _v.ZERO_REGION_END_RVA, ( f"entry slot reservation overflows verified-zero region for {_target_version}" ) +assert _v.HOOK_SLOT_RVA + 8 <= _v.ZERO_REGION_END_RVA, ( + f"observer slot placement overflows verified-zero region for {_target_version}" +) CAVE_REGION = _v.CAVE_REGION HOOK_SLOT_RVA = _v.HOOK_SLOT_RVA diff --git a/recipes/v1_0_1.py b/recipes/v1_0_1.py index 364d70c..4981c3c 100644 --- a/recipes/v1_0_1.py +++ b/recipes/v1_0_1.py @@ -15,7 +15,10 @@ BUILD = 11 CAVE_REGION = (0x8268024, 0x826C000) -HOOK_SLOT_RVA = 0x8F90C80 +# See v1_0_2 for the rationale: 0x8F90C80 (__DATA.__bss) is unstable — +# UnityRuntime overwrites it after KIOUChinlanPublish. Move to __common +# right after the entry-slot table capacity, where publishes survive. +HOOK_SLOT_RVA = 0x091E92B8 PROBED_HOOK_SLOT_RVA = HOOK_SLOT_RVA INJECT_ENTRY_TABLE_RVA = 0x8F90C00 diff --git a/recipes/v1_0_2.py b/recipes/v1_0_2.py index 3563bc4..f53627a 100644 --- a/recipes/v1_0_2.py +++ b/recipes/v1_0_2.py @@ -11,7 +11,11 @@ CAVE_REGION = (0x826F5E8, 0x8274000) # Observer dispatcher slot — chinlan caves load this single 8-byte pointer. -HOOK_SLOT_RVA = 0x8F90C80 +# Sits just past the entry-slot table inside __DATA.__common. The old +# 0x8F90C80 landed in __DATA.__bss, which il2cpp/UnityRuntime overwrites +# during lazy init (verified crash: cave BLR X16 jumped to garbage after +# publish). __common survives publish — entry slots (0x091E91B8..) do. +HOOK_SLOT_RVA = 0x091E92B8 PROBED_HOOK_SLOT_RVA = HOOK_SLOT_RVA # Entry-cave slot table — ENTRY_SLOT_BASE_RVA + idx*8 holds each hook fn ptr.