前言

在本系列的文章中,对每一个病毒分析的最后一个部分,若无特殊情况,我都会采用逆向分析的手段来为读者彻底剖析目标病毒。但是之前的“熊猫烧香”病毒,我用了三篇文章的篇幅(每篇2500字左右)也仅仅分析了病毒的三分之一,而且还没分析到病毒的核心部分。主要也是因为那是我这个系列为大家分析的第一个病毒,为了将一些原理性的东西说清楚,所以文章略显冗长,也主要是照顾一下初学的朋友,摒弃那些高大上的东西,将我的实际分析过程完整地呈现出来。相信大家在认真阅读完那三篇文章后,都能够掌握基本的分析方法,那么我在以后的文章中,只会讨论病毒中的一些比较重要的部分,会跳跃式地讲解,略去无关紧要的内容。当然,我依旧会配上详尽的图片与文字进行说明,让大家仅仅是看这些文章,就宛如亲自动手了一样。

一般来说,病毒分析不会涉及到算法问题,如果是要分析算法(如我之前对于CM4注册机制的分析),那么我们更多地是需要关注程序的流程与逻辑,一般不深究CALL的具体内容。而病毒分析则往往需要搞清楚各个不同的CALL的意义,才能够弄清楚病毒的行为。所以本文的第一部分着重讲述对这些CALL的剖析。而第二部分则简单讨论一下进程守护技术的实现。

逆向分析

这里我们跳过程序的初始化部分,来到第一个API函数的位置:

图1

我们能够直接看到的第一个API函数是GetModuleFileName,这个函数用于获取当前进程已加载模块的文件的完整路径,该模块必须由当前进程加载。而该函数的返回值则是文件路径长度,由截图可见,该返回值保存在了EAX中,为2B,也就是说路径长度为2B个字符。可以看一下所返回的路径是什么。路径保存在图1中的“PathBuffer”中,跟踪该地址查看:

图2

可见程序已正确获取了当前文件的地址。然后继续分析下一个API函数:

图3

这里出现了ShellExecute这个函数,它的功能是运行一个外部程序(或者是打开一个已注册的文件、打开一个目录、打印一个文件等等),并对外部程序有一定的控制。具体到本程序,ShellExecute会运行Explorer.exe程序来打开“d:\”,其实也就是使用程序管理器打开D盘根目录。但是执行这个API函数是有条件的,它需要根据图3中第二行CALL语句的结果进行判定,那么有必要进入这个CALL,看看需要满足什么条件才能够执行ShellExecute。

进入oso.00403C48这个函数,可以看到如下代码:

图4

程序会对EAX和EDX中的内容进行比对,其中EAX保存的字符串就是我们之前使用GetModuleFileName所获取的当前文件的路径,只不过被转化成了大写字符。而EDX保存的是D盘根目录下的OSO.EXE这个文件路径。二者在这里很明显是不同的。所以图4中黄色高亮显示的条件跳转语句也就不成立,程序会继续顺序执行:

图5

这里需要说明的是,由于本病毒是由Delphi编写的,那么字符串首地址减去4后,取出的4字节内容便是此字符串的长度。因此图5中的前两句代码意思就是获取两个路径的字符数,然后通过相减进行比较。这里很明显当前路径的字符数量是要大的,因此黄色高亮显示的条件跳转成立,来到oso.00403C6B的位置:

图6

这里依旧是字符的比较,由于二者不相等,所以上图中最后一句的条件跳转成立,来到oso.00403CD1的位置:

图7

这里比较的是盘符,也是不相等的,所以条件跳转成立,本函数也就执行完毕了。综合上述分析,这段函数的功用是判断当前所执行的文件是不是位于D盘的根目录下,如果是,则执行图3中的ShellExecute这个函数,反之则跳过这个函数执行。由于我们的这个程序是位于桌面上的,因此不执行ShellExecute函数。

接下来程序还会继续判断当前程序是否位于E、F、G、H、I盘根目录下,如果不是,那么也就不执行相应的ShellExecute函数。

之后程序会调用名为oso.004050F0的函数,进入其内部分析:

图8

