TLS学习总结

我们有知道

Immunity Debugger,OD

调试器,在调试程序时会设断在OEP(修改第一个字节0xcc)。我在想,使用什么编程技术,代码可以在OEP前被执行。在网上找了些资料,在论坛上看到许多大牛,使用静态TLS做了好多有趣的事,今天自己也来终结下,,呵呵

1. 什么是TLS?

TLS是Thread Local
Storage(线程局部存储)的简称,是一项解决多线程内部变量使用问题的技术。用于将某些数据和一特定线程关联起来,即,这些数据为关联线程所独有
(私有)。在多线程编程中, 同一个变量, 如果要让多个线程共享访问, 那么这个变量可以使用关键字volatile进行声明;
而如果一个变量不想被多个线程共享访问, 那么就应该使用TLS。

2. 如何使用TLS编程?

TLS使用非常简单, 只要对变量声明时使用__declspec(thread)修饰就可以了。例如:

__declspec(thread) int g_nData = 0;

3.多线程中使用TLS的例子(动态)
相关API

Windows TLS的API: TlsAlloc, TlsFree, TlsSetValue, TlsGetValue。(动态TLS)

● DWORD TlsAlloc(); //(若要使用动态T L S,首先必须调用TlsAlloc函数)

这个函数命令系统对进程中的位标志进行扫描,并找出一个FREE标志。然后系统将该标志从FREE改为INUSE,并且TlsAlloc返回位数组中的标志的索引。DLL(或APP)通常将该索引保存在一个全局变量中,因为它的值是每个进程而不是每个线程使用的值。

● BOOL TlsSetValue( //将一个值放入线程的数组中

DWORD dwTlsIndex,

PVOID pvTlsValue);

● PVOID TlsGetValue(DWORD dwTlsIndex); //要从线程的数组中检索一个值

● BOOL TlsFree(DWORD dwTlsIndex); //当在所有线程中不再需要保留TLS槽时

例子:
#include <windows.h>
#include "stdio.h"

#define ThreadCound 4 //创建线程个数
DWORD dwTlsIndex;

//全局变量
int iNUM_OF_CALL_COMMON=0;   
int iNUM_OF_CALL_THREAD=0;

VOID CommonFunc(VOID)
{
        LPVOID lpvData;
        // Retrieve a data pointer for the current thread.
        iNUM_OF_CALL_COMMON++;
       
        lpvData = TlsGetValue(dwTlsIndex);
        if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
                exit(0);
       
        // Use the data stored for the current thread.
    printf("common: thread %d: lpvData=%lx\n",
                GetCurrentThreadId(), lpvData);
       
        Sleep(5000);
}

DWORD WINAPI ThreadFunc(VOID)
{
        LPVOID lpvData;
       
        // Initialize the TLS index for this thread.
        iNUM_OF_CALL_THREAD++;
       
        lpvData = (LPVOID) LocalAlloc(LPTR, 256);
        if (! TlsSetValue(dwTlsIndex, lpvData))
                exit(0);
       
        printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData);
       
        CommonFunc();
       
        // Release the dynamic memory before the thread returns.
    lpvData = TlsGetValue(dwTlsIndex);
        if (lpvData != 0)
                LocalFree((HLOCAL) lpvData);
       
        return 0;
}

void main(void)
{
        DWORD dwThreadId;
        HANDLE hThread[ThreadCound];
        int i;
        //Allocate a TLS index
        if ((dwTlsIndex =TlsAlloc()) == TLS_OUT_OF_INDEXES)
        {
                exit(0);
        }
       
        for (i = 0; i<ThreadCound; i++)
        {
                hThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, &dwThreadId);
                if(hThread == NULL)
                {
                        exit(0);
                }
        }
        for (i = 0; i < ThreadCound; i++)
        {
                WaitForSingleObject(hThread, INFINITE);
        }
        TlsFree(dwTlsIndex);

printf("The nums of thread is: %d\n",iNUM_OF_CALL_THREAD);
        printf("The nums of call is: %d\n",iNUM_OF_CALL_COMMON);

}

