利用TLS添加运行前代码

TLS即线程局部存储的结构定义如下
typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD   StartAddressOfRawData;
    DWORD   EndAddressOfRawData;
    DWORD   AddressOfIndex;             // PDWORD
    DWORD   AddressOfCallBacks;         // PIMAGE_TLS_CALLBACK *
    DWORD   SizeOfZeroFill;
    DWORD   Characteristics;
} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;

其中主要关心的就是第4个参数,这个参数指向一个数组,数组中每个元素都是一个函数指针,并以一个NULL为结尾
函数原型为 
typedef VOID (NTAPI *PIMAGE_TLS_CALLBACK)(PVOID DllHandle, DWORD Reason, PVOID Reserved);
第一个参数顾名思义即为Dll句柄即模块句柄
第二个参数即表示调用该函数的时机,分别对应以下几个值:
DLL_PROCESS_DETACH    0    进程将要被终止,包括第一个线程
DLL_PROCESS_ATTACH    1    启动了一个新进程,包括第一个线程
DLL_THREAD_ATTACH      2    创建了一个新线程。创建所有线程时都会发送这个通知,除第一个线程外
DLL_THREAD_DETACH      3    线程将要被终止。终止所有线程时都会发送这个通知,除第一个线程外
第三个预留,为0
在程序加载进入OEP前,会按函数指针数组中地址顺序依次调用其函数(当然退出时也会),这可以利用到加壳脱壳等安全方面中
在程序中定义如上结构后,一般只初始化函数指针数组为有意义的值,其他值可都用初始化为0的值初始化
在定义完成生成程序后还要手动修改TLS数据目录使其指向你定义的TLS结构

下面分别贴上WIN32汇编和C的应用代码
/
;------------------------
; 静态TLS演示
; 戚利
; 2010.2.28
;------------------------
    .386
    .model flat,stdcall
    option casemap:none

include    windows.inc
include    user32.inc
includelib user32.lib
include    kernel32.inc
includelib kernel32.lib

    .data

szText  db 'HelloWorldPE',0,0,0,0  

; 构造IMAGE_TLS_DIRECTORY

TLS_DIR     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 TLS
            dd     0
            dd     0

    .data?

TLSCalled db ?   ;重进标志

    .code

start:
 
    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  
/


#include <windows.h>
void  _Tls( );

typedef struct
{
DWORD start;
DWORD end;
DWORD index;
DWORD call;
DWORD a;
DWORD b;
}TLS_DIR;

DWORD tls1=0;
DWORD tls2=0;
DWORD tls3=0;
DWORD t[2]={ _Tls, 0 };

//DWORD x=0;
TLS_DIR tls = {
        &tls1,
&tls2,
&tls3,
t,
0,
0
};




int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     MessageBox (NULL, TEXT ("Hello"), TEXT ("HelloMsg"), 0) ;
     return 0 ;
}

void  _Tls( )
{
TCHAR s[20];
TCHAR a[]=L"%d %d %d";
wsprintf(s,a,tls1,tls2,tls3);
MessageBox(0,s,0,0);
wsprintf(s,L"%X,%X,%X",&tls1,&tls2,&tls3);
MessageBox(0,s,0,0);
//_asm ret
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值