微点交流论坛
» 游客:  注册 | 登录 | 帮助

 

作者:
标题: [syscoder] 杀软行为分析1-4
点饭的百度空间
银牌会员




积分 2315
发帖 2236
注册 2007-11-30
#1  [syscoder] 杀软行为分析1-4

syscoder:参加了百度的笔试  2009-10-18 23:20
我想说的是百度的题真是很难,很变态,我也写的乱七八糟,我真是好头晕啊,好头晕啊。。。。 不过这么多人去应聘,出的复杂点也是理所应当滴


杀软行为分析一:判断文件是否为PE文件结构

  操作系统以及杀毒软件是怎么判断一个文件是否是PE文件的呢?先来看看操作系统是怎么识别的。学过PE文件的同学知道,PE文件结构中有两个标志在PE文件头中,一个是MZ标志,如果是PE文件的话,在文件的开头就是该标志,还有一个是PE文件标志,在PE文件头的开始出现(即:IMAGE_NT_HEADERS的开始出)。

      很多软件都靠上面两个标志合起来判断是否是PE文件结构,那么一个软件的运行到底需要这两个标志的哪一个呢?或许一个就够了呢?带着这些疑问,我们来测试一下,随便打开一个exe文件,用winhex修改文件开头的那个MZ(ACSII码为:4d 5A)修改成:00 00,然后保存,运行,结果发现程序无法运行了,出来一个Dos窗口,开来操作系统判断其不是PE文件结构,而是判断成了dos时代的程序,呵呵。开来MZ标志在判断PE文件结构中是不可缺少的,再来看一下PE标志是否是必须的呢?和上面操作一样,抹掉PE标志,然后运行会发现,程序无法运行了,与上面一样,弹出来一个dos窗口,看来MZ和PE都是判断PE文件不可缺少的标志。

       如果一个软件想要运行的话,那么就必须具有MZ和PE两个标志,你可以把一个病毒的MZ或PE标志去掉,会发现杀软不再杀了,当然这时文件也无法运行。

杀软行为分析二:对文件末尾多出字节的判断

  有些木马在配置客户端地址时会把客户端地址写到服务端的末尾,然后服务端读取末尾的字符得到客户端地址,然后开始连接,这样添加后文件还是可以运行的,不信的人可以试试,那么杀毒软件对此有什么反应呢?我们可以分析PE文件结构,得到最后一个节的文件偏移,然后加上该节经过文件对齐的大小,就是该PE文件实际的文件大小,如果后面还有数据,那么就可能就是木马的配置信息了,不过到底是不是,也不能这么确定啊,呵呵。。。

     那么有哪些杀毒软件会对这个很在意呢?小红伞就是其中一位,而且比较严重的一位,当小红伞发现一个文件的后面多出的字节超过大约4kb时,就开始报毒了,都不带查特征码的,这个大小是我实际测试中获得的,如果某个正常文件末尾有超过4kb的字节时,可要小心了,呵呵,说不定就被小红伞KO了,这样容易造成误杀,不过有那个正常的程序会在程序后面多加几个无用字节呢?碰到这个情况,可以选择把该文件截尾,即把后面的去掉,那么要是木马配置信息的话,木马也就被KO一半了,同时也不容易造成误杀。。

杀软行为分析三:对入口代码的判断

  PE文件的各个节在磁盘上是按照安装文件对齐的方式存放的,那么也就是说两个节之间可能存在空隙,实际情况中这些空隙往往都是存在的,只不过有大有小而已,病毒可以使用这些空隙来插入恶意代码,然后修改PE文件中的入口代码到插入代码的开始出,当文件开始执行时,则首先执行病毒代码,然后由病毒代码跳到原来的文件入口执行正常的代码,也就是说这些空隙可以被利用。。。

    杀毒软件是怎么处理的呢?要分两种情况,当病毒插入了代码,但病毒作者忘了更新节的IMAGE_SECTION_HEADER中的VirualSize字段。该字段就是该节没有对齐前的大小,那么杀毒软件只要对比一下该值就可以发现,入口代码竟然在节的空隙中,那么该文件就可能为病毒了。。

   第二种情况就复杂了,就是病毒更新了VirualSize字段,新添加的代码就输入该节的一部分了,而且是合法的部分,杀毒软件只判断VirualSize是无法发现异常的,不过这时入口代码就可能在该节的最后面,那么这是不是引发了一个问题呢?我们只要判断入口代码是不是在该节的最后面,若在最后面就是病毒了,否则则不是,那么要解决这个问题,要研究一下,一个正常PE文件的入口代码是不是总在该节的首位呢?写个程序判断一下,程序遍历一个system32文件夹下的所有PE文件,查看其入口是不是总在该节入口出呢?

// GetEntryCodeOffset.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"
char *   Dir="c:\\windows\\system32\\*.exe";

