发表日期: 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]
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回调函数地址的数组,进程在启动运行时,系统会逐一调用储存在该数组中的函数。
每当创建或终止进程的线程时会自动调用执行的函数。当然,创建进程的主线程的时候也会自动调用回调函数,且其执行先于EP代码。反调试技术就是利用的TLS回调函数的这一特征。
参数顺序和定义都是一样的。第一个参数表示模块句柄,第二个参数表示调用TLS回调函数的原因。
对于第二个参数Reaseon:
分别对应了这四种情况
执行效果:
分析:在创建主线程的时候,就调用了回调函数,此时的调用Reason就是1
然后创建子线程的时候,此时又调用了回调函数,此时的调用Reason就是2
之后子线程执行完毕,调用回调函数,调用Reason就是3
最后主线程执行完毕,调用回调函数,调用原因是0
如果使用的调试器是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回调函数
分析汇编可以得到程序的大致过程:
调用函数IsDebuggerPresent检测PEB.BeingDebugged成员得到是否处于调试状态。
然后测试返回值,如果没有在调试状态,那么直接跳转到retn 0xC(加个0xC是为了平衡栈,回调函数有三个参数)进行返回,如果在调试状态,则调用MessageBoxA弹出提示窗口。
其实我们可以给程序手动添加TLS回调函数,具体步骤如下:
1.

下面使用第二种进行讲解步骤
编辑PE文件头,修改对应节区头的Size of Raw Data和 Characteristics的值
Size of Raw Data你扩展了多少就增加多少
Characteristics如下图:

设置TLS表,让其指向我们增加的IMAGE_TLS_DIRECTORY结构体
设置我们的IMAGE_TLS_DIRECTORY,对照参数进行填写
例: 
然后我们先向那个TLS回调函数的地址指向的文件处写上C2 0C 00,对应汇编RETN 0C,为之后我们将程序拖入OD中添加TLS回调函数代码做准备,让其直接先返回
然后我们将这个程序载入OD中调试到TLS回调函数,添加我们的代码(对照上方我们调试程序得到的汇编),最后保存出去即可。