以上是动态TLS在多线程中的使用.
而利用静态线程局部存储可以玩弄调试器甚至可以感染一些pe.
静态线程局部存储是在Windows的PE/COFF可执行文件格式中所支持的静态线程局部存储。即在PE头中数据目录表中的第10项,这一项指向的是Tls目录,Tls目录的结构如下:

IMAGE_TLS_DIRECTORY32  STRUCTStartAddressOfRawData  dd  ?EndAddressOfRawData  dd  ?AddressOfIndex 
  dd  ?AddressOfCallBacks    dd  ?SizeOfZeroFill   
dd  ?Characteristics   
dd  ?IMAGE_TLS_DIRECTORY32  ENDS比较重要的是该结构的第四项,是指向Tls
CallBack的数组,该数组里面存放了一个或多个TLS回调函数.而TLS回调函数要执行大概经历以下三个步骤:1.程序在链接时,连接器要在PE文
件的目录表创建TLS目录2.在创建线程时,PE加载器会从TEB(当前线程环境块,通过FS寄存器获取)中获取指向TLS回调函数数值的指针(TEB偏
移2Ch).3.查看TLS 回调函数数组是否为空,不为空时加载器会依次执行回调函数。
静态TLS代码;
#include "stdio.h"#include <windows.h>//告诉编译器在PE文件中要创建TLS目录#pragma
comment(linker,
"/INCLUDE:__tls_used")//TLS_CallBack()函数,第二个参数决定了函数在那种情况下(DllMain函数一样)
/*        DLL_PROCESS_ATTACH:是指新进程创建时,初始化主线程时执行       
DLL_PROCESS_DETACH: 是指在进程终止时执行       
DLL_THREAD_ATTACH:  是指创建新线程时,但是不包括主线程       
DLL_THREAD_DETACH:  是指在所有线程终止时执行,但是同样不包括主线程*/void go_anit(){       
ExitProcess(0);}void __stdcall my_tls_callback(PVOID h, DWORD reason,
PVOID pv){        //仅在进程初始化创建主线程执行        if (reason ==
DLL_PROCESS_ATTACH)        {                //检查OEP               
IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER*)GetModuleHandle(NULL); 
              IMAGE_NT_HEADERS *NtHeader =
(IMAGE_NT_HEADERS*)(((DWORD)DosHeader)+ (DWORD)DosHeader->e_lfanew); 
              BYTE *ope =
(PBYTE)(NtHeader->OptionalHeader.AddressOfEntryPoint +
(DWORD)DosHeader);                if (*ope == 0xcc)                {     
                  go_anit();                }        }}/*       
下面创建一个TLS段        ".CRT$XLB"的含义是:".CRT"表明是使用C RunTime机制 $后面的XLB中,       
X表示随机的标识        L表示TLS Callback section        B可以被换成B到Y的任意一个字母,.       
$是给连接器的。*/#pragma data_seg(".CRT$XLB")//定义多个TLS_CallBack
PIMAGE_TLS_CALLBACK p_Tls_CallBack[] = {my_Tls_CallBack1,
my_Tls_CallBack2,my_Tls_CallBack3, 0};PIMAGE_TLS_CALLBACK p_Tls_CallBack
= my_tls_callback;#pragma data_seg()void main(){        printf("Hello
TLS\n");        getchar();}
这种方法就能真真的玩弄调试器吗?显然不是的,首先我们来看下创建一个进程的过程1.打开将要在该进程中执行的映像文件。
首先操作系统找到执行的Windows映像然后创建一个内存区对象,以便后面将它映射到新的进程地址空间中。
2.创建Windows执行体进程对象。
接下来操作系统调用内部的系统函数NtCreateProcess来创建一个Windwos执行体进程对象。具体步骤是:
(1)建立EPROCESS
(2)创建初始的进程地址空间(3)初始化内核进程块KPROCESS
(4)结束进程地址空间的创建过程
(5)建立PEB
(6)完成执行体进程对象的创建过程
3.创建初始线程(栈、堆执行环境初始化及执行线程体对象)。
这时候Windows执行体进程对象已经完全建立完成,但它还没有线程所以无法执行,接下来系统调用NtCreateThread来创建一个挂起的新线程它就是进程的主线程体。

