现在的位置: 首页 > 综合 > 正文

寻找黑匣子–程序行为记录与跟踪

2012年03月14日 ⁄ 综合 ⁄ 共 8546字 ⁄ 字号 评论关闭

 

. 杀不掉的QQ尾巴

来回跑了几次后,小张不由得感到一阵绝望,楼上宣传部门的一台办公电脑感染了QQ尾巴,时不时就在公司员工交流QQ群里冒出几句色情话语,而这个QQ的使用者很不巧是个年轻女孩,而且机器上安装的杀毒软件没有任何反应,于是这杀毒的重任就落到了网络部门的杀毒高手小张身上,而小张的确也不负众望的完成了任务,然而到第二天上班,这个尾巴就又回来了,甚至在每次小张刚离开回到自己办公室,就又看到了群里这个QQ发出来的尾巴。反复几次后,整个办公室的同事都认为小张是故意制造机会和那女孩接触,并借此机会进行跑楼梯的体育锻炼。小张真是有种吃黄连的感觉,自己分明是在已经确认病毒删除完毕而且重启机器也不会恢复的时候才离开的,怎么会反复出现?

这一次,在清理完尾巴重启后,小张打开进程查看工具等待半天,也没看到半个可疑程序,无奈之下他只好让那台机器的使用者坐下来进行平时的操作,而他在旁边盯着工具界面。在那个女孩迟疑的打开QQ时,进程工具里突然出现了一个陌生进程,小张紧张得差点直接用手往那女孩还在握住的鼠标上抓去了:这不是自己这些天里最咬牙切齿的文件名、一切流言蜚语的来源吗?

最后,小张找到了让他哭笑不得的“杀不掉”的尾巴源头:这个恶意程序把QQ目录下的TIMPlatform.exe给替换了,而QQ每次启动时都会加载这个程序,这样一来就等于把恶意程序又运行了一遍,无怪乎杀之不尽赶之不绝,他就差没有对天哀叹了:我又不能监视它运行时做了什么,怎么知道它还会玩这种旁门左道的损招?

随着时代变迁和技术发展,如今的后门和恶意程序早已不再是一般用户能够发现和查杀的普通用户层应用程序了,这也让一些所谓的维护人员成了专业重装系统员,因为他们的工作已经不能像过去那样依靠一两张防病毒产品光盘就可以坐享其成了,即使在大量安全工具的配合下,查杀一个后门也必须要有足够的实际经验和知识,否则他们根本连个影子都找不出来。至于市面上的反病毒产品,在如今众多恶意程序的攻势下也渐渐力不从心,例如前不久闹得轰轰烈烈的AV终结者,就让用户经历了一次莫名其妙的灭顶之灾。然而事实上,AV终结者更像是个手下留情的测试作品,因为它实际上并未采用高级的技术来进行破坏和保护自己不被发现,否则,这就真的是一次灭顶之灾了。

但是,无论技术手段多么高级的恶意程序,它都首先需要在用户的机器上成功运行起来,然后按照设计的思路,释放文件、打开驱动、注入进程、改写注册表等,如果我们能将这些步骤记录下来,那么我们不也就能完整的发现恶意程序的所有操作,并有很大的机会把它对系统做的破坏操作给恢复了吗?

. 黑匣子的原理

对于一般用户而言,一个程序从开始运行直到结束,这期间内都做过什么,并不是我们需要关心的事情,他们只要听到播放器里的音乐、看到电影画面、和远方的朋友用通讯工具聊天就可以了,有谁会去关心从用户点击播放器程序图标到音乐响起的时间里,这个程序具体做了什么事情呢?然而,如果面对的程序是恶意软件之流,用户就不得不关心一下它到底对自己的计算机造成什么影响了。

程序在运行期间所进行的操作被称为“程序行为”(Action),一般泛指程序进行的相对表现较明显的操作,例如创建读写文件、访问注册表、连接网络等,而在这些操作之外做的程序内部运算、判断、逻辑等操作并不是我们需要关心的,除非是对它进行复杂的分析如逆向工程。对程序行为进行监视记录的过程就是“跟踪”(Tracing),如果要进一步深入,则要使用调试器(Debugger)环境进行汇编级的指令分析,这就是“调试”(Debugging),也可视为更全面的跟踪,因为调试过程可观察到整个程序里的运算和每一步过程。

