Обратный вызов TLS, при котором вызов sprintf_s приводит к сбою - PullRequest
0 голосов
/ 24 мая 2018

Вот мой код:

#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:p_tls_callback1")
#pragma const_seg(push)
#pragma const_seg(".CRT$XLAAA")
EXTERN_C const PIMAGE_TLS_CALLBACK p_tls_callback1 = tls_start_protect;
#pragma const_seg(pop)

, и следующий фрагмент кода напрямую вызывается tls_start_protect.

    char buf[10];
    sprintf_s(buf, 10, "hello\n");

и происходит сбой.

0:000> k
 # Child-SP          RetAddr           Call Site
00 0000007c`e676eb58 00007ff6`e3b04829 AGTtest!__crtFlsGetValue+0x10 [f:\dd\vctools\crt\crtw32\misc\winapisupp.c @ 422] 
01 0000007c`e676eb60 00007ff6`e3b047f3 AGTtest!_getptd_noexit+0x1d [f:\dd\vctools\crt\crtw32\startup\tidtable.c @ 277] 
02 0000007c`e676eb90 00007ff6`e3b03737 AGTtest!_getptd+0xb [f:\dd\vctools\crt\crtw32\startup\tidtable.c @ 337] 
03 0000007c`e676ebc0 00007ff6`e3b06030 AGTtest!_LocaleUpdate::_LocaleUpdate+0x1b [f:\dd\vctools\crt\crtw32\h\setlocal.h @ 248] 
04 0000007c`e676ebf0 00007ff6`e3b02816 AGTtest!_output_s_l+0x6c [f:\dd\vctools\crt\crtw32\stdio\output.c @ 1028] 
05 0000007c`e676ef10 00007ff6`e3b028a8 AGTtest!_vsnprintf_helper+0x92 [f:\dd\vctools\crt\crtw32\stdio\vsprintf.c @ 140] 
06 0000007c`e676ef80 00007ff6`e3b025a3 AGTtest!_vsprintf_s_l+0x3c [f:\dd\vctools\crt\crtw32\stdio\vsprintf.c @ 237] 
07 0000007c`e676efc0 00007ff6`e3b0112f AGTtest!sprintf_s+0x1f [f:\dd\vctools\crt\crtw32\stdio\sprintf.c @ 216] 
08 0000007c`e676f000 00007ffb`bd6a52c8 AGTtest!tls_start_protect+0x1f [d:\repos\antidebug\agt\tls_callback.c @ 83] 
09 0000007c`e676f040 00007ffb`bd6a1577 ntdll!LdrpCallInitRoutine+0x4c
0a 0000007c`e676f0a0 00007ffb`bd7201cd ntdll!LdrpCallTlsInitializers+0x93
0b 0000007c`e676f120 00007ffb`bd75166d ntdll!LdrpInitializeProcess+0x1c99
0c 0000007c`e676f510 00007ffb`bd706d5e ntdll!_LdrpInitialize+0x4a8b9
0d 0000007c`e676f590 00000000`00000000 ntdll!LdrInitializeThunk+0xe

Аналогично семейство _vscprintf(format, args) также аварийно завершает работу в __crtFlsGetValue.

Интересно, слишком рано называть семейство printf s, до которого инициализация еще не была выполнена.Что я знаю, так это то, что обратный вызов TLS (только DLL_PROCESS_ATTACH) выполняется после 'ntdll! Ldr *' загрузки всех зависимых модулей и перед 'EOP'.

Вопрос :

  • Любая деталь об инициализации _vscprintf, делается ли это "CRT" в коде некоторых конструкторов CPP ???

  • Любое другое ограничениеTLS callback ???

  • Если мне нужно позвонить _vscprintf в TLS Callback, как?(каким-то образом я просто хочу напечатать до main)

1 Ответ

0 голосов
/ 25 мая 2018

вы используете статический связанный CRT - это видно из вашей трассировки стека.CRT со статической связью в exe инициализируется после вызова exe точки входа.но обратный вызов tls на DLL_PROCESS_ATACH вызывается до exe точки входа.в этом случае ваш статический CRT еще не инициализирован, и любой вызов этого кода CRT может привести к сбою.решение - использовать динамически связанный CRT в отдельной DLL - в этом случае он уже будет инициализирован перед обратным вызовом TLS

...