2017-09-21 4 views
0

J'ai produit une liste d'assembleur de mon fichier source .C. Et dans la source C j'ai mis en œuvre tls comme ceci:MASM ne reconnaît pas mon rappel TLS

char *msg = "callback"; 
void NTAPI tls_callback(PVOID DllHandle, DWORD dwReason, PVOID lpVd) 
{ 
    MessageBoxA(0,msg,msg,0); 

} 

#ifdef _WIN64 
#pragma comment (linker, "/INCLUDE:_tls_used") 
#pragma comment (linker, "/INCLUDE:tls_callback_func") 
#else 
#pragma comment (linker, "/INCLUDE:__tls_used") 
#pragma comment (linker, "/INCLUDE:_tls_callback_func") 
#endif 

#ifdef _WIN64 
#pragma const_seg(".CRT$XLF") 
EXTERN_C const 
#else 
#pragma data_seg(".CRT$XLF") 
EXTERN_C 
#endif 
PIMAGE_TLS_CALLBACK tls_callback_func = tls_callback; 
#ifdef _WIN64 
#pragma const_seg() 
#else 
#pragma data_seg() 
#endif 

__declspec(thread) char *tlsData = "tls static data"; 

J'ai produit liste de montage de ce fichier C, et tls maintenant ressembler à ceci:

PUBLIC [email protected] 
PUBLIC _tls_callback_func 
PUBLIC _tlsData 

_TLS SEGMENT 
_tlsData 
    DB 00H 
    DB 00H 
    DB 00H 
    DB 00H 
    DB 00H 
    DB 40H 
    DB 30H 
    DB 80H 
_TLS ENDS 
CRT$XLF SEGMENT 
_tls_callback_func DD FLAT:[email protected] 
CRT$XLF ENDS 


_TEXT SEGMENT 
_DllHandle$ = 8      ; size = 4 
_dwReason$ = 12      ; size = 4 
_lpVd$ = 16      ; size = 4 
[email protected] PROC     ; COMDAT 

    push ebp 
    mov ebp, esp 

    mov edx, DWORD PTR _msg 

    push 0 
    push edx 
    push edx 
    push 0 
    call DWORD PTR [email protected] 
; Line 34 
    pop ebp 
    ret 12     ; 0000000cH 
[email protected] ENDP 
_TEXT ENDS 

Je ne vois pas que la motif tls est produit cependant, j'ai regardé dans IDA PRO le modèle devrait être:

.rdata:004921A8 __tls_used  dd offset __tls_start 
.rdata:004921AC TlsEnd_ptr  dd offset __tls_end 
.rdata:004921B0 TlsIndex_ptr dd offset __tls_index 
.rdata:004921B4 TlsCallbacks_ptr dd offset _tls_callback_func 
.rdata:004921B8 TlsSizeOfZeroFill dd 0 
.rdata:004921BC TlsCharacteristics dd 100000h 

faire, je dois définir un nouveau segment et tls placer les boniment là-dedans? Ou il devrait être dans la section de données?

Je compilez comme ceci:

ml.exe listing.asm /coff

J'ai regardé fichier produit intérieur ida pro, et je vois que tls n'a pas été produit du tout, comment puis-je dire masm ou son agent de liaison faire un répertoire?

+0

Je n'arrive pas à trouver d'options pour l'éditeur de liens ou l'assembleur pour générer le répertoire TLS. La solution de contournement la plus rapide consiste probablement à placer la structure TLS dans un segment (section), à laisser l'éditeur de liens générer une carte de symboles et à coder un script qui lit le fichier map et corrige l'exécutable. –

+0

N'essayez jamais d'assembler et d'utiliser la sortie d'assembly du compilateur Microsoft C/C++. Je ne sais pas si c'est le cas ici, mais généralement la sortie de l'assembly générée par le compilateur Microsoft C/C++ est incomplète et incorrecte. Votre objectif est-il d'avoir un assembly ou une fonction C++ appelée en tant que rappel TLS? –