4.通知Windows子系统新进程创建了(子系统是操作系统的一部分它是一个协助操作系统内核管理用户态/客户方的一个子系统具体的进程为
Csrss.exe)。
接下来操作系统通过客户态(Kernel32.dll)给Windows子系统(Csrss)发送一个新进程线程创建的数据消息,让子系统建立自己的进程线程管理块。当
Csrss接收到该消息时候执行下面的处理:
*复制一份该进程和线程句柄
*设置进程优先级
*分配Csrss进程块
*把新进程的异常处理端口绑定到Csrss中,这样当该进程发生异常时,Csrss将会接收到异常消息
*分配和初始化Csrss线程块
*把线程插入到进程的线程列表中
*把进程插入到Csrss的线程列表中
*显示进程启动光标
5.开始执行初始线程(如果创建时候指定了线程的CREATE_SUSPENDED状态则线程暂时挂起不执行)。
到这里进程环境已经建立完毕进程中开始创建的主线程到这里获得执行权开始执行线程
6.在新进程和线程环境中完成地址空间的初始化(比如加载必须的DLL和库),然后开始到进程入口执行。
到这步实质是调用ldrInitializeThunk来初始化加载器,堆管理器NLS表TLS数组以及临界区结构,并且加载任何必须要的DLL并且用
DLL_PROCESS_ATTACH功能代码来调用各DLL入口点,最后当加载器初始化例程返回到用户模式APC分发器时进程映像开始在用户模式下执行,然后它调用线程启动函数开始执行。

操作系统会抛出一个CreateProcessEvent事件,早于Tls_CallBack函数,同时ExceptionEvent事件也是早于
Tls_callback的所以我们可以设置调试器第一次断点“系统断点” 本实验我用的Immunity Debugger调试器,
OD相似选项->调试选项->事件->设置第一次暂停于 “系统断点”  单步跟中会发现      对当前进程信息设置

file:///C:/Users/asus/AppData/Local/youdao/ynote/images
/C357E1C9D1184437819E2C6A7919ADB8/clipboard.png到此跟进,,,查了好多资料也不知道这个函数是啥
子,,求大牛指导

file:///C:/Users/asus/AppData/Local/youdao/ynote/images
/DCE533091FD64FE48C52145B1484E6F6/clipboard.png之后见call跟进,,,到ZwContiune函
数, 继续执行线程,他的一个参数是CONTEXT指针,找到Context->EIP

file:///C:/Users/asus/AppData/Local/youdao/ynote/images/2D7F6F8AC69F46B293E3ED5CC47F167E/clipboard.png出现OPE地址

file:///C:/Users/asus/AppData/Local/youdao/ynote/images/000F6F5D807640FB92E5BFC4E562AF28/clipboard.png
跟进call eax

file:///C:/Users/asus/AppData/Local/youdao/ynote/images/98213D4D5ACD48A3A6C4BF957917E3B1/clipboard.pngcall edx 则进入OEP

file:///C:/Users/asus/AppData/Local/youdao/ynote/images/6A1D98036EB64140BAEF6A1F7B67F792/clipboard.png

file:///C:/Users/asus/AppData/Local/youdao/ynote/images
/05EAE8B3357D45CCA440A3082C120B11/clipboard.png这个过程真的还很模糊,很多疑问,不知道进入OEP之
前的那些函数具体的干了啥,,,,求指导


7.png
(16.36 KB, 下载次数: 2)



8.png
(10.68 KB, 下载次数: 1)


时间: 2024-08-30 16:25:28

TLS学习总结的相关文章

【安全牛学习笔记】SSL、TLS中间人攻击

╋━━━━━━━━━━━━━━━━━╋ ┃SSL中间人攻击                                    ┃ ┃攻击者位于客户端和服务器通信链路中┃ ┃    ARP                                                  ┃ ┃    DHCP                                               ┃ ┃    修改网关                                    

【安全牛学习笔记】SSL、TLS拒绝服务攻击和补充概念