也许很多用户会觉得,这些复杂技术距离我们很远,甚至会想像为需要复杂设备和程序才能完成,其实,这些技术的应用范围,一直就在我们身边。如果你正在使用一款防毒产品,那么你系统里执行的程序就已经处于被记录行为的状态了;如果你使用HIPS产品,就会更强烈的感受到程序运行被监视着;如果你正在使用调试器,那就不用我说了吧……

Windows系统里,至少有三种技术可以实现程序行为的记录,甚至控制程序的某些行为,分别是“虚拟机”(VM)、“API钩子”(API Hooking)和“API跟踪”(API Tracing)。

应用广泛的虚拟机技术

经常提到的虚拟机技术有两种,一种是普遍应用上的虚拟机技术,它是通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统,此类虚拟机的概念比较广泛,可以是一种使用软件模拟一个完整的计算机硬件环境技术如VMWare,也可以是介于硬件和编译程序之间的交互介质,如Java虚拟机等;另一种则是反病毒产品中使用的“通用解密器”技术,为了检测一些复杂或者代码加密的病毒,杀毒引擎必须让它运行起来以便自我暴露危险程序行为,但是如果病毒真的在用户计算机里运行了,就违背反病毒产品的初衷了,因此反病毒产品也采取了一种虚拟环境检测方法,这就是虚拟机技术,但是这个技术并非是为病毒提供一套计算机仿真系统,这样就太庞大复杂和消耗资源了,这种虚拟机是指杀毒引擎模拟出一个仿真CPU,这个“CPU”具备和真正CPU等同的指令分析功能,杀毒引擎将待检测的程序代码读入“CPU”中逐条指令循环执行,直到出现特定情况才结束工作,在这个过程中探知程序是否具备病毒行为特征或者暴露出病毒特征码。这就是杀毒引擎的“虚拟机技术”,它的目的就是让程序文件在没有实际运行的情况下得到运行后的结果。

无论是哪种虚拟机技术,它们都能记录和解释程序的每一步执行过程,否则将无法正常运行程序,这也就说明,程序行为是可以被记录的,只是一般不会提供用户查看的接口。在恶意软件检测工作上,虚拟机技术可以帮助安全人员在不会真正让自己感染病毒的环境下放心的运行恶意程序,从而通过其他手段记录程序行为,普通用户也可通过虚拟机技术来保护自己的系统免受各种恶意软件的攻击,在虚拟环境中执行的程序,所做的一切改动都不会影响到真实的系统,所以用户要理清这个概念,避免不必要的损失,例如现在流行的影子系统(Shadow),它是通过在应用层上虚拟出一个目前的系统环境,所有的操作都没有写入真正的磁盘文件上,从而保证用户在上网时无论遭遇什么后门病毒,重启后都不会存在,最终实现了绝对安全的系统环境。然而,如果用户对它的机制不够了解,单纯认为它只是用来防范病毒,那就大错特错了,如果一个职员为了系统安全而使用全保护模式的影子系统,然后她又把公司的工作任务直接在电脑上完成并保存,那么重启后,她将会发现这一天的努力全化作了泡影!其实非蠕虫性质的网络入侵突破点通常只有几个,如浏览器、即时通讯程序、邮件等,那么我们只要单纯把这几个程序放入虚拟环境中,就不需要把整个系统都变成影子来防范了,这个技术被称为“沙箱”(Sandbox),与影子系统相似,它也是一种虚拟机环境,但是它仅仅为用户指定的程序提供虚拟作用,而不是整个系统,这样一来,有虚拟机需求的用户就不用担心自己辛苦撰写的文件由于一次习惯性的疏忽而丢失了。

充满钩子的世界——API Hooking

钩子技术在Windows系统中的作用与重要性我在这里就不再复述了,尤其从早期rootkit技术开始,这些钩子就伸向了更底层的系统内核中,从而获得了突破一切传统木马与病毒的权限,而后,大量的恶意软件纷纷向底层靠拢,到今天为止,一般用户已经无法通过简单的删除某个目录某个文件的方法来达到把一些软件扫地出门的效果了。

如果要一个用户谈及对恶意软件的感受,他的第一想法一定是“无法删除和卸载”;如果他被告知自己机器上还存在着rootkit后门,他的反应一定是不相信,因为他“安装着最新的杀毒软件”,如果这个用户对系统只有一些使用经验,那么他会发现任务管理器里没看到什么奇怪的进程,所以他仍然会认为自己系统是安全的。

