Skip to content

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_H
  • AOWL_GT_CASES
  • AOWL_GT_EXPECT_FIELDOFFSET
  • AOWL_GT_EXPECT_PARAMCOUNT
  • AOWL_GT_FAIL
  • AOWL_GT_FIELD_OFFSET_OFF
  • AOWL_GT_INCONCLUSIVE
  • AOWL_GT_METHOD_PARAMCOUNT_OFF
  • AOWL_GT_PASS
  • AOWL_GT_REPS

Functions

SignatureLine
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

aoughwl — self-hosted platform for things n stuff. Contact / Support on Discord for access to the private backends.