SSL/TLS拒绝服务攻击 thc-ssl-doc SSL协商加密对性能开销增加,大量握手请求会导致拒绝服务 利用SSL secure Reegotiation特性,在单一TCP连接中生成数千个SSL重连接请 求,造成服务器资源过载 与流量式拒绝服务攻击不同,thc-ssl-dos可以利用dsl线路打垮30G宽带的服务器 服务器平均处理300次/秒SSL握手请求 对SMTPS.POP3S等服务同样有效 thc-ssl-dos 192.223.209.205 2083 --accept 对策 禁用

linux基础学习第二十三天linux安全和加密之SSL\TLS协议、CA、openssl

内容: 1.通信加密类型及算法 2.TLS/SSL协议的引入及其通信过程 3.CA.数字签名的引入 4.一个安全的数据通信交换过程 5.openssl工具的使用 6.自制私有根CA过程 一.通信加密类型及算法 数据加密通信的重要性不言而喻,美国NIST,为了保证计算机的安全,提出了几个要求: (1).数据要有保密性:数据保密性和隐私性:确保信息不被别人获取,个人存储的信息不能被别人收集到: (2).完整性:包括数据完整性和系统完整性:数据完整性确保数据和程序只能以特定权限的进行授权和改变,只能授

FTP服务学习笔记之ssl/tls安全认证配置(3)

在Redhat5.8_X64bit上配置 一.实验说明 操作系统:Redhat5.8_x64bit 实验平台:VMware Workstation 实验目的:配置ftp基于ssl/tls安全认证 二.实验步骤如下: 1.安装vsftpd #yum install vsftpd #rpm -ql vsftpd #service vsftpd start #chkconfig vsftpd on 2.配置CA #cd /etc/pki/CA #mkdir certs newcerts crl #to

Lync 2010 学习(七),TLS and MTLS for Lync Server 2010

TLS:Transport Layer Security ,传输层安全协议 MTLS:Mutual Transport Layer Securit,相互传输层安全协议 OSI七层模型中网络层通过数据包的路由来进行数据包的转发,而作为网络层的上一层传输层则需要保证数据传输的完整性,同时也可以保证数据的安全性等. TLS:安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性.该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshak

Python Web学习笔记之SSL,TLS,HTTPS

一. SSL 1. SSL简介 SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持.SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装.压缩.加密等基本功能的支持. SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证.协商加密算法.交换加密密钥等. SSL协议提供的服务主要有:1)认证用户和

运维学习之加密和解密

运维学习之加密与解密: 众所周知,在网络的世界里不存在绝对的安全性.各种钓鱼网站,病毒等等危害着我们的网 络环境.所以,作为一个运维人员,在我们利用网络进行通信时,保证通信的机密性.完整性.可用性是必要的. 我们的日常生活中有以下三点威胁网络安全的行为: 1.威胁机密性的攻击行为,它的途径是窃听.嗅探.扫描和通信量分析 2.威胁完整性的攻击行为,它的途径是更改.伪装.重放.否认 3.威胁可用性的攻击行为,它的途径是拒绝服务 为应对以上问题,我们在技术和服务两方面提出了解决方案: 从技术上我们使用

kvm学习笔记

http://blog.opskumu.com/ http://blog.csdn.net/kumu_Linux http://blog.opskumu.com/kvm-notes.html#kvm- KVM十年 virtio-gpu介绍 Linode 从 Xen 升级到 KVM qemu2.7编译实战 SPICE协议的理解 海量"小文件"优化秘籍:GlusterFS 让KVM虚拟机支持console功能 利用KVMGT-kernel,实现 KVM GPU虚拟化 让KVM虚机能使用音箱

.NET线程控制快速学习01

最近,由于基础框架的整体升级,因此需要更新所有相关项目的DLL文件.这个过程存在不小的风险,因此也对发布后的生产服务器进行了密切的监控,结果还是出现了个别应用出现异常的情况,很快的占用了大量的服务器内存和CPU等资源.通过研究dump,初步发现是由于配置服务器出现单点故障,然后应用通过多线程调用相关SOA服务时出现异常,引发了ThreadAbortException异常,而且由于原有异常处理代码不够严谨,而且与异步发送报警邮件紧密结合在一起,造成线程数量的几何级增加,最终使得整个服务器不可用.这