2012年7月5日星期四

tls.asm


首先声明:本文搜集自网络。
tasm版本的,fasm的你就自己实现吧!
.586p
.model flat, stdcall
locals
jumps

extrn                MessageBoxA:proc
extrn                ExitProcess:proc
.data
Tls:
                     dd     offset Tls1
                     dd     offset Tls2
                     dd     offset Tls3
                     dd     offset TlsCallBack
                     dd     0
                     dd     0

Tls1                 dd     0
Tls2                 dd     0
Tls3                 dd     0
TlsCallBack          dd     offset TlsProc
                     dd     0
                     dd     0

TlsProc              proc   DllHandle:dword, reason:dword, Reserved:dword
                     cmp    reason, 1
                     jne    __skip
                     push   40h
                     push   offset mTitle
                     push   offset mText 
                     push   0
                     call   MessageBoxA
                     push   0
                     call   ExitProcess
__skip:              ret    0ch
TlsProc              endp

mText                db     "Nope, there is no code at entry point", 0
mTitle               db     "TLS", 0
                     

.code
start:
                     ret
end    start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
masm版本的:
.386
.model   flat,stdcall
option   casemap:none
include windows.inc
include user32.inc
includelib user32.lib

.code

;; 定义一个TLS节
OPTION DOTNAME
.tls  SEGMENT 
TLS_Start LABEL DWORD
 dd 0900h dup ("0")
TLS_End LABEL DWORD
.tls ENDS
OPTION NODOTNAME

;这里需要注意的是,必须要将此结构声明为PUBLIC,用于让连接器连接到指定的位置,
;其次结构名必须为_tls_uesd这是微软的一个规定。编译器引入的位置名称也如此。
PUBLIC _tls_used
_tls_used IMAGE_TLS_DIRECTORY <TLS_Start, TLS_End, dwTLS_Index, TLS_CallBackStart, 0, 0>

dwTLS_Index        dd  ?
TLS_CallBackStart  dd  TlsCallBack0
szTitle            db  "Hello TLS",0

TlsCallBack0 proc Dllhandle:LPVOID,dwReason:DWORD,lpvReserved:LPVOID  
  .if dwReason== DLL_PROCESS_ATTACH  
    invoke MessageBox,0,addr szTitle,addr szTitle,0
  .endif
  ;在这里还可以ExitProcess。
  ret
TlsCallBack0   ENDP

Start:ret
end  Start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
c/c++版本的:

#include <windows.h>
#include <winnt.h>
//下面这行告诉链接器在PE文件中要创建TLS目录
#pragma comment(linker, "/INCLUDE:__tls_used")
/*这是PIMAGE_TLS_CALLBACK()函数的原型,其中第一个和第三个参数保留,第二个参数决定函数在那种情况下*/
void NTAPI my_tls_callback(PVOID h, DWORD reason, PVOID pv)
{
/*一共有四个选项DLL_PROCESS_ATTACH、DLL_THREAD_ATTACH、DLL_THREAD_DETACH和DLL_PROCESS_DETACH。详见微软发布的《Microsoft Portable Executable and Common Object File Format Specification v8》*/
//仅在进程初始化创建主线程时执行的代码
if( reason == DLL_PROCESS_ATTACH ){
MessageBox(NULL,L"hi,this is tls callback",L"title",MB_OK);
}
return;
}
/*下面这段是创建一个tls段
".CRT$XLB"的含义是:
.CRT表明是使用C RunTime机制
$后面的XLB中
X表示随机的标识
L表示是TLS callback section
B可以被换成B到Y的任意一个字母,但是不能使用".CRT$XLA"和".CRT$XLZ"
因为".CRT$XLA"和".CRT$XLZ"是用于tlssup.obj的
*/
#pragma data_seg(".CRT$XLB")
/*如果要定义多个TLS_CallBack函数,可以把下面这句写成:
PIMAGE_TLS_CALLBACK p_thread_callback [] = {tls_callback_A, tls_callback_B, tls_callback_C,0};
其中tls_callback_B和tls_callback_C应该是你定义好的其他TLS_callBack函数
*/
PIMAGE_TLS_CALLBACK p_thread_callback = my_tls_callback;
#pragma data_seg()

int main(void)
{
MessageBox(NULL,L"hi,this is main()",L"title",MB_OK);
  return 0;
}

没有评论:

发表评论