造成这些现象的原因是什么呢?因为这些恶意程序使用的交互接口,并非Ring 3用户层上的标准Win32 API,而是通过各种手段如驱动程序进入到Ring 0内核层的Native API。
“Native API”(原生API)是Windows NT架构系统中真正工作的API,众所周知,Windows是一个通过大量API函数来实现程序功能的系统,然而,由于Windows是支持POSIX标准(可移植操作系统接口,Portable Operating System Interface)的系统,这就意味着,它除了能运行标准Windows平台程序(即Win32程序)以外,还支持少量其他平台上的程序运行,如OS/2。由于不同平台的程序功能实现方法差异,系统就必须分别为它支持的各个符合POSIX标准的程序提供相应的接口函数,如果根据这个思路去开发一套庞大而完整的接口函数调用,那就太不切实际了,于是,在NT架构系统上,开发者设计了两种不同性质的API接口层,一种被称为“用户态API”,它包括常见的Win32 API和POSIX接口API等,这些API运行在Ring3用户层上,构成了今天的Windows世界;而另一种是被称为“Native”性质的API,它们才是真正的系统API,通常运行在内核态上,实现真正的系统核心功能调用。同时为了实现POSIX,开发者还设计了被称为“子系统”(Sub System)的技术来将不同的系统环境区别开来,正常情况下,从系统引导到桌面时,我们就处于“Win32”子系统下,这时候起到作用的自然就是Win32 API。普通程序员平时接触到的几千个Win32 API,实际上都是通过几百个Native API的不同封装形式来实现的。系统厂商极少提供这些API的公开文档,是因为它们要比一般的函数难以应用而且可能发生变化,当程序员使用Win32 API时,最终的执行过程是在系统经过兼容性检查、错误处理、参数选项分离等一系列复杂转换后,才送入Native API进行处理的,Native API才是真正执行并反馈运行结果的主体,用户层的API调用只是一种封装形式罢了,例如fopen和CreateFile这两个Win32函数,它们的真正执行函数是Native性质的NtCreateFile,这就是rootkit可以让一般的进程工具不能发现自己的原因,因为它直接干涉了Native API的执行结果。

因为API还有这样复杂的故事,所以现在的恶意程序纷纷为了能最大限度提升自己的权限而变身rootkit性质程序,去“钩”这些原生API,而达到同等层次的安全检测工具和反病毒产品,也为了达到同样的效果而做了同样的事情,到了这个地步,安全产品和恶意软件在执行过程中已经没有区别了,唯一的区别是对用户和系统环境造成的后果差异而已,就如杀人犯和外科医生都通过把刀插入病人的身体以达到各自的目的,只不过一个是在杀人,一个是在救人,仅此而已。

既然大家都要控制到原生API层,那么他们的做法有没有共同点呢?答案是一定的,Windows作为一个规范的系统,就必须在原生API和用户层API之间存在一个标准的接口来实现数据传递,并限制用户使用其他不知名的操作来达到目的,这个接口由一个名为“ntdll.dll”的动态链接库文件负责,所有用户层API的处理都是调用这个DLL文件中的相关API入口实现的,但它只是一个提供从用户层跳转到内核层的接口,它并不是最终执行体。当API调用被转换为ntdll内的相关API函数后,系统就会在一个被称为“SSDT”(System Service Descriptor Table,系统服务描述符表)的数据表里查找这个API的位置,然后真正的调用它,这时候执行的API就是真正的原生API了,它们是位于NT系统真正内核程序ntoskrnl.exe里的函数。这一过程,就是系统服务的调用,例如外壳程序需要运行一个新的进程,那么它就会调用kernel32.dll导出的API函数CreateProcess,接下来就是kernel32.dll内的执行过程,实际上它只是把这个请求又包装了一下,变形为自己发出的参数,去调用ntdll.dll里导出的NtCreateProcess函数,然后ntdll.dll通过一个中断请求int 2Eh(Sysenter)进入内核态,并把我们最初的新建进程请求转换为“服务号”一起传递过去,到了内核的世界里,在正常手段下对API的调用都需要先通过一个函数地址描述表的转变来实现,SSDT就是这个表,它记录了一个庞大的地址索引,内容为几百个原生API在内核中导出的地址位置,除此之外还有一些有用的其他信息,在这个例子里,系统根据SSDT里记录的服务号与函数对应关系来确认我们要使用什么函数,以及这个函数在内核中的位置信息,最终实现功能调用,函数执行完毕后再把结果通过ntdll接口一层层传递回去,直到发出请求的程序收到一个表示处理结果的状态代码,这一次系统服务的调用过程就结束了。

