偃师小程序制作【偃师企业邮箱】偃师网站外包、偃师微信商城开发、偃师网店美工、偃师淘宝设计-网站优化-网站建设【企业网站制作|网页设计】- 高端网站建设 - 书生商友信息科技-

全国热线:400-111-6878

网站建设推广专家

偃师小程序制作【偃师企业邮箱】偃师网站外包、偃师微信商城开发、偃师网店美工、偃师淘宝设计

发表日期: 2021-04-30 09:57:11 浏览次数:145

偃师小程序制作【偃师企业邮箱】偃师网站外包、偃师微信商城开发、偃师网店美工、偃师淘宝设计


偃师区,隶属于河南省洛阳市,位于河南省西部,总面积668.58平方千米 [1]  。截至2019年末,偃师区总人口63.2万人 [3]  ,截至2020年6月,偃师区下辖4个街道、9个镇 [2]  ,偃师区人民政府驻槐新街道民主路27号。 [24] 

周,设偃师县。1993年,偃师撤县设市。 [4]  2021年3月,撤销县级偃师市,设立洛阳市偃师区 [25]  。偃师区是河南省制造业高质量发展综合评价试点市 [5]  、革命文物保护利用片区分县 [6]  、国家卫生城市(区)。 [18] 

2019年,偃师区实现地区生产总值443.6亿元,固定资产投资193.8亿元,一般公共预算收入24.6亿元,社会消费品零售总额222.6亿元。 [7] 


TLS回调函数学习

一:TLS

Thread Local Storage,线程局部存储:各线程独立的数据存储空间。使用TLS技术可以在线程内部独立使用或修改进程的全局数据或静态数据, 就像对待自身的局部变量一样

 

TLS回调函数常用于反调试,主要是利用了TLS回调函数的调用要先于EP代码的执行

 

如果开启了TLS功能,PE文件头就会设置TLS表,IMAGE_NT_HEADERS-IMAGE_OPTIONAL_HEADER-IMAGE_DATA_DIRECTORY[9]描述了IMAGE_TLS_DIRECTORY结构体的位置。

 

IMAGE_TLS_DIRECTORY:

 

图片描述
对其中各参数的描述:

 

StartAddressOfRawData:tls模板在内存中的起始VA,模板是用于创建线程时初始化TLS数据的,可以看到模板中的内容其实就是TLS中创建的变量

 

EndAddressOfRawDataL:tls模板在内存中的结束VA

 

AddressOfIndex:存储TLS索引的位置

 

AddressOfCallBacks: 指向TLS注册的回调函数的函数指针(地址)数组

 

SizeOfZeroFill:用于指定非零初始化数据后面的空白空间的大小

 

Characteristics:属性

 

逆向过程中比较重要的成员就是AddressOfCallBacks,指向含有TLS回调函数地址的数组,进程在启动运行时,系统会逐一调用储存在该数组中的函数。

二:TLS回调函数

每当创建或终止进程的线程时会自动调用执行的函数。当然,创建进程的主线程的时候也会自动调用回调函数,且其执行先于EP代码。反调试技术就是利用的TLS回调函数的这一特征。

 

图片描述
参数顺序和定义都是一样的。第一个参数表示模块句柄,第二个参数表示调用TLS回调函数的原因。

 

对于第二个参数Reaseon:

 

图片描述
分别对应了这四种情况

