基于“执行路径重建”的盗号木马逆向分析取证方法研究
徐国天
中国刑事警察学院,沈阳 110854

作者简介:徐国天,男,辽宁沈阳人,硕士,副教授,研究方向为电子物证。E-mail:459536384@qq.com

摘要

目的 在不清楚盗号木马监控的特定窗体标题及关键配置信息加密情况下,办案人员很难通过网络监听和逆向分析方法获得黑客预置的电子邮箱账户数据。为了有效提取上述信息,本文提出一种基于“执行路径重建”的盗号木马逆向分析取证方法。方法 首先逆向分析木马程序的执行路径,随后正向修改、重建木马程序的执行路径,强制木马程序沿着检验人员设定的路径执行电子邮件发送行为,进而获取邮箱配置等关键信息。结果 从木马程序执行的邮件发送函数参数中提取出黑客电子邮箱账户、密码等关键配置信息。结论 应用本文提出的基于“执行路径重建”的盗号木马逆向分析取证方法可以对木马程序进行有效的检验分析。

关键词: 执行路径重建; 盗号木马; 逆向; 网络监听; 取证
中图分类号:DF793.2 文献标志码:A 文章编号:1008-3650(2019)04-0283-06
Reverse Analysis into Stealing-information Trojan through “Reconstructing Execution Path”
XU Guotian
National Police University of China, Shenyang 110854, China
Abstract