由于上述原理,杀人犯和外科医生都会优先考虑把SSDT的内容给篡改以达到效果,简单的说,例如一个恶意程序把SSDT里对于获取进程标识的服务号对应的原生API地址修改为指向自己位于Ring0层的驱动入口,那么每次系统执行到这个函数时,都会由于SSDT的错误引导而进入了作者指定的服务模块中,就会导致相关的操作请求和参数被这个第三方模块记录和篡改,于是各种奇怪的现象就会发生了,就拿隐藏自身进程的rootkit技术来说,其原理就在于通过篡改SSDT里枚举进程的原生API服务号先指向自己的模块,再由自己的模块另行传递到真正的系统服务上(如果没有这一步操作或者操作错误,那么这个对应的系统服务就会作废甚至引发系统崩溃),并对真正的系统服务返回的数据进行加工处理,如删除带有自己进程名的数据,那么最终返回的数据里自然就“看不到”这个进程了。

正因如此,掌握了SSDT监控的程序便具备了比较有效的程序行为记录功能,这类程序的特点是钩住了大量的原生API,甚至某些HIPS系统如SSM等,更是把几乎所有SSDT里的地址全部改向了自己的模块,从而实现对所谓“危险”API的拦截,所以HIPS类防护工具在国外也被称为“程序动作拦截器”,由于它把自己置于用户程序和系统服务的中间,它就具备了监视记录程序行为的特权。

蛛丝马迹——API Tracing

虽然钩SSDT的技术使得rootkit和反rootkit都达到了一定程度上的效果,但这却不是技术的终点,因为太多安全工具已经具备发现钩SSDT的驱动的能力并提供还原SSDT的功能,传统意义上的rootkit技术已经过时了,于是如何通过其他方法绕过安全工具检测、或者接管更底层的API等方法被提了出来,而实际上,他们的研究已经成功了,过去大家的讨论热点在于以Zw/Nt开头的原生API以及SSDT上,但是现在,比原生API更底层的技术被挖掘出来了,它们以Cm开头,是原生API调用的对象,于是许多以前的理论和技术极限再次被推翻……想像一下,在你的安全工具努力去检测SSDT的时候,新的恶意软件早已直接绕过这一步到达更高一层楼了,那么你的检测工作,也就被沦为之前Ring 3工具那样的无效了,于是现在的rootkit技术,足以绕过市面上大部分反rootkit工具如IceSword、AST等,用户的唯一机会,就是将其在第一次运行时阻止,因为再强大的恶意软件,它首先也是从Ring 3开始运行的,可以说,Ring 3就是它的摇篮,所以,在Ring 3层绕过SSDT直达内核的方法被发现之前,目前各类HIPS工具还是可以信赖的,当然前提是用户具备足够的知识不至于引狼入室——至少,在国内,这一点,很难。

那么,是不是事情到了这个地步就意味着无法无天了呢?虽然道高一尺魔高一丈,但是有一种工具却是可以无视的——只是一般人也别指望用它来进行日常病毒检测查杀罢了。正所谓功能越强大的东西使用就越复杂,这类工具一般用户是无法使用的,因为它们被称为“调试器”。

调试器”之所以强大,是因为它们直接用的是CPU提供的调试指令,CPU自身就是所有指令代码的最终执行体,它具备的功能自然是十分强大的,对程序代码进行调试模式的执行也是其中一个功能,我们的程序文件是在内存里被转变为一条条指令代码运作的,而通过调试类工具对CPU内寄存器的相关位置下达了调试指令,这些工具就可以观察并更改程序运行的每一步过程,目前值得欣慰的是尚无办法阻止CPU显示某条指令,除非你自己都不想这个程序运行了,CPU不是“缸中之脑”。