可见病毒程序调用了GetSystemDirectory函数用于获取系统目录。一般来说,恶意程序使用这个函数的目的就是要将自身复制到系统目录中,以迷惑用户(详见《反病毒攻防研究第001篇:自我复制与自删除》)。之后病毒程序会将字符“severe.exe”与上面获得的系统目录字符串进行组合,新的路径也就是病毒程序需要隐藏的位置:

图9

之后可以看到CreateFile函数:

图10

但是这个CreateFile函数的执行是有条件的,它取决于上图中第一行代码中的CALL的返回值。进入这个CALL进行分析,可以找到:

图11

程序调用了FindFirstFile函数来查找系统目录中有没有severe.exe这个文件,如果没有(返回值为-1)则不执行图10中的CreateFile函数。由此可见,CreateFile函数在这里的作用不是创建文件,而是打开文件。接下来就是文件的复制操作:

图12

之后又是一系列的文件复制,病毒会将自身改名为tfidma.exe,并复制到系统目录中。还会将自身改名为conime.exe,复制到系统目录的drivers文件夹中。类似的操作不再赘述。之后程序就会再次调用ShellExecute函数,以执行所创建出来的这些程序。因此在“资源管理器”中就会出现severe.exe、conime.exe与tfidma.exe等进程。可以说在这个时候,我们的计算机就已经中病毒了。接下来我们会遇到线程的创建函数:

图13

CreateThread函数往往与Sleep或者WaitForSingleObject函数相配合使用。因为每个线程都有自己的CPU时间片,当主线程创建了新线程后,它的CPU时间片有时并没有完,它还可以继续执行。有时候如果主线程的代码非常少,那么在CPU指定的CPU时间片中主线程执行完后就退出了。主线程结束,那么意味着程序也就结束了,所以在这种情况下,我们自己创建的线程根本就没有被执行到。所以我们需要让主线程等待我们创建的线程,就需要使用Sleep或者WaitForSingleObject函数。本程序所采用的就是Sleep函数(等待1.3秒)。

回到图13中,根据OD对CreateThread函数的解析可以知道,该线程所调用的是oso.00404958这个函数。分析这个函数可以知道,它主要是创建了名为“hx1.bat”的批处理文件并执行,而该批处理的内容为:

@echo off
set date=2004-1-22
ping ** localhost > nul
date %date%
del %0

其主要作用就是修改系统时间,测试本地网络系统并删除自身。病毒的常规分析部分就是这些。

进程守护技术原理

进程的守护技术最早应该是源于“中国黑客病毒(worm.runouce)”,它开创性地采用了“三线程”结构。创建三线程就是为了更好地保护程序自身不被关闭和删除。我们可以将想要执行的代码放在主线程里,然后再生成两个辅助线程,它们的功能就是实现对程序的保护,防止程序被用户关闭或删除。在此,称我们的可执行文件的进程为主进程。两个辅助线程相互实时监视,如果监视对象被关闭了,就重新创建线程或进程。比如病毒程序可以选择Explorer.exe和Taskmgr.exe作为远程进程驻体。如果用户知道了远程线程的驻体为资源管理器后,就会打开任务管理器来结束Explorer,这时我们再把远程线程驻入到任务管理器中。也就是说,只要Explorer或Taskmgr有一个存在,就不可能结束主进程。如果有其它结束进程的工具,你就可以将其关闭掉,只要资源管理器和任务管理器均不存在时,就没有驻体来维持远程进程。不过,如果我们选择的远程进程为随机的,或者就是病毒自创的,这就不容易发现了。

这种三线程结构的程序框架大致如下(代码来自《浅析三线程程序开发思路与实现》):

