"""The kill switch: resp+0x17c. userInfo deser base is resp+0xd8, so the byte is userInfo_struct + 0xa4. Find (a) its default in the userInfo init FUN_18010ea80 and (b) which atom writes it in the userInfo deser FUN_18013ec10. WHY IT MATTERS: the response ctor defaults tradingEnabled (resp+0x50) to 1, yet model+0x1fd2e reads 0 live while we serve {"configs": []}. The settings deser only touches resp+0x50 via atom 0x336, which we never send. The ONLY other writer is if (*(char *)(resp + 0x17c) != 0) *(u32 *)(resp + 0x50) = 0; at the tail of FUN_180174630. So that branch is taken. Something sets +0x17c. CONTROL for the offset arithmetic: resp+0x2f4 has ctor default 1 and is read by the callback as *(u8*)(resp+0x2f4); the outer parser sets it to 0 in case 0x2cf. That is an independently visible byte field in the same object, confirming that single-byte fields in this struct are addressed exactly the way I am reading +0x17c. """ import traceback for a, tag in [(0x18010ea80, "userInfo sub-struct init (resp+0xd8)"), (0x18013ec10, "userInfo deserialiser")]: try: s = dec(a, 300) print("\n\n########## %#x %s len=%d ##########" % (a, tag, len(s))) print(s) except Exception: traceback.print_exc()