Appearance
aowlspt_il2cpp_gatetest.h
Source: abi/aowlspt_il2cpp_gatetest.h — 482 lines, 24 file-scope functions.
What this header owns
Reproduced verbatim from the header's own banner comment — these notes are frequently the only written record of why the subsystem is shaped the way it is.
text
aowlspt_il2cpp_gatetest.h -- the LIVE self-test for the token-gate layer.
WHAT THIS IS FOR
================
`aowlspt_il2cpp_gates.h` was proven in a SCRATCH PROCESS that mapped
GameAssembly.dll by hand. That is not the same claim as "it works inside
EscapeFromTarkov.exe". This header reproduces the scratch proof IN THE
CLIENT and reports a verdict to the host log.
THE CONTROL, AND WHY "IT RETURNED SOMETHING" IS NOT A TEST
==========================================================
On a token mismatch the export does not return NULL and does not abort: it
tail-calls a trap that returns MT19937-64 output. So a call that "worked"
and a call that was rejected are BOTH non-zero, and any check of the shape
`if (ret) pass;` CANNOT FAIL (CLAUDE.md 9b). The only falsifiable check is
the PAIR:
WITH the correct token -> N calls, all IDENTICAL, and equal to a value
we know independently because WE WROTE IT into
a staged receiver we allocated ourselves;
WITHOUT a token (NULL) -> N calls, at least two DIFFERENT results, which
is the MT19937-64 stream and nothing else;
WITH a CORRUPTED token -> N calls, at least two DIFFERENT results. This
is the leg that proves THIS TEST CAN FAIL: if
a deliberately wrong token still produced the
right answer, the gate is not what gates the
export and the whole verdict is INCONCLUSIVE.
Three outcomes, never two: PASS / FAIL / INCONCLUSIVE. "The gate refused to
arm" is INCONCLUSIVE, not a pass and not a failure.
WHY THIS IS SAFE TO RUN AT HOST BOOT, WITHOUT A RAID
====================================================
1. The receiver is a STATIC BUFFER IN OUR OWN DLL, zeroed, with the known
answer written at the offset the export reads. No live game object is
touched, so the test cannot be wrong about a MethodInfo layout and cannot
corrupt one. The correct answer is known because we wrote it.
2. Both exports under test return a SMALL INTEGER, not a pointer. The random
trap value is compared and discarded. NOTHING RETURNED BY A GATED EXPORT
IS EVER DEREFERENCED HERE -- which is the rule that the no-token and
corrupt-token legs would otherwise violate by construction.
3. Every leg runs under exactly ONE `aowl_p_p_seh`, never nested.
MEASURED OFFLINE FROM D:\Games\Tarkov\GameAssembly.dll (disassembly of the
export bytes themselves, not from any prose):
il2cpp_method_get_param_count @0x5B42A0
48 8B C2 mov rax, rdx ; RDX is the token (argidx 1)
48 8B D9 mov rbx, rcx ; RCX is the receiver
48 85 D2 / 74 23 test rdx,rdx / jz -> ; NULL token jumps STRAIGHT
; to the trap tail-call
41 B8 20 00 00 00 mov r8d, 0x20 ; 32 token bytes
48 8D 15 F2 05 FB 05 lea rdx, [rip+..] ; -> RVA 0x65648B0, which is
; exactly the token_rva the
; generated row records
E8 .. call memcmp / 85 C0 / 75 0A ; mismatch -> trap
0F B6 43 52 movzx eax, [rbx+0x52] ; THE READ. One byte. It is
48 83 C4 20 / 5B / C3 ; the last thing it does.
il2cpp_field_get_offset @0x5B3310 (NONCE flavour)
41 BF 98 01 00 00 mov r15d, 0x198 ; == the row's tls_slot
49 83 3C 07 00 / 74 7E ; slot EMPTY -> trap
48 8B CD / E8 DA 5F 00 00 ; deriv(nonce), and
; 0x5B33D6+0x5FDA = 0x5B93B0
; == the row's deriv_rva
41 B8 20 00 00 00 / 48 8B D0 / 48 8B CF ; memcmp(ours, deriv, 32)
85 C0 / 75 09
48 63 46 18 movsxd rax, [rsi+0x18] ; THE READ. dword, signed.
So the two staged offsets below (+0x52 byte, +0x18 dword) are MEASURED, and
three fields of the generated map (token_rva, tls_slot, deriv_rva) were
independently re-derived from the instruction stream while doing it.Constants
AOWLSPT_IL2CPP_GATETEST_HAOWL_GT_CASESAOWL_GT_EXPECT_FIELDOFFSETAOWL_GT_EXPECT_PARAMCOUNTAOWL_GT_FAILAOWL_GT_FIELD_OFFSET_OFFAOWL_GT_INCONCLUSIVEAOWL_GT_METHOD_PARAMCOUNT_OFFAOWL_GT_PASSAOWL_GT_REPS
Functions
| Signature | Line |
|---|---|
void aowl_gt_stage(void) | 105 |
void aowl_gt_raw_thunk(void* p) | 129 |
int32_t aowl_gt_raw_call(void* fn, void* recv, void* tok, uint64_t* out) | 141 |
int32_t aowl_gt_all_same(const uint64_t* v, int32_t n) | 171 |
int32_t aowl_gt_any_differ(const uint64_t* v, int32_t n) | 177 |
int32_t aowl_gt_corrupt_token(int32_t row, unsigned char* out32) | 186 |
void aowl_gt_run_case(aowl_gt_case_t* c, void* recv, uint64_t expect) | 200 |
void aowl_gt_survey(void) | 308 |
void aowl_gt_run(void) | 360 |
int32_t aowl_gt_case_count(void) | 399 |
int32_t aowl_gt_verdict(int32_t i) | 400 |
int32_t aowl_gt_pass_count(void) | 401 |
int32_t aowl_gt_fail_count(void) | 402 |
int32_t aowl_gt_inconc_count(void) | 403 |
int32_t aowl_gt_static_armed(void) | 404 |
int32_t aowl_gt_nonce_armable(void) | 407 |
int32_t aowl_gt_leaked_arms(void) | 410 |
int32_t aowl_gt_refused_count(void) | 411 |
int32_t aowl_gt_prologue_bad_count(void) | 412 |
int32_t aowl_gt_fault_count(void) | 413 |
char aowl_gt_first_refusal(void) | 414 |
int32_t aowl_gt_hex(char* out, int32_t cap, uint64_t v) | 423 |
void aowl_gt_joinhex(char* out, int32_t cap, const uint64_t* v, int32_t n) | 435 |
char aowl_gt_line(int32_t i) | 451 |