虽然调试器的使用相当复杂,但是它的用途极为广泛,除了一般的逆向破解工程可能需要一条条的指令跟踪以外,它实际上还可以用来跟踪程序行为,通过相应的插件和断点设置,调试器可以记录到一个程序的API调用和参数供高级用户分析,当然,调试器也有相关的权限等级,目前常用的OllyDbg是位于Ring3层的调试器,它只能记录到ntdll.dll这一步,而位于Ring0级的SoftIce和系统级调试器WinDbg则可用于跟踪调试更复杂的核心层操作。

虽然调试器并非所有用户都能使用,但是它的API Tracing思想却是通用的,这样一来,不需要通过API Hooking技术就可以实现程序行为的记录了。

. 寻找黑匣子

对于高级用户和安全人员来说,当务之急是能否得到一种可以记录程序行为的工具,具备程序行为跟踪拦截功能的程序有许多,例如虚拟机、反病毒产品和HIPS类程序等,但是很遗憾,大部分产品并不会提供让你查看一个程序运行过程的功能,因为对于广大用户来说,这个功能除了耍酷以外,几乎一点用处都没有,目前只有少数HIPS产品提供了基本够用的程序行为记录功能,如Tiny Firewall这款产品。

Tiny Firewall是一个网络防火墙,但是它将IDS功能集成进去,从而实现了全面的程序行为检测和危险操作拦截的功能,而它更是具备了一个大部分HIPS产品都没有的功能——程序行为跟踪和还原。

Tiny Firewall可以从网络上获得,最终的版本号为6.5.126,其后的版本由于被CA购买并修改,失去了IDS部分,变成了接近传统意义的网络防火墙类工具,已经不具备本文所提的功能,所以不要指望它的升级版本了。

安装Tiny并重启后,系统任务栏托盘区会出现一个类似盾牌的图标,有关Tiny的防范设置在此不表,有兴趣挑战这个号称世界上最难设置的防火墙的读者可以自行查看相关资料。

现在随便运行一个程序,会看到Tiny弹出一个拦截消息,里面分为二列,左边“THIS TIME ONLY”表示仅在这次运行有效,右边“ALWAYS”则是永久有效的规则设置,如果是一般的常用程序,我们直接点击“Trust this Application”(信任这个程序)即可,但是现在,我们的意图是跟踪程序运行,因此,先停下你意欲点击这个拦截消息框内任何按钮的手,现在把鼠标移动到系统托盘区那个盾牌上,双击它,启动“Activity Monitor”(活动监视器),等活动监视器加载完毕的时候,点击拦截消息框内的“Track’n Reverse ™”(跟踪和复原)按钮,然后在出现的窗口上点击OK,你会看到程序开始运行,活动监视器上同时开始记录许多数据,现在右击系统托盘区那个盾牌图标,选“Run TrackLog Analyzer”(运行跟踪日志分析器),留意“Active Tracking”里是否有你正在运行的程序文件名,现在,如果是一般程序,那么可以关闭它了,如果是后台的恶意程序,就可以跳过这一步(反正它也不会提供退出功能……),然后选中“Active Tracking”里的相关文件名,点击界面上的红叉按钮,会看到文件自动进入了“Completed Tracking”列表,同时界面上的红叉按钮附近的2个按钮也为可用状态,现在点击第一个类似结构图的按钮“View Report”,右边的各个列表框中就会出现刚才这个程序操作的所有行为了,如文件操作、系统服务操作、注册表操作、运行时执行过的其他外部文件等,同时我们还可以点击右下角的“Revert changes”把刚才运行的程序所进行的改动给恢复到未运行前的状态。

如果你是一个有经验的用户,那么你会发现这个程序行为记录仍然有点不齐全,这就是注册表部分,它只记录了程序对什么部分进行了什么操作,但是却没有详细的数据改动记录,这样我们就不能完整的分析到一个程序对注册表做出的修改了,所以我们还必须借助一个第三方的有效注册表记录程序,Sysinternal的NT Registry Monitor,通过对它设置相关文件名的Filter,就可记录程序运行期间对注册表的修改,并生成日志文件,结合Tiny的程序行为记录功能,即可实现对一个程序的行为记录。

. 结语

在很多年以前,我们在网络上是相对安全的,大部分人都不必像现在一样,需要层层保护才能小心翼翼的移动半步,即使中了个木马,也只是几个可以轻易终止的EXE进程,最多加个关联保护罢了。是什么时候开始,我们不得不拿起各种安全检测工具,甚至,为了狙杀恶意程序而分析它的行为了呢?

抱歉!评论已关闭.