CN112733093A - 基于ring3环对抗的程序行为保护方法、系统及存储介质 - Google Patents
基于ring3环对抗的程序行为保护方法、系统及存储介质 Download PDFInfo
- Publication number
- CN112733093A CN112733093A CN202110005471.1A CN202110005471A CN112733093A CN 112733093 A CN112733093 A CN 112733093A CN 202110005471 A CN202110005471 A CN 202110005471A CN 112733093 A CN112733093 A CN 112733093A
- Authority
- CN
- China
- Prior art keywords
- function
- exception
- debugging
- address
- program
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
- 238000000034 method Methods 0.000 title claims abstract description 103
- 208000032826 Ring chromosome 3 syndrome Diseases 0.000 title claims abstract description 27
- 238000003860 storage Methods 0.000 title claims abstract description 11
- 230000008569 process Effects 0.000 claims description 41
- 230000002159 abnormal effect Effects 0.000 claims description 40
- 238000012545 processing Methods 0.000 claims description 31
- 238000001514 detection method Methods 0.000 claims description 29
- 238000009826 distribution Methods 0.000 claims description 27
- 238000012544 monitoring process Methods 0.000 claims description 19
- 238000004590 computer program Methods 0.000 claims description 10
- 230000002441 reversible effect Effects 0.000 claims description 9
- 230000005540 biological transmission Effects 0.000 claims description 4
- 238000009795 derivation Methods 0.000 claims description 4
- 230000001681 protective effect Effects 0.000 abstract description 3
- 230000006870 function Effects 0.000 description 267
- 239000008186 active pharmaceutical agent Substances 0.000 description 107
- 230000006399 behavior Effects 0.000 description 47
- 238000004458 analytical method Methods 0.000 description 15
- 230000008676 import Effects 0.000 description 13
- 238000010586 diagram Methods 0.000 description 12
- 244000035744 Hura crepitans Species 0.000 description 8
- 238000005516 engineering process Methods 0.000 description 7
- 230000001960 triggered effect Effects 0.000 description 7
- 238000013461 design Methods 0.000 description 6
- 230000003068 static effect Effects 0.000 description 6
- 230000007246 mechanism Effects 0.000 description 5
- 238000002347 injection Methods 0.000 description 2
- 239000007924 injection Substances 0.000 description 2
- VLCQZHSMCYCDJL-UHFFFAOYSA-N tribenuron methyl Chemical compound COC(=O)C1=CC=CC=C1S(=O)(=O)NC(=O)N(C)C1=NC(C)=NC(OC)=N1 VLCQZHSMCYCDJL-UHFFFAOYSA-N 0.000 description 2
- 230000005856 abnormality Effects 0.000 description 1
- 230000008485 antagonism Effects 0.000 description 1
- 238000003491 array Methods 0.000 description 1
- 239000008280 blood Substances 0.000 description 1
- 210000004369 blood Anatomy 0.000 description 1
- 230000002860 competitive effect Effects 0.000 description 1
- 238000005336 cracking Methods 0.000 description 1
- 230000001351 cycling effect Effects 0.000 description 1
- 238000011161 development Methods 0.000 description 1
- 230000000694 effects Effects 0.000 description 1
- 230000000670 limiting effect Effects 0.000 description 1
- 238000004519 manufacturing process Methods 0.000 description 1
- 230000003287 optical effect Effects 0.000 description 1
- 238000011160 research Methods 0.000 description 1
- 230000000717 retained effect Effects 0.000 description 1
- 239000000126 substance Substances 0.000 description 1
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/10—Protecting distributed programs or content, e.g. vending or licensing of copyrighted material ; Digital rights management [DRM]
- G06F21/12—Protecting executable software
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/50—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems
- G06F21/55—Detecting local intrusion or implementing counter-measures
- G06F21/56—Computer malware detection or handling, e.g. anti-virus arrangements
- G06F21/566—Dynamic detection, i.e. detection performed at run-time, e.g. emulation, suspicious activities
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Computer Security & Cryptography (AREA)
- General Engineering & Computer Science (AREA)
- Computer Hardware Design (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Technology Law (AREA)
- Multimedia (AREA)
- Health & Medical Sciences (AREA)
- General Health & Medical Sciences (AREA)
- Virology (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明提供的基于ring3环对抗的程序行为保护方法、系统及存储介质,设置了两个独立保护方法,即利用异常处理链对程序实行反调试保护和通过自实现的接口调用函数对程序中需要使用的API进行隐藏;上述两种方法既可独立执行又可相互配合执行。为了防止攻击者对软件进行Inline Hook,设置了统一的函数接口,并监控函数入口处代码是否被修(即hook),根据判断情况选择性地执行不同逻辑完成函数的调用,从而绕过hook;给所有API的调用套上了一层保护膜,通过设计统一的函数接口,所有API的调用都将借用该接口实现,通过这种方法,能够很好地实现程序行为隐藏,实现行为保护。
Description
技术领域
本发明涉及软件保护领域,尤其涉及一种基于ring3环对抗的程序行为保护方法、系统及存储介质。
背景技术
软件研发具备难度高、周期长等特点,凝聚了软件开发者的心血,具备极高的商业价值。正因如此,软件存在破解、外挂等安全风险,以及同行的竞品分析风险,为此,需要研究保护软件的方法,阻止攻击者非法修改或分析软件逻辑,避免软件产品的核心技术泄露。虽然国家已经出台了相关政策保护软件开发者的合法利益,加强了公众的产权保护意识,但是仍然有攻击者针对软件产品进行分析,破解和产出外挂,从而获取巨大的经济利益。因此,技术保护是针对软件破解者最直接的保护手段。
目前攻击者对软件分析的角度一般分为两种:静态分析和动态分析。攻击者可以利用现有的一些分析工具,从软件本身出发,使用反汇编或者反编译工具对二进制程序整体的逻辑架构进行分析,对关键逻辑进行定位,理解代码逻辑。在windows平台下,攻击者静态分析的思路如下图1,从图1可知,攻击者可以从可执行文件,dll或者驱动程序入手,通过直接分析或者间接分析的手段,获取原始软件,通过原始软件内部的信息,分析出软件的实现逻辑。
动态分析主要是对程序运行时的寄存器状态,堆栈状态以及API调用进行分析,追踪数据流和代码执行逻辑,分析程序行为,主要包括动态调试与API调用监控。动态调试通过捕获程序运行时发生的各种中断或异常事件达到调试的目的,当异常发生时,系统会检测当前进程是否处于调试状态,处于调试状态时,系统会产生一个调试事件,调试器通过捕获该调试事件,获得执行自定义代码的机会。其常用的工具有IDA Pro,Ollydbg,CheatEngine,x64dbg,Windbg等。当攻击者使用动态调试和静态分析的方法无法对软件进行很好分析的时候,就会采用API监控的方式,常用的API监控思路如下图2,如图所示,通过使用一些成熟的API监控比如API monitor和WinAPIOverride等对API进行监控,或者自己编写注入工具实现无模块注入,实现监控特定函数API,获取API调用时的参数信息和返回值信息。
随着静态分析技术和动态分析技术等逆向分析技术的发展,软件开发者的利益受到了巨大的挑战,因此,如何提高软件的防护等级,保护原创软件,是非常必要的,因此研究一种程序行为保护方法。
发明内容
为了解决以上问题,本申请针对攻击者通过动态调试或API监控的方式分析程序的行为,针对windows平台下的可执行文件,研究和设计了一种基于ring3环对抗的程序行为保护方法、系统及存储介质;能有效地检测软件程序是否被进行动态的调试,很好地实现程序行为隐藏,实现行为保护。
在本申请一方面的实施例中提出了一种基于ring3环对抗的程序行为保护方法,包括以下步骤:
S1、捕捉异常事件,在自定义的异常处理链中设置检测代码,判断程序是否被调试,如果被调试,则终止程序的运行;如果未检查出是否被调试,则进行下一步;
S2、采用自实现GetModuleHandle函数获取动态链接库中dll的基地址;并根据获取到的dll的基地址,以及想获取的API函数名,利用自定义GetProcAddress函数,得到API函数的地址,并将API函数的地址按照匹配规则保存在函数向量中,隐藏API函数;
S3、设置统一函数接口,检测被调用的API函数是否被Inline Hook,若是,则绕过被Hook的代码,否则,直接调用API函数,实现有选择性地完成系统调用。
在上述实施例提供的基于ring3环对抗的程序行为保护方法中,设置了三个独立保护方法,即利用异常处理链对程序实行反调试保护和通过自实现的接口调用函数对程序中需要使用的API进行隐藏以及设置统一函数接口,检测被调用的API函数是否被InlineHook,实现有选择性地完成系统调用;上述三种方法既可独立执行又可相互配合执行。为了防止攻击者对软件进行Inline Hook,设置统一的函数接口,监控函数入口处代码是否被修(即hook),根据判断情况选择性地执行不同逻辑完成函数的调用,从而绕过hook;给所有API的调用套上了一层保护膜,通过设计统一的函数接口,所有API的调用都将借用该接口实现,通过这种方法,能够很好地实现程序行为隐藏,实现行为保护。
优选的,在S1中,捕捉异常事件时,包括如下步骤:
在异常处理链分发流程中,设置取消线程调试事件,使异常调用链接管异常;
从EXCEPTION_RECORD,CONTEXT结构中获取异常类型,异常信息以及异常上下文;
设置DR0~DR3调试寄存器的值为固定的陷阱值,在自定义的异常处理链中通过比对陷阱值,并检测异常类型和异常地址所在页的页属性进行反调试;
通过Inline Hook RtlpCallVectoredHandlers函数,先于VEH调试器接管异常,掌握代码逻辑执行流,实现代码控制,进行反调试检测。
在本实施例中,与其他常规反调试手段来阻止逆向分析者对程序的调试不同的是,引入了基于异常处理链的联合反调试框架,能针对软件断点、硬件断点和内存断点类型的断点调试进行通用性检测,调试者不论在任意时间段主动调试程序,设置软件断点、硬件断点或者是内存断点时,执行到断点位置的线程都将触发异常。
进一步优选的,在S1中依据异常处理链的分发逻辑设置联合反调试框架,实现反调试,所述异常处理链的分发逻辑包括如下步骤:
S101、系统第一次分发被调试程序发出的调试事件,如果存在调试器调用
WaitForDebugEvent函数,则WaitForDebugEvent函数会返回一个DEBUG_EVENT结构体,如果没有调试器处理调试事件,则进行下一步;
S102、系统进入异常分发处理逻辑,经过RtlDispatchException函数,进行异常处理,RtlpCallVectoredHandlers函数将异常分发给注册的VEH函数,如果无法处理异常,则进行下一步;
S103、系统继续执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数,和RtlpExecuteHandlerForException函数将异常分发给注册的SEH函数,如果无法处理异常,则进行下一步;
S104、系统再次发出被调试程序发出的调试事件,如果存在调试器,则由调试器接管,否则,则进行下一步;
S105、系统执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数和RtlExecuteHandlerForException函数将异常分发给系统处理异常的UEF函数,在分发异常给UEF函数时,会调用NtQueryInformationProcess函数,并设置函数的第二个参数ProcessInformationClass为ProcessDebugPort,判断当前进程是否被调试,如果被调试,则终止程序的运行。
在本实施例中,提供的判断程序是否被调试的判断方法中,完成联合反调试的设置以后,当攻击者在程序的任意执行时间段对代码执行流总会经过的位置下软件断点、硬件断点或者是内存断点时,由于断点本身就是一种触发异常的机制,故均会触发异常,此时调试器已经无法捕获调试事件,异常会直接经由系统的异常处理分发逻辑分发到各已经注册的异常处理函数处进行处理,按照先VEH再UEF的顺序,从而实现基于异常处理链的联合反调试功能。
在上述任意一项实施例中优选的,在S2中,采用自实现GetModuleHandle函数获取到的动态链接库中dll的基地址时,包括以下步骤:
a0、分析PEB结构,在PEB结构中偏移0x0C的位置获取PEB_LDR_DATA结构,通过该结构中存在三个LIST_ENTRY指针,得到三条包含映像以及动态链接库相关信息的双链;
a1、通过双链先获取kernel32.dll的基地址;
a2、利用获取的kernel32.dll的基地址,获得LoadLibrary函数的地址;
a3、利用LoadLibrary函数的地址获取其他的动态链接dll的基地址。
进一步优选的,在S2中,在获取API函数的地址时,采用自实现GetProcAddress函数根据得到的dll的基地址从dll的EAT中获取函数地址,包括以下步骤:
b1、解析PE格式,从可选头找到Export Table的RVA和Size;
b2、利用RVA定位到导出表PIMAGE_EXPORT_DIRECTORY中;
b3、通过解析导出表结构获取函数地址。
进一步优选的,在b3中通过解析导出表结构获取函数地址时,包括如下步骤:
b301、通过导出表中的AddressOfNames字段,得到由函数名称指针组成的数组;通过AddressOfNameOrdinals字段、得到由函数名索引组成的数组;通过AddressOfFunctions字段、得到由函数地址组成的数组;
b302、分别以函数名、函数名索引和函数地址序号为索引,得到函数地址。
在本实施例中,通过自实现GetModuleHandle和GetProcAddress获取函数地址,调用API不再是直接从IAT调用,能直接对抗IAT Hook实现监控的工具和沙箱,从IDA看二进制程序的导入表Import Table也无法再看到通过这种方式调用的API名称,能够有效实现程序行为的隐藏。
在上述任意一项实施例中优选的:在S3中,判断函数入口处代码是否被hook,根据判断情况选择性地执行不同逻辑完成函数的调用,采用如下方法:
S301、比较接口函数中参数个数,如果参数个数不为0,则回溯栈上内容,将栈上内容按照API函数的传参方式再一次push进栈中;如果参数个数为0,则直接进行下一步;
S302、从栈上取出待调用的函数地址,检测函数地址入口处代码是否被攻击者Hook;
S303、如果被hook,则绕过被hook的代码,调用API函数;否则,直接调用API函数。
在本实施例提供的判断是否需要调用API函数的方法中,让所有的API调用都经过同一个自定义的函数接口,在该函数接口处为不同的API函数传入参数,并判断函数起始地址有无被Inline Hook,并最终跳转到其他地址处执行,有效避开了沙箱的检测,隐匿了程序行为。
本发明另一方面实施例中提出的一种基于ring3环对抗的程序行为保护系统,包括反调试模块、行为隐藏模块和对抗模块;
所述反调试模块用于监测软件是否被动态调试,进行反调试保护;所述反调试模块包括异常事件捕捉单元和调试判断单元;所述异常事件捕捉单元用于捕捉异常事件;并将捕捉到的异常事件发送到调试判断单元中,进行判断;所述调试判断单元根据接收到的异常事件,在自定义的异常处理链中设置检测代码,判断程序是否被调试,如果被调试,则终止程序的运行;如果没有检查出来是否被调试,则继续运行;
所述行为隐藏模块,用于采用自实现GetModuleHandle函数获取动态链接库中dll的基地址;并根据获取到的dll的基地址,以及想获取的API函数名,利用自定义GetProcAddress函数,得到API函数的地址,并将API函数的地址按照匹配规则保存在函数向量中,隐藏API函数;供程序运行时调取;
所述对抗模块,用于设置统一函数接口,检测被调用的API函数是否被InlineHook,若是,则绕过被Hook的代码,否则,直接调用API函数,实现有选择性地完成系统调用。
进一步优选的,所述异常事件捕捉单元中用于在异常处理链分发流程中,设置取消线程调试事件,使异常调用链接管异常;包括获取异常信息子单元、反调试子单元和反调试检测子单元;
所述获取异常信息子单元,用于从EXCEPTION_RECORD,CONTEXT结构中获取异常类型,异常信息以及异常上下文;
所述反调试子单元,用于设置DR0~DR3调试寄存器的值为固定的陷阱值,在自定义的异常处理链中通过比对陷阱值,并检测异常类型和异常地址所在页的页属性进行反调试;
所述反调试检测子单元,用于通过Inline Hook RtlpCallVectoredHandlers函数,先于VEH调试器接管异常,掌握代码逻辑执行流,实现代码控制,进行反调试检测。
本申请实施例提供的基于ring3环对抗的程序行为保护系统,融合了反调试模块,行为隐藏模块和对抗模块,在基于ring3环对程序的行为提供保护。其中反调试模块从异常处理链出发,提出了一种被动的反调试框架,能有效地检测软件是否被进行动态的调试,这种方法可以在几乎不增加系统额外开销的情况下,对调试状态进行检测。
行为隐藏模块中,自实现了GetMooduleHandle接口和GetProcAddress接口,将需要用到的将API函数的地址按照匹配规则保存在函数向量中,从而达到不再调用GetModuleHandle以及GetProcAddress函数,实现API的“隐匿”调用,达到能够隐藏程序行为的效果。对抗模块在行为隐藏模块的基础上又对程序的隐秘性进行了增强。为了防止攻击者对软件进行Inline Hook,通过在函数入口地址处对代码进行修改,使其跳转到攻击者的自定义代码执行,从而分析出函数行为,设计了统一的函数接口,给所有API的调用套上了一层保护膜,通过设计统一的函数接口,所有API的调用都将借用该接口实现,通过这种方法,能够很好地实现程序行为隐藏,实现行为保护。行为隐藏和对抗模块设计方法能在ring3环阻止绝大多数行为监控工具,包括自实现的行为监控工具,且这种方法可以应用于NT以后的32位应用程序,由于64位的windows系统是兼容32位应用程序的,故也可以在64位系统上正常运行,具有很好的兼容性。
本发明另一项实施例中提出一种存储介质,所述存储介质上存储有计算机程序,所述计算机程序被处理器执行时实现上述基于ring3环对抗的程序行为保护方法的步骤。
附图说明
构成本申请的一部分的说明书附图用来提供对本发明的进一步理解,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
图1为背景技术中攻击者的静态分析思路;
图2为背景技术中常用API监控思路;
图3本申请实施例提供的基于ring3环对抗的程序行为保护系统的系统总体框架图;
图4本申请实施例提供的基于ring3环对抗的程序行为保护系统的基于异常处理链的联合反调试框架;
图5为本申请实施例中利用函数名在EAT中获取函数地址的流程图;
图6本申请实施例中获取kernel32基地址的流程图;
图7本申请实施例中对抗模块实现结构框图;
图8本申请实施例中接口函数实现流程;
图9本申请实施例中基于ring3环对抗的程序行为保护方法的流程图。
具体实施方式
下面将参考附图并结合实施例来详细说明本发明。需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。
以下详细说明均是示例性的说明,旨在对本发明提供进一步的详细说明。除非另有指明,本发明所采用的所有技术术语与本申请所属领域的一般技术人员的通常理解的含义相同。本发明所使用的术语仅是为了描述具体实施方式,而并非意图限制根据本发明的示例性实施方式。
以下为本申请中涉及到的相关术语的解释。
静态分析:是指攻击者使用反汇编或者反编译工具对二进制程序整体的逻辑架构进行分析,对关键逻辑进行定位,理解代码逻辑。
动态分析:是指对程序运行时的寄存器状态,堆栈状态以及API调用进行分析,追踪数据流和代码执行逻辑,分析程序行为,主要包括动态调试与API调用监控。
动态调试:一般分为启动调试和附加调试。启动调试指的是攻击者利用反编译或者反汇编工具直接启动软件,这种情况下,调试器为父进程;附加调试指的是攻击者先启动软件,再使用调试器附加上目标软件。
Hook技术:在系统没有调用该函数之前,钩子程序就先捕获该消息,钩子函数先得到控制权,从而执行我们自己的代码片段,常见的Hook技术包括IAT Hook,EAT Hook,Inline Hook以及异常Hook。
IAT Hook:IAT Hook的核心思想在于通过解析PE文件,找到PE的NtHeader中可选头OptionalHeader,在可选头中获取Import Table在内存中的偏移RVA以及大小,定位到Import Table,通过INT(Import Name Table)找到IAT(Import Address Table)表中的对应位置,修改对应函数地址为自定义函数地址即可。一旦某函数被IAT Hook,程序如果直接调用该函数,则会跳转到自定义的函数中执行代码,但是如果程序通过GetProcAddress动态获取该函数地址,则可以绕过IAT Hook的监控。
EAT Hook:EAT Hook是针对GetProcAddress这种动态获取函数地址进行的Hook方式,GetProcAddress通过解析对应的动态链接库dll,在可选头中获取Export Table在内存中的偏移RVA以及大小,定位到Export Table,通过Export Table中的三级索引,找到对应的函数地址,作为GetProcAddress的返回值。一旦某函数被EAT Hook,程序调用GetProcAddress获取函数地址,就会得到自定义的函数地址。
Inline Hook:Inline Hook的核心原理在于修改目标函数地址处代码的字节码为跳转类型的字节码,让代码在执行时跳转到自定义函数,最后再返回原函数的相应位置执行。这样程序无论是直接调用还是通过GetProcAddress获取函数地址后再调用,都会经过攻击者Inline Hook的位置,被监控到程序行为,但Inline Hook并不是不可绕过,可以通过判断调用函数的地址处代码是否被修改为跳转代码,从而执行不同的代码逻辑,绕过Inline Hook的检测。
异常Hook:异常Hook是通过注册异常处理链,同时引发程序在执行时触发异常,从而通过异常分发逻辑跳转到注册的自定义异常处理代码处执行。
虚拟化技术:虚拟化技术就是将基于x86汇编系统的可执行代码转化为字节码指令系统的代码,以达到保护原有指令不被轻易篡改和逆向的目的。
软件逆向:对软件进行逆向分析及研究,从而演绎并得出该软件的处理流程、内部逻辑、功能特性等要素。
SEH:即Structured Exception Handling,SEH是结构化异常处理的简称,它是一种用于处理软件和硬件异常的系统保护机制,基于某一个线程而不是进程。如果程序设置了一个__try和__except块,当程序在__try块内触发异常时,比如执行时遇到软件断点0xcc,保留当前线程的上下文数据到CONTEXT,同时保存相关的异常信息到EXCEPTION_RECORD,跳出当前执行代码逻辑,经由系统分发对应异常到注册的SEH异常处理函数对属于其的异常进行处理。如果异常触发的位置不在__try块内,则异常并不会分发到设置的SEH异常处理函数中。
VEH:即Vectored Exception Handling,VEH是向量化异常处理的简称,它是基于进程而不是线程。即不管程序的哪个线程发生异常,触发异常的线程都会保存当前执行上下文,跳出当前执行代码逻辑,经由系统分发异常到VEH设置的异常处理函数,且其代码执行优先级在调试器之后,SEH之前。
UEF:即Unhandled Exception Filter,UEF是未处理异常过滤的简称,本来每一个进程在初始化的时候会调用SetUnhandledExceptionFilter,该函数会为该进程的每一个线程注册一个统一的最高级别异常处理函数,即UEF是基于进程而不是线程。UEF的执行优先级在SEH之后,是系统处理异常的最后手段,如果UEF都无法处理异常,程序将以崩溃结束。
如图9所示,本申请一方面的实施例提供提出了一种基于ring3环对抗的程序行为保护方法,包括以下步骤:
S1、捕捉异常事件,在自定义的异常处理链中设置检测代码,判断程序是否被调试,如果被调试,则终止程序的运行;如果未检查出是否被调试,则进行下一步;
S2、采用自实现GetModuleHandle函数获取动态链接库中dll的基地址;并根据获取到的dll的基地址,以及想获取的API函数名,利用自定义GetProcAddress函数,得到API函数的地址,并将API函数的地址按照匹配规则保存在函数向量中,隐藏API函数;
S3、设置统一函数接口,检测被调用的API函数是否被Inline Hook,若是,则绕过被Hook的代码,否则,直接调用API函数,实现有选择性地完成系统调用。
如图4所示,在S1中,捕捉异常事件时,包括如下步骤:
在异常处理链分发流程中,设置取消线程调试事件,使异常调用链接管异常;
从EXCEPTION_RECORD,CONTEXT结构中获取异常类型,异常信息以及异常上下文;
设置DR0~DR3调试寄存器的值为固定的陷阱值,在自定义的异常处理链中通过比对陷阱值,并检测异常类型和异常地址所在页的页属性进行反调试;异常类型和异常信息从EXCEPTION_RECORD指针中获取,异常上下文从CONTEXT指针中获取。
通过Inline Hook RtlpCallVectoredHandlers函数,先于VEH调试器接管异常,掌握代码逻辑执行流,实现代码控制,进行反调试检测。
在本实施例中,与其他常规反调试手段来阻止逆向分析者对程序的调试不同的是,引入了基于异常处理链的联合反调试框架,能针对软件断点、硬件断点和内存断点类型的断点调试进行通用性检测,调试者不论在任意时间段主动调试程序,设置软件断点、硬件断点或者是内存断点时,执行到断点位置的线程都将触发异常。
总体框架如图4所示,引入了基于异常处理链的联合反调试框架,能针对软件断点、硬件断点和内存断点类型的断点调试进行通用性检测,是一种通用性检测框架,属于被动反调试。
在上图的联合反调试框架中,调试者不论在任意时间段主动调试程序,设置软件断点、硬件断点或者是内存断点时,执行到断点位置的线程都将触发异常,由于设置了取消线程调试事件,系统不会发出调试事件,让调试器接管代码,并按照异常处理逻辑。
程序在发生异常时都需要EXCEPTION_POINTERS、CONTEXT、CEPTION_RECORD这三个结构保存异常发生时的线程上下文状态,以便对异常进行处理。
EXCEPTION_POINTERS包含一个EXCEPTION_RECORD指针以及一个CONTEXT指针。EXCEPTION_RECORD指针指向的地址保存了异常发生时的异常类型,异常标志位,异常发生的地址等关于异常的重要信息。CONTEXT指针指向的地址保存了发生异常时寄存器的状态,在每一个异常处理函数中都需要使用EXCEPTION_POINTERS来对异常进行处理。
UEF是系统默认注册的,其执行优先级在SEH之后,是系统处理异常的最后手段,本专利通过再次调用SetUnhandledExceptionFilter,并自定义处理异常的函数,替换掉了系统默认注册的UEF。在ring3层,如果一个线程注册了VEH,SEH,以及UEF,且满足在设置的SEH块中触发异常(比如__try块),那么当异常发生时,在S1中依据异常处理链的分发逻辑设置联合反调试框架,实现反调试,所述异常处理链的分发逻辑包括如下步骤:
S101、系统第一次分发被调试程序发出的调试事件,如果存在调试器调用
WaitForDebugEvent函数,则WaitForDebugEvent函数会返回一个DEBUG_EVENT结构体,如果没有调试器处理调试事件,则进行下一步;
S102、系统进入异常分发处理逻辑,经过RtlDispatchException函数,进行异常处理,RtlpCallVectoredHandlers将异常分发给注册的VEH函数,如果无法处理异常,则进行下一步;
S103、系统继续执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数和RtlpExecuteHandlerForException将异常分发给注册的SEH函数,如果无法处理异常,则进行下一步;
S104、系统再次发出被调试程序发出的调试事件,如果存在调试器,则由调试器接管,否则,则进行下一步;
S105、系统执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数和RtlExecuteHandlerForException函数将异常分发给系统处理异常的UEF函数,在分发异常给UEF函数时,会调用NtQueryInformationProcess函数,并设置函数的第二个参数ProcessInformationClass为ProcessDebugPort,判断当前进程是否被调试,如果被调试,则终止程序的运行。
上述异常处理链的先后调用关系说明,在截断调试器捕获异常以后,系统会把异常首先分发给注册了的VEH调用链,其次是SEH调用链,最后是UEF异常处理函数。由于SEH调用链是基于线程的,且触发保护机制需要在设置好的异常块中,比如__try和__except块,使用范围有限,无法保证攻击者一定会在这个范围内进行动态调试,因此,本发明在异常处理的选择上,使用基于进程级别的VEH调用链和UEF异常处理函数。
本发明通过调用RtlAddVectoredExceptionHandler注册VEH异常处理函数,调用SetUnhandledExceptionFilter替换程序默认的UEF异常处理函数,注册属于软件开发者自己的异常调用链。
二者注册的异常处理函数的第一个参数均是EXCEPTION_POINTERS类型的指针,通过该指针,可以从EXCEPTION_RECORD指针获得发生异常时的相关信息,通过CONTEXT指针能获取发生异常时的上下文信息。完成联合反调试的设置以后,当攻击者在程序的任意执行时间段对代码执行流总会经过的位置下软件断点、硬件断点或者是内存断点时,由于断点本身就是一种触发异常的机制,故均会触发异常,此时调试器已经无法捕获调试事件,异常会直接经由系统的异常处理分发逻辑分发到各已经注册的异常处理函数处进行处理,按照先VEH再UEF的顺序,从而实现基于异常处理链的联合反调试功能。
如图6所示,在S2中,采用自实现GetModuleHandle函数获取到的动态链接库中dll的基地址时,包括以下步骤:
a0、分析PEB结构,在PEB结构中偏移0x0C的位置获取PEB_LDR_DATA结构,通过该结构中存在三个LIST_ENTRY指针,得到三条包含映像以及动态链接库相关信息的双链;
a1、通过双链先获取kernel32.dll的基地址;
a2、利用获取的kernel32.dll的基地址,获得LoadLibrary函数的地址;
a3、利用LoadLibrary函数的地址获取其他的动态链接dll的基地址。
在本实施例中,由于一个进程的映像及其动态链接库的相关信息都会保存在一个由LDR_DATA_TABLE_ENTRY结构体组成的双链当中,只需要在进程加载以后,遍历该双链即可获得想要的动态链接库相关信息。采用通过kernel32.dll可以获得LoadLibrary函数的地址,因此,本实施例通过双链先获取kernel32.dll的基地址,使用自实现的GetProcAddress找到LoadLibrary的地址,利用LoadLibrary的地址便于加载其他的动态链接库。
在32位的NT以后的系统上,fs寄存器指向TEB(Thread Environment Block),TEB用于描述一个线程的状态,在TEB偏移0x30的位置指向了PEB(Process EnvironmentBlock)结构,PEB里包含了当前进程的相关信息。在PEB偏移0x0C的位置指向了PEB_LDR_DATA结构,该结构中存在三个LIST_ENTRY指针,指向了三条包含映像以及动态链接库相关信息的双链,分别在偏移0x0C,0x14,0x1C的位置,通过这三个双链都可以找到kernel32.dll动态链接库的相关信息。
事实上,这三个双链的每一个链表节点都是LDR_DATA_TABLE_ENTRY结构体,每一个链表节点都是进程的映像,或者某个动态链接库的相关信息,只需要遍历该双链结构即可获取想要的dll相关信息,包括动态链接库的基地址、大小、名称、文件位置等等。选择偏移0x14处的双链InMemoryOrderList寻找kernel32.dll的基地址。ntdll.dll是双链中的第一个dll,kernel32.dll是双链中的第二个dll。由此可以实现通过如图6的方式获取kernel32.dll的基地址:进而得到LoadLibrary函数的地址。
如图5所示,在S2中,从如何获取API函数地址出发,自实现GetModuleHandle,获取加载的动态链接库dll的基地址,避免LoadLibrary以及GetModuleHandle等敏感API的调用;自实现GetProcAddress,用获取得到的动态链接库dll的基地址,以及想获取的API函数名,得到API函数的地址,并将API函数的地址保存在函数向量当中,当需要调用API时,直接从全局变量中获取对应函数的地址,配合后续的对抗模块进行调用。
通过自实现获取函数地址,调用API不再是直接从IAT调用,能直接对抗IAT Hook实现监控的工具和沙箱,从IDA看二进制程序的导入表Import Table也无法再看到通过这种方式调用的API名称,能够有效实现程序行为的隐藏。
在获取API函数的地址时,采用自实现GetProcAddress根据得到的dll的基地址从dll的EAT中获取函数地址,包括以下步骤:
b1、解析PE格式,从可选头找到Export Table的RVA和Size;
Import Table由多个IMAGE_IMPORT_DESCRIPTOR结构体组成,一个结构体包含需要加载的一个dll信息,完成dll的加载,并根据该结构体中的INT从dll的EAT(ExportTable)当中获取到函数的地址,并完成自身IAT表的填充,以便后续API的直接调用。自实现GetProcAddress的核心就是自实现从dll的EAT中获取函数地址的过程。
解析PE格式,从可选头找到Export Table的RVA和Size,利用RVA定位到导出表PIMAGE_EXPORT_DIRECTORY,结构如下表所示:
表一导出表结构
b2、利用RVA定位到导出表PIMAGE_EXPORT_DIRECTORY中;所述导出表中至少包括以下字段名AddressOfFunctions;AddressOfNames;和AddressOfNameOrdinals;其中,
AddressOfFunctions字段指向由函数地址组成的数组;
AddressOfNames字段指向由函数名称指针组成的数组;
AddressOfNameOrdinals字段指向由函数序号组成的数组;
b3、通过解析导出表结构获取函数地址。
在获取函数地址时,包括如下步骤:
b301、通过导出表中的AddressOfNames字段,得到由函数名称指针组成的数组;通过AddressOfNameOrdinals字段、得到由函数名索引组成的数组;通过AddressOfFunctions字段、得到由函数地址组成的数组;
b302、分别以函数名、函数名索引和函数地址序号为索引,得到函数地址。
在本实施例中,通过自实现GetModuleHandle和GetProcAddress获取函数地址,调用API不再是直接从IAT调用,能直接对抗IAT Hook实现监控的工具和沙箱,从IDA看二进制程序的导入表Import Table也无法再看到通过这种方式调用的API名称,能够有效实现程序行为的隐藏。
如图7-8所示:在S3中,判断函数入口处代码是否被hook,根据判断情况选择性地执行不同逻辑完成函数的调用,采用如下方法:
S301、比较接口函数中参数个数,如果参数个数不为0,则回溯栈上内容,将栈上内容按照API函数的传参方式再一次push进栈中;如果参数个数为0,则直接进行下一步;
S302、从栈上取出待调用的函数地址,检测函数地址入口处代码是否被攻击者Hook;
S303、如果被hook,则绕过被hook的代码,调用API函数;否则,直接调用API函数。
让所有的API调用都经过同一个自定义的函数接口,在该函数接口处为不同的API函数传入参数,并判断函数起始地址有无被Inline Hook,并最终跳转到原API函数加5的地址处执行,有效避开了沙箱的检测,隐匿了程序行为。
在步骤2中,虽然使得程序不再直接调用API,但是API的调用总归是要经过相应API的函数起始地址的,如果攻击者对软件进行Inline Hook,通过在函数入口地址处对代码进行修改,使其跳转到攻击者的自定义代码执行,则还是会被攻击者分析出程序行为。为此,步骤S3的设计能够有效地对抗此类监控,做到进一步“隐匿”程序行为。
通过设置统一的函数接口,所有API的调用都将借用该接口完成,调用函数时,程序不再执行函数入口地址处代码,而是通过统一设置的接口完成调用。接口的设置原型如下:
extern"C"DWORD callFunction(DWORD dwFunction,int n,...);
调用的API函数地址通过行为隐藏模块中的设计,在程序初始化的时候将需要用到的API地址保存在全局变量中。在调用时,取出对应全局变量中API函数的地址,带入统一函数接口callFunction的第一个参数dwFunction,其中第一个参数是调用的API函数地址,第二个参数设置为API的参数个数,后续参数设置为API的参数,根据API的不同,参数类型个数都不尽相同。接口函数的实现如图8。
在本实施例提供的判断是否需要调用API函数的方法中,让所有的API调用都经过同一个自定义的函数接口,在该函数接口处为不同的API函数传入参数,并判断函数起始地址有无被Inline Hook,并最终跳转到其他地址处执行,有效避开了沙箱的检测,隐匿了程序行为。又对程序的隐秘性进行了增强。为了防止攻击者对软件进行Inline Hook。
如图3-4所示,本发明另一方面实施例中提出的一种基于ring3环对抗的程序行为保护系统,包括反调试模块、行为隐藏模块和对抗模块;
所述反调试模块用于监测软件是否被动态调试,进行反调试保护;所述反调试模块包括异常事件捕捉单元和调试判断单元;所述异常事件捕捉单元用于捕捉异常事件;并将捕捉到的异常事件发送到调试判断单元中,进行判断;所述调试判断单元根据接收到的异常事件,在自定义的异常处理链中设置检测代码,判断程序是否被调试,如果被调试,则终止程序的运行;如果没有检查出来是否被调试,则继续运行。
所述行为隐藏模块,用于采用自实现GetModuleHandle获取动态链接库中dll的基地址;并根据获取到的dll的基地址,以及想获取的API函数名,利用自定义GetProcAddress,得到API函数的地址,并将API函数的地址按照匹配规则保存在函数向量中,隐藏API函数;供程序运行时调用。
所述对抗模块,用于设置统一函数接口,检测被调用的API函数是否被InlineHook,若是,则绕过被Hook的代码,否则,直接调用API函数,实现有选择性地完成系统调用。
如图4所示,所述异常事件捕捉单元中用于在异常处理链分发流程中,设置取消线程调试事件,使异常调用链接管异常;包括获取异常信息子单元、反调试子单元和反调试检测子单元;
所述获取异常信息子单元,用于从EXCEPTION_RECORD,CONTEXT结构中获取异常类型,异常信息以及异常上下文;
所述反调试子单元,用于设置DR0~DR3调试寄存器的值为固定的陷阱值,在自定义的异常处理链中通过比对陷阱值,并检测异常类型和异常地址所在页的页属性进行反调试;
所述反调试检测子单元,用于通过Inline Hook RtlpCallVectoredHandlers函数,先于VEH调试器接管异常,掌握代码逻辑执行流,实现代码控制,进行反调试检测。
反调试模块引入了基于异常处理链的联合反调试框架,能针对软件断点、硬件断点和内存断点类型的断点调试进行通用性检测,是一种通用性检测框架,属于被动反调试,总体框架如图4所示。
在上图的联合反调试框架中,调试者不论在任意时间段主动调试程序,设置软件断点、硬件断点或者是内存断点时,执行到断点位置的线程都将触发异常,由于设置了取消线程调试事件,系统不会发出调试事件,让调试器接管代码,并按照异常处理逻辑。
程序在发生异常时,都需要EXCEPTION_POINTERS、CONTEXT、EXCEPTION_RECORD这三个结构保存异常发生时的线程上下文状态,以便对异常进行处理。
EXCEPTION_POINTERS包含一个EXCEPTION_RECORD指针以及一个CONTEXT指针。EXCEPTION_RECORD指针指向的地址保存了异常发生时的异常类型,异常标志位,异常发生的地址等关于异常的重要信息。CONTEXT指针指向的地址保存了发生异常时寄存器的状态,在每一个异常处理函数中都需要使用EXCEPTION_POINTERS来对异常进行处理。
UEF是系统默认注册的,其执行优先级在SEH之后,是系统处理异常的最后手段,本专利通过再次调用SetUnhandledExceptionFilter,并自定义处理异常的函数,替换掉了系统默认注册的UEF。在ring3层,如果一个线程注册了VEH,SEH,以及UEF,且满足在设置的SEH块中触发异常(比如__try块),那么当异常发生时,处理的先后顺序如下:
1、系统第一次分发被调试程序发出的调试事件,如果存在调试器调用WaitForDebugEvent,WaitForDebugEvent会返回一个DEBUG_EVENT结构体,便于调试器处理线程上下文和异常信息,如果没有调试器处理调试事件,则进行下一步;
2、系统进入异常分发处理逻辑,经过RtlDispatchException,RtlpCallVectoredHandlers将异常分发给注册的VEH函数,如果无法处理异常,则进行下一步;
3、系统继续执行异常分发处理逻辑,经过KiUserExceptionDispatcher,RtlDispatchException,RtlpExecuteHandlerForException将异常分发给注册的SEH函数,如果无法处理异常,则进行下一步;
4、系统再次发出被调试程序发出的调试事件,如果存在调试器,则由调试器接管,否则,则进行下一步;
5、系统执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数和RtlExecuteHandlerForException函数将异常分发给系统处理异常的UEF函数,在分发异常给UEF函数时,会调用NtQueryInformationProcess函数,并设置函数的第二个参数ProcessInformationClass为ProcessDebugPort,判断当前进程是否被调试,如果被调试,则终止程序的运行。
本发明在系统分发异常给UEF时,通过调用NtQueryInformationProcess,并设置函数的第二个参数ProcessInformationClass为ProcessDebugPort判断当前进程是否被调试,正常运行的情况下,会通过这处代码,执行到自定义的UEF代码处,如果被调试,则终止程序的运行,从而达到反调试功能。
上述异常处理链的先后调用关系说明,在截断调试器捕获异常以后,系统会把异常首先分发给注册了的VEH调用链,其次是SEH调用链,最后是UEF异常处理函数。由于SEH调用链是基于线程的,且触发保护机制需要在设置好的异常块中,比如__try和__except块,使用范围有限,无法保证攻击者一定会在这个范围内进行动态调试,因此,本发明在异常处理的选择上,使用基于进程级别的VEH调用链和UEF异常处理函数。
本发明通过调用RtlAddVectoredExceptionHandler注册VEH异常处理函数,调用SetUnhandledExceptionFilter替换程序默认的UEF异常处理函数,注册属于软件开发者自己的异常调用链。
行为隐藏模块从如何获取API函数地址出发,自实现GetModuleHandle,获取加载的动态链接库dll的基地址,避免LoadLibrary以及GetModuleHandle等敏感API的调用;
如图6所示,通过kernel32.dll可以获得LoadLibrary函数的地址,因此,本发明通过双链先获取kernel32.dll的基地址,使用自实现的GetProcAddress找到LoadLibrary的地址,便于加载其他的动态链接库。
在32位的NT以后的系统上,fs寄存器指向TEB(Thread Environment Block),TEB用于描述一个线程的状态,在TEB偏移0x30的位置指向了PEB(Process EnvironmentBlock)结构,PEB里包含了当前进程的相关信息。在PEB偏移0x0C的位置指向了PEB_LDR_DATA结构,该结构中存在三个LIST_ENTRY指针,指向了三条包含映像以及动态链接库相关信息的双链,分别在偏移0x0C,0x14,0x1C的位置,通过这三个双链都可以找到kernel32.dll动态链接库的相关信息。
事实上,这三个双链的每一个链表节点都是LDR_DATA_TABLE_ENTRY结构体,每一个链表节点都是进程的映像,或者某个动态链接库的相关信息,只需要遍历该双链结构即可获取想要的dll相关信息,包括动态链接库的基地址、大小、名称、文件位置等等。选择偏移0x14处的双链InMemoryOrderList寻找kernel32.dll的基地址。ntdll.dll是双链中的第一个dll,kernel32.dll是双链中的第二个dll。
自实现GetProcAddress,用获取得到的动态链接库dll的基地址,以及想获取的API函数名,得到API函数的地址,并将API函数的地址保存在全局变量当中,当需要调用API时,直接从全局变量中获取对应函数的地址,配合后续的对抗模块进行调用。
通过自实现获取函数地址,调用API不再是直接从IAT调用,能直接对抗IAT Hook实现监控的工具和沙箱,从IDA看二进制程序的导入表Import Table也无法再看到通过这种方式调用的API名称,能够有效实现程序行为的隐藏。
程序在启动时,会解析自身的PE格式,从可选头找到Import Table的RVA和Size,Import Table由多个IMAGE_IMPORT_DESCRIPTOR结构体组成,一个结构体包含需要加载的一个dll信息,完成dll的加载,并根据该结构体中的INT从dll的EAT(Export Table)当中获取到函数的地址,并完成自身IAT表的填充,以便后续API的直接调用。自实现GetProcAddress的核心就是自实现从dll的EAT中获取函数地址的过程。
解析PE格式,从可选头找到Export Table的RVA和Size,利用RVA定位到导出表PIMAGE_EXPORT_DIRECTORY,结构上表1所示。
其中,AddressOfFunctions指向由函数地址组成的数组,AddressOfNames指向由函数名称指针组成的数组,AddressOfNameOrdinals指向由函数序号组成的数组,通过这三个数组获得函数地址的步骤图如图5所示具体步骤为:
1、在AddressOfNames函数名表中比较要寻找的函数名,循环NumberOfNames次,取对应函数名在AddressOfNames中的下标;
2、根据下标,在AddressOfNameOrdinals函数序号表中索引出一个序号值,大小2字节;
3、根据序号值,在AddressOfFunctions函数地址表中索引获取函数地址。
如图7-8所示,让所有的API调用都经过同一个自定义的函数接口,在该函数接口处为不同的API函数传入参数,并判断函数起始地址有无被Inline Hook,并最终跳转到原API函数加5的地址处执行,有效避开了沙箱的检测,隐匿了程序行为。
行为隐藏模块虽然使得程序不再直接调用API,但是API的调用总归是要经过相应API的函数起始地址的,如果攻击者对软件进行Inline Hook,通过在函数入口地址处对代码进行修改,使其跳转到攻击者的自定义代码执行,则还是会被攻击者分析出程序行为。为此,对抗模块的设计能够有效地对抗此类监控,做到进一步“隐匿”程序行为。
通过设置统一的函数接口,所有API的调用都将借用该接口完成,调用函数时,程序不再执行函数入口地址处代码,而是通过统一设置的接口完成调用。接口的设置原型如下:
extern"C"DWORD callFunction(DWORD dwFunction,int n,...);
调用的API函数地址通过行为隐藏模块中的设计,在程序初始化的时候将需要用到的API地址保存在全局变量中。在调用时,取出对应全局变量中API函数的地址,带入统一函数接口callFunction的第一个参数dwFunction,其中第一个参数是调用的API函数地址,第二个参数设置为API的参数个数,后续参数设置为API的参数,根据API的不同,参数类型个数都不尽相同。接口函数的实现如下图8,设置统一函数接口,判断是否需要调用API函数时,采用如下方法:通过这种方法,能够很好地实现程序行为隐藏,实现行为保护。
1、接口函数比较参数个数,如果参数个数不为0,则回溯栈上内容,将栈上内容按照API函数的传参方式再一次push进栈中;如果参数个数为0,则直接进行下一步;
2、从栈上取出待调用的函数地址,检测函数地址入口处代码是否被攻击者Hook;
3、如果被hook,则绕过被hook的代码,调用API函数;否则,直接调用API函数。
本领域内的技术人员应明白,本申请的实施例可提供为方法、系统、或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本申请是参照根据本申请实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
由技术常识可知,本发明可以通过其它的不脱离其精神实质或必要特征的实施方案来实现。因此,上述公开的实施方案,就各方面而言,都只是举例说明,并不是仅有的。所有在本发明范围内或在等同于本发明的范围内的改变均被本发明包含。
Claims (10)
1.一种基于ring3环对抗的程序行为保护方法,其特征在于,包括以下步骤:
S1、捕捉异常事件,在自定义的异常处理链中设置检测代码,判断程序是否被调试,如果被调试,则终止程序的运行;如果未检查出是否被调试,则进行下一步;
S2、采用自实现GetModuleHandle函数获取动态链接库中dll的基地址;并根据获取到的dll的基地址,以及想获取的API函数名,利用自定义GetProcAddress函数,得到API函数的地址,并将API函数的地址按照匹配规则保存在函数向量中,隐藏API函数;
S3、设置统一函数接口,检测被调用的API函数是否被Inline Hook,若是,则绕过被Hook的代码,否则,直接调用API函数,实现有选择性地完成系统调用。
2.根据权利要求1所述的基于ring3环对抗的程序行为保护方法,其特征在于,在S1中,捕捉异常事件时,包括如下步骤:
在异常处理链分发流程中,设置取消线程调试事件,使异常调用链接管异常;
从EXCEPTION_RECORD,CONTEXT结构中获取异常类型,异常信息以及异常上下文;
设置DR0~DR3调试寄存器的值为固定的陷阱值,在自定义的异常处理链中通过比对陷阱值,并检测异常类型和异常地址所在页的页属性进行反调试;
通过Inline Hook RtlpCallVectoredHandlers函数,先于VEH调试器接管异常,掌握代码逻辑执行流,实现代码控制,进行反调试检测。
3.根据权利要求2所述的基于ring3环对抗的程序行为保护方法,其特征在于:在S1中依据异常处理链的分发逻辑设置联合反调试框架,实现反调试,所述异常处理链的分发逻辑包括如下步骤:
S101、系统第一次分发被调试程序发出的调试事件,如果存在调试器调用
WaitForDebugEvent函数,则WaitForDebugEvent函数会返回一个DEBUG_EVENT结构体,如果没有调试器处理调试事件,则进行下一步;
S102、系统进入异常分发处理逻辑,经过RtlDispatchException函数,进行异常处理,RtlpCallVectoredHandlers函数将异常分发给注册的VEH函数,如果无法处理异常,则进行下一步;
S103、系统继续执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数和RtlpExecuteHandlerForException函数将异常分发给注册的SEH函数,如果无法处理异常,则进行下一步;
S104、系统再次发出被调试程序发出的调试事件,如果存在调试器,则由调试器接管,否则,则进行下一步;
S105、系统执行异常分发处理逻辑,经过KiUserExceptionDispatcher函数,RtlDispatchException函数和RtlExecuteHandlerForException函数将异常分发给系统处理异常的UEF函数,在分发异常给UEF函数时,会调用NtQueryInformationProcess函数,并设置函数的第二个参数ProcessInformationClass为ProcessDebugPort,判断当前进程是否被调试,如果被调试,则终止程序的运行。
4.根据权利要求1所述的基于ring3环对抗的程序行为保护方法,其特征在于,在S2中,采用自实现GetModuleHandle函数获取到的动态链接库中dll的基地址时,包括以下步骤:
a0、分析PEB结构,在PEB结构中偏移0x0C的位置获取PEB_LDR_DATA结构,通过该结构中存在三个LIST_ENTRY指针,得到三条包含映像以及动态链接库相关信息的双链;
a1、通过双链先获取kernel32.dll的基地址;
a2、利用获取的kernel32.dll的基地址,获得LoadLibrary函数的地址;
a3、利用LoadLibrary函数的地址获取其他的动态链接dll的基地址。
5.根据权利要求4所述的基于ring3环对抗的程序行为保护方法,其特征在于,在S2中,在获取API函数的地址时,采用自实现GetProcAddress函数根据得到的dll的基地址从dll的EAT中获取函数地址,包括以下步骤:
b1、解析PE格式,从可选头找到Export Table的RVA和Size;
b2、利用RVA定位到导出表PIMAGE_EXPORT_DIRECTORY中;
b3、通过解析导出表结构获取函数地址。
6.根据权利要求5所述的基于ring3环对抗的程序行为保护方法,其特征在于,在b3中通过解析导出表结构获取函数地址时,包括如下步骤:
通过导出表中的AddressOfNames字段,得到由函数名称指针组成的数组;
通过AddressOfNameOrdinals字段、得到由函数名索引组成的数组;
通过AddressOfFunctions字段、得到由函数地址组成的数组;
分别以函数名、函数名索引和函数地址序号为索引,得到函数地址。
7.根据权利要求1所述的基于ring3环对抗的程序行为保护方法,其特征在于:在S3中,判断函数入口处代码是否被hook,根据判断情况选择性地执行不同逻辑完成函数的调用,采用如下方法:
S301、比较接口函数中参数个数,如果参数个数不为0,则回溯栈上内容,将栈上内容按照API函数的传参方式再一次push进栈中;如果参数个数为0,则直接进行下一步;
S302、从栈上取出待调用的函数地址,检测函数地址入口处代码是否被攻击者Hook;
S303、如果被hook,则绕过被hook的代码,调用API函数;否则,直接调用API函数。
8.一种基于ring3环对抗的程序行为保护系统,其特征在于,包括反调试模块、行为隐藏模块和对抗模块;
所述反调试模块用于监测软件是否被动态调试,进行反调试保护;所述反调试模块包括异常事件捕捉单元和调试判断单元;所述异常事件捕捉单元用于捕捉异常事件;并将捕捉到的异常事件发送到调试判断单元中,进行判断;所述调试判断单元根据接收到的异常事件,在自定义的异常处理链中设置检测代码,判断程序是否被调试,如果被调试,则终止程序的运行;如果没有检查出来是否被调试,则继续运行;
所述行为隐藏模块,用于采用自实现GetModuleHandle函数获取动态链接库中dll的基地址;并根据获取到的dll的基地址,以及想获取的API函数名,利用自定义GetProcAddress函数,得到API函数的地址,并将API函数的地址按照匹配规则保存在函数向量中,隐藏API函数;供程序运行时调取;
所述对抗模块,用于设置统一函数接口,检测被调用的API函数是否被Inline Hook,若是,则绕过被Hook的代码,否则,直接调用API函数,实现有选择性地完成系统调用。
9.根据权利要求8所述的基于ring3环对抗的程序行为保护系统,其特征在于,所述异常事件捕捉单元中用于在异常处理链分发流程中,设置取消线程调试事件,使用自定义异常调用链接管异常;包括获取异常信息子单元、反调试子单元和反调试检测子单元;
所述获取异常信息子单元,用于从EXCEPTION_RECORD,CONTEXT结构中获取异常类型,异常信息以及异常上下文;
所述反调试子单元,用于设置DR0~DR3调试寄存器的值为固定的陷阱值,在自定义的异常处理链中通过比对陷阱值,并检测异常类型和异常地址所在页的页属性进行反调试;
所述反调试检测子单元,用于通过Inline Hook RtlpCallVectoredHandlers函数,先于VEH调试器接管异常,掌握代码逻辑执行流,实现代码控制,进行反调试检测。
10.一种存储介质,其特征在于,所述存储介质上存储有计算机程序,所述计算机程序被处理器执行时实现如权利要求1至7中任一项所述基于ring3环对抗的程序行为保护方法的步骤。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202110005471.1A CN112733093B (zh) | 2021-01-04 | 2021-01-04 | 基于ring3环对抗的程序行为保护方法、系统及存储介质 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202110005471.1A CN112733093B (zh) | 2021-01-04 | 2021-01-04 | 基于ring3环对抗的程序行为保护方法、系统及存储介质 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN112733093A true CN112733093A (zh) | 2021-04-30 |
CN112733093B CN112733093B (zh) | 2024-03-12 |
Family
ID=75590858
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202110005471.1A Active CN112733093B (zh) | 2021-01-04 | 2021-01-04 | 基于ring3环对抗的程序行为保护方法、系统及存储介质 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN112733093B (zh) |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN113760770A (zh) * | 2021-09-14 | 2021-12-07 | 上海观安信息技术股份有限公司 | 基于自动静态资源检测的反调试方法和系统 |
CN113810431A (zh) * | 2021-11-19 | 2021-12-17 | 北京云星宇交通科技股份有限公司 | 一种基于Hook的交通物联网终端安全检测方法和系统 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102831054A (zh) * | 2012-06-30 | 2012-12-19 | 华为技术有限公司 | 程序断点处理方法及装置 |
CN103116715A (zh) * | 2013-03-01 | 2013-05-22 | 中标软件有限公司 | Windows平台可执行文件API延迟导入保护方法 |
CN109117201A (zh) * | 2018-07-05 | 2019-01-01 | 武汉斗鱼网络科技有限公司 | 一种程序退出的方法及相关设备 |
CN111352842A (zh) * | 2020-02-28 | 2020-06-30 | 成都金诺信高科技有限公司 | 基于嵌入式的软件调试方法 |
-
2021
- 2021-01-04 CN CN202110005471.1A patent/CN112733093B/zh active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102831054A (zh) * | 2012-06-30 | 2012-12-19 | 华为技术有限公司 | 程序断点处理方法及装置 |
CN103116715A (zh) * | 2013-03-01 | 2013-05-22 | 中标软件有限公司 | Windows平台可执行文件API延迟导入保护方法 |
CN109117201A (zh) * | 2018-07-05 | 2019-01-01 | 武汉斗鱼网络科技有限公司 | 一种程序退出的方法及相关设备 |
CN111352842A (zh) * | 2020-02-28 | 2020-06-30 | 成都金诺信高科技有限公司 | 基于嵌入式的软件调试方法 |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN113760770A (zh) * | 2021-09-14 | 2021-12-07 | 上海观安信息技术股份有限公司 | 基于自动静态资源检测的反调试方法和系统 |
CN113810431A (zh) * | 2021-11-19 | 2021-12-17 | 北京云星宇交通科技股份有限公司 | 一种基于Hook的交通物联网终端安全检测方法和系统 |
Also Published As
Publication number | Publication date |
---|---|
CN112733093B (zh) | 2024-03-12 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
Huang et al. | From system services freezing to system server shutdown in android: All you need is a loop in an app | |
EP2979219B1 (en) | Suspicious program detection | |
JP4518564B2 (ja) | 不正コード実行の防止方法、不正コード実行の防止用プログラム、及び不正コード実行の防止用プログラムの記録媒体 | |
US7971255B1 (en) | Detecting and preventing malcode execution | |
US7603713B1 (en) | Method for accelerating hardware emulator used for malware detection and analysis | |
Quist et al. | Visualizing compiled executables for malware analysis | |
CN112733093B (zh) | 基于ring3环对抗的程序行为保护方法、系统及存储介质 | |
Sun et al. | A native apis protection mechanism in the kernel mode against malicious code | |
D’Elia et al. | Designing robust API monitoring solutions | |
Kawakoya et al. | Api chaser: Taint-assisted sandbox for evasive malware analysis | |
Nadim et al. | Characteristic features of the kernel-level rootkit for learning-based detection model training | |
Kim et al. | Large-scale analysis on anti-analysis techniques in real-world malware | |
D’Elia et al. | Rope: Covert multi-process malware execution with return-oriented programming | |
CN113760770A (zh) | 基于自动静态资源检测的反调试方法和系统 | |
Zeng et al. | Tailored application-specific system call tables | |
Filho et al. | Evasion and countermeasures techniques to detect dynamic binary instrumentation frameworks | |
Gupta et al. | Dynamic code instrumentation to detect and recover from return address corruption | |
Shields | Anti-debugging–a developers view | |
Rousseau | Hijacking. net to defend powershell | |
Gao et al. | Debugging classification and anti-debugging strategies | |
Kirmani et al. | Analyzing detection avoidance of malware by process hiding | |
Qi et al. | SPAD: Software Protection Through Anti-Debugging Using Hardware-Assisted Virtualization. | |
Han et al. | AIFD: A runtime solution to buffer overflow attack | |
Gozzini | PINvader: a dynamic analysis tool for evasive techniques detection and bypass in 64-bit windows binaries | |
Bova | An evaluation of anti-evasion techniques implemented in malware analysis sandboxes and debuggers |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |