这是我的代码:
#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
的系列为时尚早,在此之前,还没有进行初始化。我所知道的是,在'ntdll!Ldr *'加载所有相关模块之后和'EOP'之前执行TLS回调(仅DLL_PROCESS_ATTACH
)。
问题:
有关_vscprintf
初始化的任何细节,是由某些CPP构造函数代码中的“CRT”完成的吗?
TLS回调的任何其他限制???
如果我确实需要在TLS回调中调用_vscprintf
,该怎么办? (不知何故,我只想在main
)之前打印
答案 0 :(得分:1)
您使用静态链接的CRT - 从堆栈跟踪中可以看到这一点。在调用>> exe入口点之后初始化的静态链接CRT。但是在 exe入口点之前调用DLL_PROCESS_ATACH
上的回调。在这种情况下,您的静态 CRT尚未初始化,并且对此CRT代码的任何调用都可能会崩溃。解决方案 - 在单独的DLL中使用动态链接的CRT - 在这种情况下,它已经在TLS回调之前初始化