三:实例(体会TLS回调函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <windows.h>
 
#pragma comment(linker, "/INCLUDE:__tls_used")//告知链接器使用TLS
 
void print_console(char* szMsg) //定义一个函数来向控制台打印字符串
{
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    //先于主线程调用执行的TLS回调函数中使用printf可能会发生Runtime Error,可直接调用WriteConsole API
    WriteConsoleA(hStdout, szMsg, strlen(szMsg), NULL, NULL);
}
 
void NTAPI TLS_CALLBACK1(PVOID DllHandle, DWORD Reason, PVOID Reserved)//第一个回调函数
{
    char szMsg[80= {0,};
    wsprintfA(szMsg, "TLS_CALLBACK1() : DllHandle = %X, Reason = %d\n", DllHandle, Reason);//wsprintfA宽字节的sprintf
    print_console(szMsg);
}
 
void NTAPI TLS_CALLBACK2(PVOID DllHandle, DWORD Reason, PVOID Reserved)//第二个回调函数
{
    char szMsg[80= {0,};
    wsprintfA(szMsg, "TLS_CALLBACK2() : DllHandle = %X, Reason = %d\n", DllHandle, Reason);
    print_console(szMsg);
}
/*
    注册TLS函数
    .CRT$XLX的作用
    CRT表示使用C Runtime 机制
    X表示表示名随机
    L表示TLS Callback section
    X也可以换成B~Y任意一个字符
*/
#pragma data_seg(".CRT$XLX") //共享数据区
    //存储回调函数地址
    PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { TLS_CALLBACK1, TLS_CALLBACK2, 0 };
#pragma data_seg()
 
DWORD WINAPI ThreadProc(LPVOID lParam)
{
    print_console("ThreadProc() start\n");
 
    print_console("ThreadProc() end\n");
 
    return 0;
}
 
int main(void)
{
    HANDLE hThread = NULL;
 
    print_console("main() start\n");
    //创建子线程
    hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    //等待子线程结束
    WaitForSingleObject(hThread, 60*1000);
    CloseHandle(hThread);
 
    print_console("main() end\n");
 
    return 0;
}

执行效果:

 

图片描述

 

分析:在创建主线程的时候,就调用了回调函数,此时的调用Reason就是1

 

然后创建子线程的时候,此时又调用了回调函数,此时的调用Reason就是2

 

之后子线程执行完毕,调用回调函数,调用Reason就是3

 

最后主线程执行完毕,调用回调函数,调用原因是0

四:调试TLS回调函数

如果使用的调试器是WinDbg,那么默认情况下它就会在系统启动断点(System Startup Breakpoint)处暂停。而像OD这种默认就会在程序的EP处暂停。

 

下面是设置OD在系统启动断点处暂停。
图片描述

 

然后将程序拖入

 

就会暂停在此处

 

图片描述
然后我们通过查看IMAGE_TLS_DIRECTORY结构体的AddressOfCallbacks查看TLS回调函数的地址

 

从而在对应的函数地址处下断点

 

图片描述

 

查看发现在rdata节区

 

图片描述
图片描述

 

文件偏移为791C

 

图片描述

 

这个值是以IMAGE_OPTIONAL_HAEDER中的IMAGE_BASE的值为基地址的VA,现在我们查看默认的image_base:

 

图片描述
其实一般都是0x400000

 

然后我们相减得到RVA为0x8114,转换为文件偏移为0x6714:

 

如下:
图片描述

 

然后我们在OD中ctrl+G跳转过去下断点:

 

图片描述

 

然后运行即可调试我们的TLS回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
00401000    55              push ebp
00401001    8BEC            mov ebp,esp
00401003    FF15 04804000   call dword ptr ds:[<&KERNEL32.IsDebugger>; KERNEL32.IsDebuggerPresent
00401009    85C0            test eax,eax
0040100B    74 1C           je XHelloTls.00401029
0040100D    6A 00           push 0x0
0040100F    68 8C924000     push HelloTls.0040928C                   ; ASCII "TLS Callback"
00401014    68 9C924000     push HelloTls.0040929C                   ; ASCII "Debugger Detected!"
00401019    6A 00           push 0x0
0040101B    FF15 E8804000   call dword ptr ds:[<&USER32.MessageBoxA>>; USER32.MessageBoxA
00401021    6A 01           push 0x1
00401023    FF15 00804000   call dword ptr ds:[<&KERNEL32.ExitProces>; KERNEL32.ExitProcess
00401029    5D              pop ebp
0040102A    C2 0C00         retn 0xC

分析汇编可以得到程序的大致过程:

 

调用函数IsDebuggerPresent检测PEB.BeingDebugged成员得到是否处于调试状态。

 

然后测试返回值,如果没有在调试状态,那么直接跳转到retn 0xC(加个0xC是为了平衡栈,回调函数有三个参数)进行返回,如果在调试状态,则调用MessageBoxA弹出提示窗口。

 

其实我们可以给程序手动添加TLS回调函数,具体步骤如下:

 

1.

 

图片描述

 

下面使用第二种进行讲解步骤

  1. 编辑PE文件头,修改对应节区头的Size of Raw Data和 Characteristics的值

Size of Raw Data你扩展了多少就增加多少

 

Characteristics如下图:

 

图片描述

  1. 设置TLS表,让其指向我们增加的IMAGE_TLS_DIRECTORY结构体

  2. 设置我们的IMAGE_TLS_DIRECTORY,对照参数进行填写

例: 图片描述

 

然后我们先向那个TLS回调函数的地址指向的文件处写上C2 0C 00,对应汇编RETN 0C,为之后我们将程序拖入OD中添加TLS回调函数代码做准备,让其直接先返回

 

然后我们将这个程序载入OD中调试到TLS回调函数,添加我们的代码(对照上方我们调试程序得到的汇编),最后保存出去即可。


微信图片_20210425092605.jpg


偃师小程序制作偃师企业邮箱偃师网站外包、偃师微信商城开发、偃师网店美工、偃师淘宝设计

上一条:偃师网站优化【偃师开通400电话】偃师网站搭建、偃师微信公众号推文外包、偃师开通京东拼多多设计、偃师淘宝装修
下一条:偃师企业微信公众号小程序开发公司、偃师企业网页设计方案、偃师做网站开发价格、偃师微信公众号制作运营报价明细表、偃师网站设计公司费用、偃师网站推广大概需要多少钱
网站制作
小程序制作
网站优化
网站开发
400电话办理
网络推广
网站建设
网店装修
微信公众号开发
网页设计
网络公司
域名企业邮箱
服务器空间
网站案例报价
百科问答
编辑排版美工
App软件开发
百度推广
代运营托管
logo设计
网络全网营销
网站备案
网站定制
小程序开发公司
首页
电话
立即预约