TPV 对每次 create_global_string 生成独立字符串常量(不去重),push 存的 字段名指针与 find 传入的指针地址不同,指针 == 永假 → provider 匹配失败 → with 上下文 __mbuddy__ 注入不上(Test 9 FAIL)+ 后续 upper() 解引用 NULL 崩溃(0xC0000005)。改为 string.strcmp 内容比较,TPC/TPV 均健壮。
71 lines
2.3 KiB
Plaintext
71 lines
2.3 KiB
Plaintext
import t, c
|
|
from stdint import *
|
|
from w32.win32process import TlsAlloc, TlsGetValue, TlsSetValue
|
|
import stdlib
|
|
import stdio
|
|
import string
|
|
|
|
|
|
# Maximum provider stack depth (compiler verifies sufficiency; increase if needed)
|
|
_MAX_PROVIDER_DEPTH: t.CDefine = 32
|
|
|
|
|
|
@t.Object
|
|
class _ProviderStack:
|
|
"""Provider stack, stores pairs of field names and pointers."""
|
|
names: t.CArray[VOIDPTR, 32]
|
|
ptrs: t.CArray[VOIDPTR, 32]
|
|
top: UINT64
|
|
|
|
|
|
# TLS index (global; all threads share the same index)
|
|
_tls_index: ULONG = 0
|
|
|
|
|
|
@t.TLS
|
|
def _init_tls():
|
|
"""Initialize TLS index (executes once; subsequent calls are skipped)."""
|
|
global _tls_index
|
|
_tls_index = TlsAlloc()
|
|
|
|
|
|
def _get_stack() -> _ProviderStack | t.CPtr:
|
|
"""Obtain current thread's provider stack. Allocate one if none exists."""
|
|
_init_tls()
|
|
stack: _ProviderStack | t.CPtr = TlsGetValue(_tls_index)
|
|
if stack == None:
|
|
stack = stdlib.malloc(_ProviderStack.__sizeof__())
|
|
string.memset(stack, 0, _ProviderStack.__sizeof__())
|
|
TlsSetValue(_tls_index, stack)
|
|
return stack
|
|
|
|
|
|
def _push_provider(field_name: str, ptr: t.CPtr):
|
|
"""Push a provider (field_name, ptr) onto the stack."""
|
|
stack: _ProviderStack | t.CPtr = _get_stack()
|
|
if stack.top >= _MAX_PROVIDER_DEPTH:
|
|
stdio.printf("[with] ERROR: provider stack overflow (depth=%lu, max=%d), field '%s' not injected\n", stack.top, _MAX_PROVIDER_DEPTH, field_name)
|
|
return
|
|
stack.names[stack.top] = field_name
|
|
stack.ptrs[stack.top] = ptr
|
|
stack.top = stack.top + 1
|
|
|
|
|
|
def _pop_provider():
|
|
"""Pop the top provider entry from the stack."""
|
|
stack: _ProviderStack | t.CPtr = _get_stack()
|
|
if stack.top > 0:
|
|
stack.top = stack.top - 1
|
|
|
|
|
|
def _find_provider(field_name: str) -> t.CPtr:
|
|
"""Search for matching field_name starting from stack top.
|
|
Return associated pointer, or NULL if no match found."""
|
|
stack: _ProviderStack | t.CPtr = _get_stack()
|
|
for i in range(stack.top - 1, -1, -1):
|
|
# 字段名用 strcmp 内容比较:编译器对每次 create_global_string 生成
|
|
# 独立的字符串常量(TPV 不去重),push/find 的指针地址不同,
|
|
# 指针 == 永假会导致 provider 匹配失败(__mbuddy__ 注入不上)。
|
|
if string.strcmp((str)(stack.names[i]), field_name) == 0:
|
|
return stack.ptrs[i]
|
|
return None |