Also der Ansatz über die Exceptions ist schonmal richtig. Fangen kannst du diese am besten, indem du einen eigenen Top-Level
Exception-Handler mit
AddVectoredExceptionHandler registrierst.
PAGE_GUARD ist allerdings denkbar ungünstig (EXTREM unperformant), weil es halt die komplette Page betrifft.
Als Alternative kannst du im betroffenen (oder allen) Thread mit
SetThreadContext die Debug Register entsprechend setzen, um einen "Hardware Breakpoint" zu aktivieren. Diese Hardware Breakpoints können je nach Wunsch durch Read, Write oder Execute getriggert werden. Nachteile gibt es allerdings auch: Du kannst maximal 4 HWBPs pro Thread setzen und die "Länge" des Breakpoints erstreckt sich nur bis maximal 4 Byte (evtl. 8 Byte unter 64-Bit, da bin ich mir grade nicht mehr sicher).