+0

@RossRidge pour utiliser les tls de l'assemblage en utilisant masm – YakibutaRamen

Répondre

2

L'éditeur de liens Microsoft utilise le symbole __tls_used (sur les systèmes x86) ou _tls_used (sur les systèmes autres que x86) comme adresse du répertoire TLS. Le répertoire TLS contient un pointeur vers un tableau terminé par zéro de rappels TLS. Ainsi, en créant un répertoire TLS approprié et en lui donnant le nom __tls_used/_tls_used, vous pouvez avoir une fonction de rappel TLS dans le code d'assemblage.

Voici un programme d'exemple qui illustre ceci:

PUBLIC __tls_used 
    PUBLIC start 

    EXTERN [email protected]:DWORD, [email protected]:DWORD, [email protected]:DWORD 

_BSS SEGMENT PUBLIC DWORD FLAT 
tls_index DD ? 
_BSS ENDS 

_RDATA SEGMENT PUBLIC PARA FLAT ALIAS('.rdata') READ 

__tls_used: 
    DD OFFSET tls_start 
    DD OFFSET tls_end 
    DD OFFSET tls_index 
    DD OFFSET tls_callbacks 
    DD tls_bss_end - tls_end 
    DD 0 ; chracterstics 

tls_callbacks: 
    DD OFFSET tls_callback 
    DD 0 

main_msg: 
    DB "Main entry called.", 13, 10 
main_msg_len = $ - main_msg 

_RDATA ENDS 

_DATA SEGMENT PUBLIC FLAT 
tls_cb_msg: 
    DB "TLS callback called. Reason: 0", 13, 10 
tls_cb_msg_len = $ - tls_cb_msg 
_DATA ENDS 


_TLS SEGMENT PUBLIC DWORD FLAT ALIAS('.tls') 
tls_start: 
    ; put initialized TLS variable definitions here 
tls_end: 
    ; put uninitialized TLS variable definitions here 
tls_bss_end: 
_TLS ENDS 

_TEXT SEGMENT PUBLIC PARA 'CODE' FLAT 
    ASSUME DS:FLAT 

tls_callback: 
    mov eax, [esp + 8] 
    add BYTE PTR [tls_cb_msg + tls_cb_msg_len - 3], al 

    push -11 ; nStdHandle 
    call [[email protected]] 

    push 0 ; lpOverlapped 
    push 0 ; lpNumberOfBytesWritten 
    pushd tls_cb_msg_len ; nNumberOfBytesToWrite 
    push tls_cb_msg ; lpBuffer 
    push eax ; hFile 
    call [[email protected]] 
    ret 12 

start: 
    push -11 ; nStdHandle 
    call [[email protected]] 

    push 0 ; lpOverlapped 
    push 0 ; lpNumberOfBytesWritten 
    pushd main_msg_len ; nNumberOfBytesToWrite 
    push main_msg ; lpBuffer 
    push eax ; hFile 
    call [[email protected]] 

    push 0 ; uExitCode 
    call [[email protected]] 
    int 3 

_TEXT ENDS 

    END start 

Notez que le code ci-dessus ne sont pas compatibles avec la mise en œuvre d'exécution Visual C++ (CRT) de TLS. Si vous envisagez de travailler avec du code C++, vous devez laisser le CRT fournir le répertoire TLS et d'autres informations. Vous pouvez lui indiquer d'utiliser un de vos rappels en mettant un pointeur sur la fonction dans la section .CRT$XL? où le point d'interrogation ? est remplacé par une lettre de B à Y. L'utilisation de la lettre B entraînera son appel avant l'appel du rappel CRT TLS. En utilisant une lettre de D à Y l'aura appelé après. Donc, le code que vous voulez serait quelque chose comme:

_CRT SEGMENT PUBLIC DWORD ALIAS('.CRT$XLD') 
    DD OFFSET my_tls_callback 
_CRT ENDS