// 1.主线程:main // 获得操作系统的系统目录GetSystemDirectory(syspath,MAX_PATH); // 查询系统目录下病毒是否存在FindFirstFile(virusname,&fdata); // 如果系统目录下没有,在将正在运行的程序复制到系统目录下CopyFile(curname,tname,TRUE); // 在查询完毕后,关闭相关句柄FindClose(ffhandle); // 打开系统目录下的文件CreateFile(kname,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); // 修改时间SetFileTime(fchandle,&ftime,NULL,&ftime); // 设置属性SetFileAttributes(kname,FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM ); // 创建驻留在主进程内的辅助监视线程CreateThread(NULL,0,watch,(LPVOID)rthread,0,NULL); // 2.本地辅助监视线程:watch // 以查询方式打开注册表的HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunRegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_QUERY_VALUE,&hkey); // 查询是否存在virusname的键值RegQueryValueEx(hkey,_T("virusname"),NULL,NULL,(LPBYTE)lpdata,&dwbuflen); // 如果没有相关键值,就以写方式再次打开注册表RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_WRITE,&hkey); // 写入我们想要的东西,系统每次启动都会运行我们的可执行文件;RegSetValueEx(hkey,_T("virusname"),NULL,type,(const byte *)wtname,dwbuflen); // 获得远程线程的运行情况,看是否为STILL_ACTIVE,如果不是则创建远程线程GetExitCodeThread(wethread,&exitcode);     // 3.远程线程:remote // 以所有可能的访问方式打开主进程,以便监视主进程的运行情况tOpenProcess(PROCESS_ALL_ACCESS,FALSE,erp->rpmousepid); // 等待直到主进程结束tWaitForSingleObject(erp->rpprocesshandle,INFINITE); // 重新启动我们的可执行文件  tWinExec(erp->rpwinexecname, 0); // 4.获得进程ID:processtopid // 列举所有的进程EnumProcesses(lpidprocesses,sizeof(lpidprocesses),&cbneeded); // 以查询信息和读取的方式打开进程OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,lpidprocesses[i]); //获得进程模块的句柄EnumProcessModules(hprocess,&hmodule,sizeof(hmodule),&cbneeded); // 获得特定模块的名字,以备比较GetModuleBaseName(hprocess,hmodule,normalname,sizeof(normalname)); // 5.创建远程线程:createremote // PROCESS_CREATE_THREAD for CreateRemoteThread // PROCESS_VM_OPERATION  for VirtualAllocEx // PROCESS_VM_WRITE      for WriteProcessMemoryOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,remotepid); // 在远程进程中分配空间,以备将线程代码置入其中VirtualAllocEx(rphandle,NULL,cb,MEM_COMMIT,PAGE_EXECUTE_READWRITE); // 将远程线程remote的代码写入到远程进程的地址空间中WriteProcessMemory(rphandle,remotethr,(LPVOID)remote,cb,NULL); // 将远程线程所需的参数也写入到远程进程的地址空间中WriteProcessMemory(rphandle,remotepar,(LPVOID)&rp,cb,NULL); // 创建远程监视线程CreateRemoteThread(rphandle,NULL,0,(LPTHREAD_START_ROUTINE)remotethr,(LPVOID)remotepar,0,NULL);

毕竟本系列不是教大家编写病毒,而是剖析病毒的大概思路,所以上述程序大家有个大概的印象即可,这样在以后的实际分析中,就能有大概的应对思路。

小结

至此,QQ盗号木马(oso.exe)病毒程序的分析就到这里。其实这几篇文章也就主要讨论了进程守护技术的实现与杀除。在以后的文章中,我只会讨论病毒中一些有特色的部分,也会与时俱进,研究一些目前流行的病毒,希望大家喜欢。

