一开始想这节的名字叫做加密TLS表,后来感觉TLS表的加密实在是有些不符合。主要是出于TLS节加密的必要性考虑。所以改成处理TLS表了。我自身喜欢把TLS利用成模糊入口点来利用。此节规划是这样的,我们先理解一下什么是TLS以及它的结构。接下来汇编一个TLS节及相关在MASM中的应用。最后,我们讲解如何修改现有的TLS以及制作TLS入口点。
什么是TLS表
这个问题最有力的参考莫过于MSDN的文档了。这种源的东西比起用我的语言归纳要清楚的多。
MSDM文档的连接为
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vclang/html/a0f1b109-c953-4079-aa10-e47f5483173d.htm
引用自MSDN
Start:
invoke MainFunc
invoke ExitProcess, 1
CommonFunc proc
LOCAL lpvData : LPVOID
LOCAL dwThreadId : DWORD
invoke TlsGetValue, dwTlsIndex
.IF eax == 0
ret
.ENDIF
mov lpvData, eax
invoke Sleep, 5000
;; 显示信息
invoke GetCurrentThread
mov dwThreadId, eax
invoke PrintLine, offset g_szOutThread, addr dwThreadId
invoke PrintLine, offset g_szOutData, addr lpvData
ret
CommonFunc endp
ThreadFunc proc
LOCAL lpvData : LPVOID
LOCAL dwThreadId : DWORD
invoke LocalAlloc, LPTR, 256
mov lpvData, eax
invoke TlsSetValue, dwTlsIndex, eax
.IF eax == 0
ret
.ENDIF
invoke GetCurrentThread
mov dwThreadId, eax
invoke PrintLine, offset g_szOutThread, addr dwThreadId
invoke PrintLine, offset g_szOutData, addr lpvData
[COLOR=Red];; 调用公共函数
invoke CommonFunc
[COLOR=Red];; 释放内存
invoke TlsGetValue, dwTlsIndex
.IF eax != 0
invoke LocalFree, lpvData
.ENDIF
ret
ThreadFunc endp
MainFunc proc
LOCAL IDThread : DWORD
LOCAL hThread[THREADCOUNT] : HANDLE
invoke TlsAlloc
.IF eax == TLS_OUT_OF_INDEXES
ret
.ENDIF
mov dwTlsIndex, eax
xor ecx, ecx
mov ebx, THREADCOUNT
CreateThreadLoop:
cmp ecx, ebx
jz EndCreateThreadLoop
push ecx
invoke CreateThread, NULL, 0, ThreadFunc, NULL, 0, addr IDThread
pop ecx
mov hThread[ecx*sizeof HANDLE], eax
inc ecx
jmp CreateThreadLoop
EndCreateThreadLoop:
xor ecx, ecx
mov ebx, THREADCOUNT
WaitThreadLoop:
cmp ecx, ebx
jz EndWaitThreadLoop
push ecx
invoke WaitForSingleObject, hThread[ecx*sizeof HANDLE], INFINITE
pop ecx
inc ecx
jmp WaitThreadLoop
[COLOR=Red];; 是否TLS索引
invoke TlsFree, dwTlsIndex
ret
EndWaitThreadLoop:
ret
MainFunc endp
PrintLine proc uses eax ebx ecx edx edi esi pFormat : LPSTR, pBuffer : LPSTR
;; it's must be include masm32.inc and masm32.lib
LOCAL szBuf[MAX_PATH] : BYTE
mov ebx, pFormat
mov edx, pBuffer
invoke wsprintf, addr szBuf, ebx, edx
invoke StdOut, addr szBuf
mov ebx, offset CRLF
invoke StdOut, ebx
ret
CRLF db 0Dh,0Ah,0
PrintLine endp
end Start
.data?
dwTLS_Index dd ?
[COLOR=Red] ;; 这里的OPTION DOTNAME的意思为让ML可以使用以“.”开头的变量,结构,联合,标号等
;; 开启这个选项也可以在ML中使用/Zm选项来启动。
OPTION DOTNAME
[COLOR=Red] ;; 定义一个TLS节
;; SEGMENT标志在ML里是用于定义一个新节。
.tls SEGMENT
TLS_Start LABEL DWORD
dd 0100h dup ("slt.")
TLS_End LABEL DWORD
.tls ENDS
OPTION NODOTNAME
.data
TLS_CallBackStart dd TlsCallBack0
TLS_CallBackEnd dd 0
g_szTitle db "Hello TLS",0
g_szInTls db "我在TLS里",0
g_szInNormal db "我在正常代码内",0
[COLOR=Red] ;; 这里需要注意的是,
;; 必须要将此结构声明为PUBLIC,用于让连接器连接到指定的位置,
;; 其次结构名必须为_tls_uesd这是微软的一个规定。编译器引入的位置名称也如此。
PUBLIC _tls_used
_tls_used IMAGE_TLS_DIRECTORY <TLS_Start, TLS_End, dwTLS_Index, TLS_CallBackStart, 0, ?>
.code
Start:
[COLOR=Red];; 在正常代码中使用
invoke MessageBox, NULL, addr g_szInNormal, addr g_szTitle, MB_OK
invoke ExitProcess, 1
ret
;; TLS的回调函数
TlsCallBack0 proc Dllhandle : LPVOID, dwReason : DWORD, lpvReserved : LPVOID
[COLOR=Red];; 这里可以判断dwReason发生的条件
mov eax, dwReason
[COLOR=Red];; 在进行加载时被调用
cmp eax, DLL_PROCESS_ATTACH
jnz ExitTlsCallBack0
invoke MessageBox, NULL, addr g_szInTls, addr g_szTitle, MB_OK
mov dword ptr[TLS_Start],0
xor eax, eax
inc eax
ExitTlsCallBack0:
ret
TlsCallBack0 ENDP
end Start
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!