bool     _MapViewFile(char * FileName,HANDLE* FileHwnd,HANDLE* MapHwnd,PVOID* MapMem);
int      _IsEntryCodeInBeginSeciton(HANDLE FileHwnd,PVOID MapMem);
WIN32_FIND_DATAA FileInfo;
ULONG    CountB=0,CountN=0,CountF=0;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE   Hwnd,FileHwnd,MapHwnd;PVOID MapMem;

SetCurrentDirectoryA("c:\\windows\\system32\\");
Hwnd=FindFirstFileA(Dir,&FileInfo);
if(Hwnd!=INVALID_HANDLE_VALUE)
{
   do
   {
    printf("Find One File :%s\n",FileInfo.cFileName);
    if(_MapViewFile(FileInfo.cFileName,&FileHwnd,&MapHwnd,&MapMem))
    {
     int Type=_IsEntryCodeInBeginSeciton(FileHwnd,MapMem);
     switch (Type)
     {
        case 0:
       {   
                            CountF++;
        break;
       }
      case 1:
       {
        CountB++;
        break;
       }
      case 2:
       {
        CountN++;
        break;
       }
     }
     UnmapViewOfFile(MapMem);
     CloseHandle(FileHwnd);
     CloseHandle(MapHwnd);

    }
   
   }   while(FindNextFileA(Hwnd,&FileInfo));
}
printf("入口代码在节的开始数量:%d\n",CountB);
printf("入口代码不在节的开始数量:%d\n",CountN);
printf("失败个数:%d\n",CountF);
return 0;
}

bool _MapViewFile(char * FileName,HANDLE* FileHwnd,HANDLE* MapHwnd,PVOID* MapMem)
{
HANDLE THwnd,TMapHwnd;PVOID TMapMem;

THwnd=CreateFileA(FileInfo.cFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
          OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(THwnd!=INVALID_HANDLE_VALUE)
{
   TMapHwnd=CreateFileMappingA(THwnd,NULL,PAGE_READONLY,0,0,NULL);
   if(TMapHwnd!=NULL)
   {
    TMapMem=MapViewOfFile(TMapHwnd,FILE_MAP_READ,0,0,0);
    if(TMapMem!=NULL)
    {
     *FileHwnd=THwnd;
     *MapHwnd =TMapHwnd;
     *MapMem =TMapMem;
     return   true;
    }
    CloseHandle(TMapHwnd);
   }
        CloseHandle(THwnd);
}
return false;
}

int _IsEntryCodeInBeginSeciton(HANDLE FileHwnd,PVOID MapMem)
{
ULONG                 SizeL,SizeH,NumSection,EntryAddr,SectionEnd;
PIMAGE_DOS_HEADER     pDos;
PIMAGE_NT_HEADERS     pNt;
PIMAGE_SECTION_HEADER pSection;
SizeL=GetFileSize(FileHwnd,&SizeH);

if(SizeL>sizeof(IMAGE_DOS_HEADER))
   pDos =(PIMAGE_DOS_HEADER)MapMem;
else
   return 0;
if(pDos->e_magic!=IMAGE_DOS_SIGNATURE)
   return 0;

if(SizeL>(pDos->e_lfanew+sizeof(IMAGE_NT_HEADERS)))
   pNt =(PIMAGE_NT_HEADERS)((ULONG)MapMem+pDos->e_lfanew);
else
   return 0;
if(pNt->Signature!=IMAGE_NT_SIGNATURE)
   return 0;
   
pSection   =(PIMAGE_SECTION_HEADER)((ULONG)pNt+sizeof(IMAGE_NT_HEADERS));
NumSection =pNt->FileHeader.NumberOfSections;
EntryAddr =pNt->OptionalHeader.AddressOfEntryPoint;

while(NumSection>0)
{
   SectionEnd=pSection->VirtualAddress+pSection->SizeOfRawData;
   if((SectionEnd>EntryAddr)&&(EntryAddr>pSection->VirtualAddress))
   { printf("在节的偏移:%d处\n",EntryAddr-pSection->VirtualAddress);
    if(pSection->VirtualAddress==EntryAddr)
     return 1;
    return 2;
   }
  
   pSection++;
   NumSection--;
}
return 0;
}

   程序运行结果如图:



  看来基本上没有PE文件的入口正好在该节的入口处,那么上面的只是判断是否在后面将不再适用。。。那么难道没有方法来检测了么?呵呵,方法是有的,你可以判断一下,是不是程序一下从后面一个JMP跳了十万八千里跳到了大前面,不过会造成误杀的,如果某位作者写程序就爱一个Jmp跳的好远,那也说不定。。。。

※ ※ ※ 本文纯属【点饭的百度空间】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

你的微笑 is 微点的骄傲!
http://hi.baidu.com/new/micropoint
2010-1-14 18:45
查看资料  发送邮件  访问主页  发短消息   编辑帖子
点饭的百度空间
银牌会员




积分 2315
发帖 2236
注册 2007-11-30
#2  

杀软行为分析四:对添加节感染的处理

杀软行为分析三提到了,病毒可以在PE文件的节空隙添加代码来感染,不过当节的空隙不够时,即空隙的大小不足以存放代码的大小时,这个方法就不好使了,病毒就会尝试添加一个节,然会在添加的节中写入代码,这样无论如何都有足够的大小来存放病毒代码了,为了首先执行,一定会修改入口代码到新增加的节的代码处,然会执行完后跳到原来的节入口去执行,这种方法要比在空隙中添加代码复制的多,要修复PE文件中很多位,不过有足够的空间加代码已经很好了。。。

     杀毒软件怎么检测这种病毒呢?杀毒软件还是一般查一下特征码,没有病毒就拉倒了,我在这只是扩展一下该方面的查杀,纯属个人见解,呵呵,当添加了一节后,那么该节就一定要修改属性为可执行的,就是添加IMAGE_SCN_MEM_EXECUTE标志,这样才可以执行代码,但是文件本来就有一个可执行的代码段,现在又多了一个,那么其可以成为一个可以点,可以根据此来判断一个PE是否被感染。。。那么到底是否可行呢?看来有必要看一下,正常的PE文件到底有几个可执行节。。。。写个代码测试下,代码只是对杀软行为分析三中的代码修改了一下。。代码如下:

// GetEntryCodeOffset.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"
char *   Dir="c:\\windows\\system32\\*.exe";

bool     _MapViewFile(char * FileName,HANDLE* FileHwnd,HANDLE* MapHwnd,PVOID* MapMem);
int      _IsJustOneExecutionSeciton(HANDLE FileHwnd,PVOID MapMem);
WIN32_FIND_DATAA FileInfo;
ULONG    CountOne=0,CountMore=0,CountF;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE   Hwnd,FileHwnd,MapHwnd;PVOID MapMem;

SetCurrentDirectoryA("c:\\windows\\system32\\");
Hwnd=FindFirstFileA(Dir,&FileInfo);
if(Hwnd!=INVALID_HANDLE_VALUE)
{
   do
   {
    printf("Find One File :%s\n",FileInfo.cFileName);
    if(_MapViewFile(FileInfo.cFileName,&FileHwnd,&MapHwnd,&MapMem))
    {
     int Type=_IsJustOneExecutionSeciton(FileHwnd,MapMem);
     switch (Type)
     {
        case 0:
       {   
                            CountF++;
        break;
       }
      case 1:
       {
        CountOne++;
        break;
       }
      default:
       {   printf("该文件有:%d个\n",Type);
        CountMore++;
        break;
       }
     }
     UnmapViewOfFile(MapMem);
     CloseHandle(FileHwnd);
     CloseHandle(MapHwnd);

    }
   
   }   while(FindNextFileA(Hwnd,&FileInfo));
}
printf("只有一个执行节的个数:%d\n",CountOne);
printf("有多个执行节的个数:%d\n",CountMore);
return 0;
}