病毒木马查杀实战第012篇:QQ盗号木马之逆向分析相关推荐

  1. 病毒木马查杀实战第007篇:熊猫烧香之逆向分析(下)

    前言 这次我们会接着上一篇的内容继续对病毒进行分析.分析中会遇到一些不一样的情况,毕竟之前的代码我们只要按照流程顺序一步一步往下走,就能够弄清楚病毒的行为,但是在接下来的代码中,如果依旧如此,在某些分 ...

  2. 病毒木马查杀实战第005篇:熊猫烧香之逆向分析(上)

    前言 对病毒进行逆向分析,可以彻底弄清楚病毒的行为,从而采取更有效的针对手段.为了节省篇幅,在这里我不打算将"熊猫烧香"进行彻底的分析,只会讲解一些比较重要的部分,大家只要掌握了这 ...

  3. 病毒木马查杀实战第003篇:熊猫烧香之行为分析

    前言 为了分析"熊猫烧香"病毒的行为,我这里使用的是Process Monitor v3.10版.关于这款软件的使用,可参考以下三篇文章: <文档翻译第001篇:Proces ...

  4. 病毒木马查杀实战第026篇:“白加黑”恶意程序研究(上)

    前言 众所周知,传统的恶意程序都是由单一文件构成的.从而实现某一种或者几种恶意功能. 而这类的恶意程序为了避免被发现以及被查杀,往往会採用五花八门的自我隐藏技术以及免杀技术,病毒程序的作者非常多时候也 ...

  5. 病毒木马查杀实战第009篇:QQ盗号木马之手动查杀

    前言 之前在<病毒木马查杀第002篇:熊猫烧香之手动查杀>中,我在不借助任何工具的情况下,基本实现了对于"熊猫烧香"病毒的查杀.但是毕竟"熊猫烧香" ...

  6. 病毒木马查杀实战第010篇:QQ盗号木马之十六进制代码分析

    前言 按照我的个人习惯,在运用诸如IDA Pro与OllyDBG对病毒进行逆向分析之前,我都会利用一些自动化的工具,通过静态或动态的分析方法(参见<病毒木马查杀第008篇:熊猫烧香之病毒查杀总结 ...

  7. 病毒木马查杀实战第002篇:熊猫烧香之手动查杀

    前言 作为本系列研究的开始,我选择"熊猫烧香"这个病毒为研究对象.之所以选择这一款病毒,主要是因为它具有一定的代表性.一方面它当时造成了极大的影响,使得无论是不是计算机从业人员,都 ...

  8. 病毒木马查杀实战第001篇:基本查杀理论与实验环境配置

    前言 <病毒木马查杀>系列以真实的病毒木马(或统称为恶意程序)为研究对象,通过现有的技术手段对其分析,总结出它的恶意行为,进而制定出相应的应对方法(如编写专杀工具),对其彻底查杀.当然,本 ...

  9. 病毒木马查杀实战第018篇:病毒特征码查杀之基本原理

    前言 在本系列的导论中,我曾经在"病毒查杀方法"中简单讲解过特征码查杀这种方式.而我也在对于实际病毒的专杀工具编写中,使用过CRC32算法来对目标程序进行指纹匹配,从而进行病毒判定 ...

  10. 病毒木马查杀实战第019篇:病毒特征码查杀之编程实现

    前言 上次我们已经简介过了病毒特征码提取的基本方法,那么这次我们就通过编程来实现对于病毒的特征码查杀. 定义特征码存储结构 为了简单起见.这次我们使用的是setup.exe以及unpacked.exe ...

最新文章

  1. Yii框架的form处理
  2. 关系型数据库到HBase的数据储存方式变迁
  3. Go 语言编程 — net/http — HTTP 客户端
  4. 计算机二级c语言填空题怎么算分,计算机二级C语言题型和评分标准
  5. 关于处理小数点位数的几个oracle函数
  6. 日期setHours()方法以及JavaScript中的示例
  7. 前端学习(531):什么是等高布局
  8. 2020年边缘计算最新前沿报告:如何与核心云、5G、AI协同?如何打造新业态和部署运营?...
  9. NSJSONSerialization介绍
  10. python爬虫中文乱码_Python爬虫处理抓取数据中文乱码问题
  11. go post请求的响应数据渲染到html模板_干货你需要了解的六种渲染模式
  12. php获取li或者a标签中间的文字
  13. c#读取csv文件成DataTable,将DataTable数据存储为csv格式文件
  14. 保护站点子目录的文件
  15. ATFX:美联储会议纪要发布后,美元指数逼近105关口
  16. wed简介及html简单标签(1)
  17. 通讯录管理系统 C++
  18. linux||Linux的操作系统的简单指令
  19. linux qt中文输入法,解决 Ubuntu 14.04 下 Qt5 中文显示和中文输入法问题
  20. python数据分析与可视化

热门文章

  1. 进阶 | 手把手教你模拟键盘和鼠标操作-ActionChains
  2. DllMain 用法
  3. i511300h和i51135g7的区别 i5 1135g7和11300h核显对比
  4. 微波暗室——天线方向图测试
  5. 抖音特效转场模板预设 Premiere调色预设 PR光效转场等900个特效包(含教程及转场音效)
  6. Canon iC MF8350Cdn打印机驱动安装,解决内存不能为written问题
  7. RPlidar学习(三)——RPlidar源代码库
  8. jquery蝴蝶飞舞网页动画js特效代码
  9. 微信小程序中组件传值
  10. win7系统怎么用计算机,Win7系统中计算器怎么用