Objective It is difficult for criminal investigators to obtain hacker email account through network monitoring and reverse analysis without knowing the specific form title and key configuration information encrypted. Therefore, a forensic reverse analysis is here proposed through “reconstructing execution path” in order to effectively extract the required information.Methods The execution path of involved Trojan program is reversely analyzed to have it forwardly modified and rebuilt so that the Trojan program can be forced to execute the email-sending path specified by the inspector, thus the key information, e.g., mailbox configuration, will be acquired.Results With such a forensic approach, the key configuration information including hacker email account and password has been extracted from the related parameters of Trojan`s email sending function.Conclusions The forensic reverse analysis from “reconstructing execution path” proposed in this paper can effectively test and process Trojan program.

Key words: execution path reconstruction; Trojan; reverse analysis; network monitoring; forensics

盗号木马隐藏在受害者计算机系统或智能终端设备内, 在后台悄悄记录用户通过键盘输入的敏感信息(如账户、密码), 并将这些信息发送到黑客指定的电子邮箱或网络服务器上。黑客定期登录这些服务器, 查收木马窃取到的相关数据。当前, 盗号木马已对人民群众的个人信息安全乃至国家安全构成严重威胁, 研究此类木马的电子数据取证方法对公安机关的侦查办案工作有重要意义[1]。盗号木马取证需要完成的一项重要任务是获取黑客预置的电子邮箱账户或服务器IP地址配置信息, 目前办案人员通常采用网络数据监听和逆向分析方法。网络监听是通过捕获木马发出的网络通信数据, 从中提取出黑客的电子邮箱账户数据。但是盗号木马只监控受害者在特定窗口(如特定的网上银行登录窗口、特定的网络游戏登录窗口)内输入的敏感信息, 用户在非监控窗口内输入的按键信息, 木马并不记录。由于不清楚黑客预设的监控窗口标题, 办案人员很难准确触发木马向外发送电子邮件, 也就无法通过网络监听办法获得黑客预置的邮箱账户信息。已有木马程序逆向分析方法是将恶意程序的二进制可执行文件(如windows系统上的exe、dll文件, android系统上的apk文件)反编译为可直接阅读的汇编代码或smali源代码, 通过逐条阅读源代码, 分析恶意程序逻辑功能, 提取黑客预先配置的邮箱账户、服务器域名等关键配置信息[2]。但当黑客电子邮箱账户等配置信息以加密方式存储在恶意代码中, 使用逆向分析方法只能得到一组加密之后的密文数据, 而不了解其对应的原始明文是什么。虽然通过网络数据包捕获方法可以提取出邮箱账户等配置信息, 但如果木马不执行邮件发送行为, 就不会捕捉到相应的网络通信数据, 也就无法提取相关配置信息。

本文采用的“ 执行路径重建” 逆向分析方法可以在不掌握木马监控的特定窗口标题情况下, 通过修改恶意程序的执行路径, 强制它执行邮件发送行为, 木马在发送邮件之前, 会自行解密电子邮箱账户等关键配置信息, 当程序中断在邮件发送函数时, 可从函数传入参数里提取出解密之后的邮箱账户信息, 从而简化分析难度, 提高分析效率。木马检验使用的工具和基本流程如下:首先对木马恶意程序进行查壳, 判断其是否采用了某种加壳措施, 对加壳木马进行脱壳。脱壳后使用Loadpe工具查看系统函数调用情况, 再使用反汇编分析工具Ollydbg逆向分析程序的执行逻辑, 分析过程中可以设置断点, 观察参数变化, 得出分析结论。

1 基于“ 执行路径重建” 的盗号木马逆向分析取证方法

木马程序通常借助WS2_32.dll链接库进行网络通信, WS2_32.dll链接库中涉及邮件发送的系统函数比较多, 例如:WSAStartup、socket、connect、send和recv[3], 在木马程序执行过程中, 如果程序能中断在这些函数上, 就可以从这些函数的参数里获得黑客的电子邮箱账户、密码和电子邮件正文数据。但在实际应用当中, 即使在这些网络函数上设置断点, 木马程序运行之后通常也不会中断在这些函数上, 这是由于盗号木马发送电子邮件需要具备多个触发条件, 如出现特定标题的登录窗体、用户在窗体内输入账户信息、用户点击登录按钮且成功登录等, 诸多条件都满足后, 木马才会发出电子邮件, 否则, 不会触发邮件发送功能。由于程序在运行过程中, 会根据实际情况选择不同的执行路径, 设置的断点没有被执行到, 说明程序当前的执行路径没有经过预设的断点。这就是取证人员需要解决的一个关键问题, 即如何让程序沿着设定的路径, 走到断点位置。

本文提出一种基于执行路径重建的取证分析方法, 描述如下:首先, 确定函数在木马程序中的调用位置, 从每个调用点开始依次向前跟踪溯源, 在遇到分枝跳转位置时, 记录下跳转点, 直至程序源头。之后从主程序开始正向调试, 依次在每个可能导致程序进入错误分枝的跳转点设置断点, 跟踪程序是在哪个位置进入错误分枝。最后, 研究错误跳转位置局部代码, 调试程序逻辑, 使其进入正确分枝, 直至最终到达预设断点位置。

基于执行路径重建的取证分析方法应用示意图见图1。图1a是木马程序的执行流程图, 从起点开始, 程序可以沿着多种路径达到终点, 当前程序选择的执行路径没有经过我们预设的断点位置。图1b表示从断点开始逆向追踪还原执行路径, 通过设置断点发现程序在拐点位置进入错误分枝。之后, 研究拐点位置的局部汇编代码, 分析逻辑调用关系, 理清触发跳转的真实原因。图1c表示通过修改局部代码的传递参数值, 使其满足进入正确分枝的触发条件, 人为改变程序的执行流向, 使其进入正确分枝, 并最终到达预设的断点位置。

图1 基于执行路径重建的取证分析方法Fig.1 Forensic reverse analysis into Trojan through “ reconstructing execution path”

本文以一款名为“ redspider.dll” 的盗号木马为例, 研究基于执行路径重建的取证分析方法。取证分析之前首先要对盗号木马进行脱壳, 相关内容不在本文讨论范围内, 脱壳后的文件名为_Unpacked.dll。

2 邮件发送函数起始和结束位置的定位

使用Loadpe工具查看_Unpacked.dll, 在WS2_32.dll链接库下出现大量函数调用[4], 说明木马程序进行了网络通信。按照程序设计的一般规律, 邮件发送函数应该设计为一个独立的功能函数, 因此需要完成的第一项工作就是在_Unpacked.dll的反汇编代码中定位到这个函数。由于邮件发送行为使用的第一个函数通常是WSAStartup, 在源程序中搜索这个函数的引用位置, 即可定位邮件发送函数的起始位置。使用Ollydbg打开_Unpacked.dll, 搜索字符串“ WSAStartup” , 结果显示在木马程序的偏移地址0X100017E7位置调用了这个函数。图2显示的是定位结果, 在地址0X100017D0之前是一块连续的空闲区域, 使用空指令nop填充。同时这一地址处的汇编指令为sub esp, 378, 是为函数申请局部变量存储空间, 其后连续4条push指令是进行环境变量保护。根据这些特征可以确定地址0X100017D0为邮件发送函数的起始位置。

图2 确定邮件发送函数的起始和结束位置Fig.2 Determining the starting and ending locality of Trojan mailing function

向下浏览程序, 在地址0X10001C02位置是一条retn指令, 这是函数结束的标志, 其后是一块连续的空指令区域, 同时在地址0X10001BF0位置调用了WSACleanup函数, 这个函数通常是邮件发送行为使用的最后一个网络函数。根据这些特征可以确定地址0X10001C02为函数的结束位置。确定邮件发送函数的起始和结束位置后, 我们在函数起始地址0X100017D0设置断点, 按F9键启动木马程序。等待一段时间后, 程序并未中断。说明程序运行之后并未触发邮件发送功能。

3 木马程序执行路径分析及重建

首先, 根据邮件发送函数起始地址确定在木马主程序偏移地址0X1000147C和0X10001521位置两次调用邮件发送函数。分别从偏移地址0X1000147C和0X10001521开始向前跟踪, 直至主程序起始位置, 每经过一个跳转点, 记录下相应的偏移地址。图3为跟踪结果, 可以看出木马程序先后在偏移地址0X10001454、0X10001471和0X100014F6位置出现异常跳转, 如果程序跳转到地址0X1000154B、0X1000155A或0X10001529, 那么木马程序在执行过程中就不会调用邮件发送函数, 我们预设的断点就不会被触发。同时, 通过图3也可以看出, 程序执行地址0X1000147C位置的汇编代码发送电子邮件, 如果程序在地址0X100014F6没有跳转到0X10001529, 那么一定会执行地址0X10001521触发第二次邮件发送, 也就是木马程序会发送两封电子邮件。从图3可以看出, 在偏移地址0X10001454、0X10001471和0X100014F6出现三次拐点, 程序可能在这三个位置进入错误分枝。按照从前至后的原则分别在0X10001454、0X10001471和0X100014F6地址设置断点, 观察程序的执行流向。

图3 调用流程分析Fig.3 Recursive analysis into one executing Trojan program

3.1 第一处拐点代码分析及修改

先在偏移地址0X10001454设置断点, 查看主程序会从这里跳转到地址0X1000155A, 即进入错误分枝。对第一个拐点位置的局部汇编代码进行分析, 判断程序是如何跳转到错误分枝的。局部位置出现的第一个系统函数是GetLocalTime, 如图4所示, 它可以获取计算机当前系统日期和时间。函数的原型定义为VOID GetLocalTime(LPSYSTEMTIME lpSystemTime), 其中lpSystemTime是一个SYSTEMTIME类型变量, 该变量用来保存函数获取的日期和时间信息。图4显示函数的运行结果保存在内存地址0X100083E0位置, 使用16个字节保存当前系统日期和时间。这一结果表示当前日期时间为“ 2017年4月23日 16点7分10秒750毫秒” , 注意结果中5~6字节保存的是星期几, 0表示星期日。

图4 时间获取函数分析Fig.4 Time acquisition function and its performing result

图5显示的是时间函数之后的8条汇编指令。第1条指令是将之前获得的日期时间信息中的分钟数据送到ax寄存器(如图5b所示)。第2条汇编指令是将地址0X1000858C位置的2字节数据(图5d)与ax寄存器数值进行比较。

图5 局部代码分析Fig.5 Analysis of local codes

经过分析, 我们发现0X1000858C地址存储的是上一次检测时记录的分钟数据, 这条指令是将上次记录的分钟值与当前分钟值进行比较, 如两者不同, 认为时间又前进了1 min。在本例中, 前次记录分钟值为6(如图5d所示), 本次值为7, 两者不同, 程序执行第4条指令, 即将计数器值加以1, 变化前后的计数器值如图5e和图5f所示。第5~8条指令是将计数器值与限定值20 min(如图5g所示)进行比较, 如计数值小于20 min, 即没有达到定时器门限值, 程序跳转到0X1000155A地址, 即进入错误分枝。否则, 定时器达到门限值, 程序进入正确分枝执行。这段程序的功能是限定邮件发送的时间间隔为20 min, 没到达门限值时不触发邮件发送功能。有两种方案可以让程序进入正确的分枝。第一种是直接将图5f内存堆栈中[esp+10]位置的计数值改为20, 达到门限值, 程序跳转到正确分枝。第二种方法是将图5g内存堆栈中的[esp+14]位置的门限值下调, 也能使程序进入正确分枝。这里我们采用第一种方案, 修改EDX寄存器, 将计数值调整为0X00000014, 即达到门限值20 min。之后, 在木马程序第二处拐点位置0X10001471设置第二个断点, 观察程序的执行流向。

3.2 第二处拐点代码分析及修改

如图6所示, 地址0X10001461开始的7条汇编指令是第二处拐点的局部汇编代码。内存地址0X1000858C存储的是另一个内存地址0X7FF80000, 1~4行代码的主要功能是统计从地址0X7FF80000开始的内存区域里有多少个字节数据, 直至0x00结束。第5行指令not ecx执行之后, ecx寄存器中存储的就是前面统计字节个数加1, 由于目前从地址0X7FF80000开始的内存里没有任何数据, 因此ecx寄存器值为1。第6行语句dec ecx指令执行之后, ecx寄存器值为0。因此, 第7行je _Unpacke.1000154B判断之后, 程序跳转到0X1000154B地址, 进入错误分枝。经过分析, 发现实际上地址0X7FF80000开始的内存里存储的是键盘记录信息, 木马会将这些信息发送到黑客指定的电子邮箱。因此, 可以在这一区域任意输入一些文本信息, 木马程序识别出目标内存里存储了文字信息, 会误认为这是窃取到的键盘记录数据, 程序判断信息字符串文本长度(即ecx寄存器数值)大于零, 将跳转到正确分枝继续运行。如图6所示, 从地址0X7FF80000开始填写6个字节“ hello” , ecx寄存器内存储的是字符串长度值加1。因此, 将ecx寄存器值修改为0X00000007。之后在邮件发送函数的起始地址0X100017D0设置断点, 逐步执行邮件发送程序, 通过观察内存和堆栈内参数的变化来了解黑客配置的电子邮箱信息。

图6 程序执行流向分析Fig.6 Course orientation by program execution

3.3 邮件账户信息及第一封邮件内容提取

木马程序使用send函数发送数据, 使用recv函数接收数据。从这两个函数的参数里可以获得木马发送和接收的通信数据。Send函数的原型定义如下:int send( SOCKET s, const char FAR* buf, int len, int flags ), 该函数的第一个参数s指定发送端套接字描述符; 第二个参数buf指向一个缓冲区, 存储准备发送的数据内容; 第三个参数len指明实际要发送数据的字节个数; 第四个参数flags一般设置为0。Recv函数的原型定义如下:int recv( SOCKET s, char FAR * buf, int len, int flags), 第二个参数buf指向一个接收缓冲区, 存储通过网络接收到的字节数据。在这两个函数的调用位置设置断点, 可以获得木马发送和接收的所有数据内容。断点设置方法如图7所示。在程序拐点和邮件发送函数起始、结束位置分别设置断点(如有多个结束位置, 则分别设置断点), 再在send和recv函数上面设置断点。之后按F9键运行程序, 木马程序会多次调用send和recv函数发送接收数据, 每次收发数据都会触发一次中断, 从buf缓存内可以获得收发数据内容。需要注意的是, 在程序运行过程中存储接收和发送数据的缓存地址可能发生切换, 在调试过程中应予以重视。

图7 设置断点获取电子邮件相关数据Fig.7 Getting email-related data through setting breakpoints

图8为木马程序中断在断点位置时发送和接收缓存内的数据内容, 黑客电子邮箱账户信息, 数据内容采用了base-64编码, 可以使用任何一款base-64解码软件还原。还原之后显示, 账户名为xgt888, 密码为86982480。电子邮件正文内容, 主题是“ 红蜘蛛的礼物” , 内容是“ hello” , 即我们模拟的键盘记录信息。

图8 提取出的邮件账户信息Fig.8 Extracting the information of one email account

3.4 第三处拐点代码分析及修改

如图3所示, 在地址0X100014F6位置存在第三次拐点, 如果木马程序在这个位置跳转到偏移地址0X10001529, 那么第二次邮件发送行为将不会发生。为了让木马程序进入正确的分枝, 发出第二封电子邮件, 我们先来研究一下第三处拐点附近的局部汇编代码。局部代码如图9所示, 第三条语句执行了一次函数调用, 前面两条语句是使用push命令传入两个参数, 第五条语句使用test命令测试函数的执行结果, 如果执行结果eax值为0, 则程序跳转到0X10001529地址, 进入错误分枝。下面, 我们在第二条语句处设置断点, 来观察函数的执行功能。前两个断点位置的相关参数也要正确设置, 程序才能执行到这个位置。木马程序运行到地址0X100014EB断下, 两个传递参数值如图10所示。

图9 第三次拐点位置局部汇编代码Fig.9 Local codes assembled at the third inflection point

图10 调整函数执行参数Fig.10 Adjusting the executed parameters of the modified function

目测是进行字符串比较, 将参数2的前四个字节修改为0XB5 C7 C2 BC, 即汉字“ 登录” , 此时两个参数字符串值相同。函数执行结果存储在EAX寄存器内, 值为0XFFF80000, 即参数2的内存起始地址。至此, 判断出函数功能是进行字符串比较, 不同返回值为0, 相同返回子串在主串中的位置。调整参数之后, 木马程序会沿着正确的路径执行, 发送第二封电子邮件。与第一封邮件相比, 第二封邮件的收件人是redspider119@163.com, 邮件正文内容仍然是“ hello” 。这说明木马程序的作者在木马中预置了一个后门, 木马每窃取到一组账户信息, 先发送到黑客邮箱里一份, 再发送到木马作者邮箱一份。

4 总结

本文提出一种基于执行路径重建的盗号木马取证分析方法, 这种方法可以在不掌握木马监控的特定窗口标题情况下, 通过修改木马程序的执行路径, 强制木马程序执行电子邮件发送行为, 进而获取邮箱配置信息。该方法要求取证人员具备一定的汇编程序分析基础。下一步, 计划研究自动化辅助分析方法, 以简化分析难度、提高分析效率。

参考文献
[1] 张慧琳, 邹维, 韩心慧. 网页木马机理与防御技术[J]. 软件学报, 2013(4): 19-22. [本文引用:1]
[2] 余倩. Android木马及其关键技术的研究与实现[D]. 成都: 电子科技大学, 2016. [本文引用:1]
[3] 佛罗赞. 数据通信与网络[M]. 吴时霖, 译. 北京: 机械工业出版社, 2007: 57-58. [本文引用:1]
[4] 钱林松. C++反汇编与逆向分析技术揭秘[M]. 北京: 机械工业出版社, 2011: 32-36. [本文引用:1]