bool _MapViewFile(char * FileName,HANDLE* FileHwnd,HANDLE* MapHwnd,PVOID* MapMem)
{
HANDLE THwnd,TMapHwnd;PVOID TMapMem;

THwnd=CreateFileA(FileInfo.cFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
          OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(THwnd!=INVALID_HANDLE_VALUE)
{
   TMapHwnd=CreateFileMappingA(THwnd,NULL,PAGE_READONLY,0,0,NULL);
   if(TMapHwnd!=NULL)
   {
    TMapMem=MapViewOfFile(TMapHwnd,FILE_MAP_READ,0,0,0);
    if(TMapMem!=NULL)
    {
     *FileHwnd=THwnd;
     *MapHwnd =TMapHwnd;
     *MapMem =TMapMem;
     return   true;
    }
    CloseHandle(TMapHwnd);
   }
        CloseHandle(THwnd);
}
return false;
}

int _IsJustOneExecutionSeciton(HANDLE FileHwnd,PVOID MapMem)
{
ULONG                 SizeL,SizeH,NumSection,EntryAddr,SectionEnd,NumExe=0;
PIMAGE_DOS_HEADER     pDos;
PIMAGE_NT_HEADERS     pNt;
PIMAGE_SECTION_HEADER pSection;
SizeL=GetFileSize(FileHwnd,&SizeH);

if(SizeL>sizeof(IMAGE_DOS_HEADER))
   pDos =(PIMAGE_DOS_HEADER)MapMem;
else
   return 0;
if(pDos->e_magic!=IMAGE_DOS_SIGNATURE)
   return 0;

if(SizeL>(pDos->e_lfanew+sizeof(IMAGE_NT_HEADERS)))
   pNt =(PIMAGE_NT_HEADERS)((ULONG)MapMem+pDos->e_lfanew);
else
   return 0;
if(pNt->Signature!=IMAGE_NT_SIGNATURE)
   return 0;
   
pSection   =(PIMAGE_SECTION_HEADER)((ULONG)pNt+sizeof(IMAGE_NT_HEADERS));
NumSection =pNt->FileHeader.NumberOfSections;

while(NumSection>0)
{   
   if((pSection->Characteristics & IMAGE_SCN_MEM_EXECUTE))
   {
    NumExe++;
   }
   pSection++;
   NumSection--;
}
return NumExe;
}

   执行情况如图:



  虽然大部分都是一个执行节,结果发现有两个文件竟然大于了1个可执行节,这两个文件是什么呢?

就是这两位:



竟然有12个可执行节,不过学过驱动的同学可能到不惊讶,因为这两个文件是系统内核核心文件,这两个文件是运行Ring0下的。。不过,总体来说,在判断时这两个文件可以排除在外,这两个文件要坏了,你可能就要重装系统了。。呵呵。。。得出结论:判断是否多于1个执行节是可行的方法。。。

下一篇:
杀软行为分析五:微点对网络通信的拦截

※ ※ ※ 本文纯属【点饭的百度空间】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

你的微笑 is 微点的骄傲!
http://hi.baidu.com/new/micropoint
2010-1-14 18:45
查看资料  发送邮件  访问主页  发短消息   编辑帖子
zzz@zzz
注册用户





积分 111
发帖 111
注册 2010-1-4
#3  

这位同学理解的还算精湛,如果超微考虑一下壳的概念和工作流程,这篇比较鲜明的对比又会变得模糊了。。。

※ ※ ※ 本文纯属【zzz@zzz】个人意见,与【 微点交流论坛 】立场无关※ ※ ※
2010-1-14 22:19
查看资料  发送邮件  发短消息   编辑帖子
点饭的百度空间
银牌会员




积分 2315
发帖 2236
注册 2007-11-30
#4  

正好反馈下 同事的系统蓝屏 他只装了微点主防和微点杀毒:
drmkaud.sys
mp110021.sys

※ ※ ※ 本文纯属【点饭的百度空间】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

你的微笑 is 微点的骄傲!
http://hi.baidu.com/new/micropoint
2010-1-15 18:02
查看资料  发送邮件  访问主页  发短消息   编辑帖子
Legend
超级版主

超级版主



积分 77171
发帖 70170
注册 2005-10-29
#5  

请楼上让您同事将微点杀毒软件升级到最新版本测试,如果还有问题,麻烦他协助我们生成个蓝屏文件发给我们具体分析,谢谢。

具体的设置和操作如下:
1)设置生产蓝屏文件:
我的电脑(或计算机)-〉右键属性-〉高级-〉启动和故障恢复 -〉将"写入调试信息"改为“完全内存转储”,并取消勾选"系统失败"中的“自动重新启动” 。
2)在出现蓝屏时请等待蓝屏文件写入100%完成后重启,然后将c:\windows\MEMORY.DMP压缩发给我们,以便我们具体分析。

※文章所有权归【Legend】与【东方微点论坛】共同所有,转载请注明出处!※

微点官方认证新浪微博:欢迎进入 微点新浪微博
微点技术支持邮箱: support@micropoint.com.cn
给Legend发短消息
2010-1-15 18:19
查看资料  发短消息   编辑帖子
点饭的百度空间
银牌会员




积分 2315
发帖 2236
注册 2007-11-30
#6  

好的 让他天天升级去 另外反馈一个情况:

微点杀毒最新版:



※ ※ ※ 本文纯属【点饭的百度空间】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

你的微笑 is 微点的骄傲!
http://hi.baidu.com/new/micropoint
2010-1-15 18:43
查看资料  发送邮件  访问主页  发短消息   编辑帖子
Legend
超级版主

超级版主



积分 77171
发帖 70170
注册 2005-10-29
#7  

好的,这个问题您已经发了新帖,我们会具体测试分析的,谢谢。

※文章所有权归【Legend】与【东方微点论坛】共同所有,转载请注明出处!※

微点官方认证新浪微博:欢迎进入 微点新浪微博
微点技术支持邮箱: support@micropoint.com.cn
给Legend发短消息
2010-1-15 19:39
查看资料  发短消息   编辑帖子



论坛跳转:

可打印版本 | 推荐 | 订阅 | 收藏


[ 联系我们 - 东方微点 ]


北京东方微点信息技术有限责任公司 福建东方微点信息安全有限责任公司

闽ICP备05030815号