PE学习(九)第九章:TLS 动态TLS与静态TLS
来源:互联网 发布:深入浅出java 云盘 编辑:程序博客网 时间:2024/05/04 20:36
第九章:线程局部存储
PEB,在NT中,该结构可以从进程空间的FS:[0x30]处找到,PEB描述的信息主要包括:进程状态、进程堆、PE映像信息等,其中Ldr记录了进程加载进内存的所有模块的基地址。
TLS技术:
动态线程局部存储技术、静态线程局部存储技术
OS动态申请通过四个API,静态则通过预先在PE文件中声明数据存储空间。
TlsAlloc函数一旦得到一个可用的索引值后,还会遍历进程中的每个线程,并将对应的TLS存储槽全部清0,再返回。
TlsSetValue/TlsGetValue为了速度没有参数验证的错误检查,可以传不是TlsAlloc返回的值作为参数。
TLS存储槽实际对应于TEB中TlsSlot字段,用户可以直接操作此字段
静态线程局部存储预先将变量定义在PE文件内部,一般使用.tls节存储,在Visual C++中只要如下声明
_declspec (thread) int tlsFlag = 1;
静态线程局部存储只有用于静态加载,静态连接到该DLL的其他DLL也要确保不被动态加载。
//动态TLS实例 .386 .model flat,stdcall option casemap:noneinclude windows.incinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.libMAX_THREAD_COUNT equ 4;数据段 .datahTlsIndex dd ?dwThreadID dd ?hThreadID dd MAX_THREAD_COUNT dup(0)dwCount dd ?szBuffer db 500 dup(0)szOut1 db '线程%d终止,用时:%d毫秒。',0szErr1 db '读取TLS槽数据时失败!',0szErr2 db '写入TLS槽数据时失败!',0;代码段 .code;----------; 初始化;----------_initTime proc local @dwStart pushad ;获得当前时间, ;将线程的创建时间与线程对象相关联 invoke GetTickCount mov @dwStart,eax invoke TlsSetValue,hTlsIndex,@dwStart .if eax==0 invoke MessageBox,NULL,addr szErr2,\ NULL,MB_OK .endif popad ret_initTime endp;----------; 获取用时;----------_getLostTime proc local @dwTemp pushad ;获得当前时间, ;返回当前时间和线程创建时间的差值 invoke GetTickCount mov @dwTemp,eax invoke TlsGetValue,hTlsIndex .if eax==0 invoke MessageBox,NULL,addr szErr2,\ NULL,MB_OK .endif sub @dwTemp,eax popad mov eax,@dwTemp ret_getLostTime endp;----------; 线程函数;----------_tFun proc uses ebx ecx edx esi edi,lParam local @dwCount local @tID pushad invoke _initTime ;模拟耗时操作 mov @dwCount,1000*10000 mov ecx,@dwCount .while ecx>0 dec @dwCount dec ecx .endw invoke GetCurrentThreadId mov @tID,eax invoke _getLostTime invoke wsprintf,addr szBuffer,\ addr szOut1,@tID,eax invoke MessageBox,NULL,addr szBuffer,\ NULL,MB_OK popad ret_tFun endpstart: ;通过在进程位数组中申请一个索引, ;初始化线程运行时间记录系统 invoke TlsAlloc mov hTlsIndex,eax mov dwCount,MAX_THREAD_COUNT mov edi,offset hThreadID .while dwCount>0 invoke CreateThread,NULL,0,\ offset _tFun,NULL,\ NULL,addr dwThreadID mov dword ptr [edi],eax add edi,4 dec dwCount .endw ;等待结束线程 mov dwCount,MAX_THREAD_COUNT mov edi,offset hThreadID .while dwCount>0 mov eax,dword ptr [edi] mov dwThreadID,eax push edi invoke WaitForSingleObject,eax,\ INFINITE invoke CloseHandle,dwThreadID pop edi add edi,4 dec dwCount .endw ;通过释放线程局部存储索引, ;释放时间记录系统占用的资源 invoke TlsFree,hTlsIndex end start
//静态TLS实例 .386 .model flat,stdcall option casemap:noneinclude windows.incinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.lib .dataszText db 'HelloWorldPE',0,0,0,0 ; 构造IMAGE_TLS_DIRECTORYTLS_DIR dd offset Tls1 dd offset Tls2 dd offset Tls3 dd offset TlsCallBack dd 0 dd 0Tls1 dd 0Tls2 dd 0Tls3 dd 0TlsCallBack dd offset TLS dd 0 dd 0 .data?TLSCalled db ? ;重进标志 .codestart: invoke ExitProcess,NULL RET ; 以下代码将会在.code之前执行一次TLS: ; 变量TLSCalled是一个防重进标志。正常情况下该部分代码 ; 会被执行两次,但使用了该标识后,该代码只在开始运行前 ; 执行一次 cmp byte ptr [TLSCalled],1 je @exit mov byte ptr [TLSCalled],1 invoke MessageBox,NULL,addr szText,NULL,MB_OK@exit: RET end start
静态TLS实例生成的exe需要手动修改下数据目录表
根据 .data节 800文件偏移地址 3000内存偏移,szText占10字节
所有TLS数据目录起始RVA修改为3010,大小为一个TLS数据目录大小。能170文件偏移位置修改为10 30 00 00 18 00...
0 0
- PE学习(九)第九章:TLS 动态TLS与静态TLS
- TLS
- TLS
- TLS
- TLS
- TLS
- TLS
- TLS
- TLS
- tls
- TLS
- TLS
- SSL与TLS学习
- TLS学习
- PE文件格式TLS回调
- 流水账笔记:PE文件格式(TLS)
- 线程 TLS 学习总结
- TLS学习笔记
- Linux -ps命令
- Android-selector
- 无间道之并查集
- JVM之类加载器
- UITabBarController
- PE学习(九)第九章:TLS 动态TLS与静态TLS
- Linux shell脚本编程语法基础
- Vector返回枚举的方法
- 实验4
- JAVA内存区域和GC机制
- Greedy Mouse
- LightOJ1314---Names for Babies
- xmodem ymodem zmodem协议
- 入职培训有感