首页
社区
课程
招聘
[原创]记一次头铁的病毒样本分析过程
2021-10-27 05:07 18644

[原创]记一次头铁的病毒样本分析过程

2021-10-27 05:07
18644

一、样本:

[1]运行效果:

    点击确定后就无任何反应。


二、静态分析

[1]程序信息

MD5    fdd9fd0249d48d8c6d991741c67fcfeb

SHA-1    ff0181242825b5bb8cac1d4d17e8377352e3aa55

SHA-256    6a9bdabc4599618513de5c963972929de9322c486e84e101e177c0868e7c5fb7

File size    1.34 MB (1408512 bytes)

    其中较为引人注目的就是winnet.dll、shell32.dll、advapi32.dll,这三者分别是对网络,运行程序,注册表进行操作的动态库,说明程序存在运行外部程序和联网操作。

    字符串的话,通过Strings.exe查询后没发现任何敏感字符串,这里就不贴出来了。(因为太多了 =。=)

[2]在线查毒

[3]进程行为监控:

        通过火绒的监控发现其对注册表进行了大量操作,不过并没什么影响。

        且运行了一个名为CrashReporter.exe的程序。

        途中创建了一些文件

        首先是CrashReporter.exe,跳到目标目录后发现其文件大小与样本大小相同,故猜测此样本运行后将自身转移到新路径后伪装绿色运行,其次是txt,打开后发现内容为

ABC

AAC

AAD

BBC

BAC

BAD

        暂时不知什么意思,然后是WeiXinCR01,内容为

D2 C2 7E AD 52 06 C4 93

        这里根据后面的调试,发现内容含义为Crc32计算C盘的序列号的结果。

[4]网络行为

        HttpDebuger无任何发现。


三、动静态分析

        首先分析原样本,突破口可以从给MessageBoxA下断后返回拿到关键点。

        这里直接返回到call的位置,直接计算call地址的相对地址,然后扔进IDA进行分析。


        这个样本在静态分析时之所以没有看到敏感字符串是因为他的字符串都是以字符数组初始化的,

        在分析的时候可以通过先转义这些字符数组的内容,再去分析这个地方执行了什么。比如这里的字符数组为SetEvent error,那么说明调用SetEvent失败。并且他这个样本调用函数的方式是通过一个类似shellcode的方法获取,然后把函数存放放到一个全局变量里。

        我们来到调用了MessageBoxA后,直接到函数头部进行一直交叉引用,最后来到了WinMain的最初调用处。

        这个过程中会发现整个代码中存在很多这种形式的代码。

         这些代码看似是在获取TEB和PEB操作,但是经过简单分析后,发现这些其实就是垃圾代码,只是为了通过增大代码量,用来增加分析时间。


[1]StartMainWork分析

        在这个StartMainWork函数执行前,会执行几个数据初始化的函数,包括有crc32和crc64表的生成,动态库函数的获取,还有样本之后所需要用到的数据。这里crc32和64生成的函数很好识别,因为其算法固定,且带有常量值,下面是样本生成crc的关键代码。

for ( i = 0; i < 256; ++i )                   // 开始生成crc32表

  {

    crcValue = i;

    for ( j = 0; j < 8; ++j )

    {

      ......垃圾代码........

      if ( crcValue & 1 )

        crcValue = (crcValue >> 1) ^ 0xEDB88320;// 搜索这个值,可以知道这里是CRC算法的常量值

      else

        crcValue = crcValue >> 1;

      g_crc32Table[i] = crcValue;

    }

  }


for ( jj = 0; jj < 256; ++jj )                // 开始生成crc64表

  {

    v45 = jj;

    for ( kk = 0; kk < 8; ++kk )

    {

      ......垃圾代码........

      if ( v45 & 1 )

      {

        LODWORD(v0) = (v45 >> 1) ^ 0xAC4BC9B5;  // 根据这个常量值,搜索后发现是crc64的常量值

        HIDWORD(v0) = (v45 >> 1 >> 32) ^ 0x95AC9329;

        v45 = v0;

      }

      else

      {

        v45 >>= 1;

      }

      g_crc64Table_Low[2 * jj] = v45;

      g_crc64Table_Hight[2 * jj] = HIDWORD(v45);


        然后比较有意思的就是动态库函数的获取了,该样本采取了类似shellcode的方式获取,通过Ldr来遍历自身的dll模块,然后通过都PE文件的解析寻找函数地址,并添加到全局函数表中。该方式在《恶意代码分析实战》一书中第十九章的shellcode符号解析有讲解,这里就不详细解释了。以下是关键代码。

peb = readPEB();

*functionTable = peb;

if ( peb )

{

    // 通过动态调试得知这里获取的是Kernel32.dll地址,参数二为字符串Kernel32.dll通过crc32计算后的结果

    ModuleBase = getModuleBaseByCrcValue(*functionTable, 0xF7784A01);

    functionTable[1] = ModuleBase;

    if ( KernelBase )

    {

        // 直接从目录项里获取参数三对应的函数地址

        procCreateFileA = getProcAddrByDirArray(functionTable[1], -1, (int)&strCreateFileA, 0);

        ....往下的也是一样

    }

    ............

}

        这里贴出他加载的所有函数

$ ==>     757E3090  kernel32.CreateFileA

$+4       757DDF70  kernel32.GetLastError

$+8       757D83E0  kernel32.GetSystemDirectoryA

$+C       757E22D0  kernel32.ExpandEnvironmentStringsA

$+10      757E0BE0  kernel32.GetStartupInfoA

$+14      757F2DA0  kernel32.CreateProcessA

$+18      757E2E40  kernel32.CloseHandle

$+1C      757E3030  kernel32.WaitForSingleObject

$+20      757E3420  kernel32.ReadFile

$+24      757D89C0  kernel32.lstrcat

$+28      757E2DF0  kernel32.GetCurrentProcessId

$+2C      757DDE70  kernel32.GetCurrentThreadId

$+30      757E2300  kernel32.GetTickCount

$+34      757E3510  kernel32.WriteFile

$+38      757F2D80  kernel32.CreatePipe

$+3C      75130000  "MZ?"

$+40      75155840  user32.wsprintfA

$+44      757C0000  "MZ?"

$+48      757E0B30  kernel32.LoadLibraryA

$+4C      757E0A40  kernel32.FreeLibrary

$+50      757E0D90  kernel32.GetModuleFileNameA

$+54      757DE010  kernel32.lstrlenW

$+58      757DDF00  kernel32.SetLastError

$+5C      7581F6A0  kernel32.lstrcpyW

$+60      757E03A0  kernel32.lstrlenA

$+64      757D8320  kernel32.lstrcpyA

$+68      757DF440  kernel32.lstrcmp

$+6C      757DF320  kernel32.VirtualAlloc

$+70      757DF420  kernel32.VirtualFree

$+74      757E0860  kernel32.GetModuleFileNameW

$+78      757E3090  kernel32.CreateFileA

$+7C      757E32C0  kernel32.GetFileSize

$+80      757E3420  kernel32.ReadFile

$+84      757E2E40  kernel32.CloseHandle

$+88      757D88F0  kernel32.GetEnvironmentVariableA

$+8C      757D89C0  kernel32.lstrcat

$+90      757E3510  kernel32.WriteFile

$+94      757DDF70  kernel32.GetLastError

$+98      757E0E60  kernel32.Sleep

$+9C      757E3030  kernel32.WaitForSingleObject

$+A0      757E2E90  kernel32.CreateEventA

$+A4      757E0E70  kernel32.CreateThread

$+A8      757E2FE0  kernel32.SetEvent

$+AC      757D92B0  kernel32.OutputDebugStringA

$+B0      757E2300  kernel32.GetTickCount

$+B4      757D2EB0  kernel32.FindResourceA

$+B8      757E03E0  kernel32.SizeofResource

$+BC      757DE7A0  kernel32.LoadResource

$+C0      757DF2A0  kernel32.LockResource

$+C4      757F4B10  kernel32.SetCurrentDirectoryA

$+C8      7581CD60  kernel32.WinExec

$+CC      757DF4B0  kernel32.GetProcAddress

$+D0      757E2DF0  kernel32.GetCurrentProcessId

$+D4      757DDE70  kernel32.GetCurrentThreadId

$+D8      757F2D80  kernel32.CreatePipe

$+DC      757E3010  kernel32.WaitForMultipleObjects

$+E0      757E2FD0  kernel32.ResetEvent

$+E4      757E0AF0  kernel32.ProcessIdToSessionId

$+E8      757E1E10  kernel32.GetNativeSystemInfo

$+EC      757E0640  kernel32.IsWow64Process

$+F0      757E2DE0  kernel32.GetCurrentProcess

$+F4      757F2DA0  kernel32.CreateProcessA

$+F8      757D9870  kernel32.TerminateProcess

$+FC      757F5000  kernel32.VirtualAllocEx

$+100     757F5250  kernel32.WriteProcessMemory

$+104     757F2E40  kernel32.CreateRemoteThread

$+108     757E0590  kernel32.OpenProcess

$+10C     757F4B70  kernel32.SetEnvironmentVariableA

$+110     757F3550  kernel32.GetEnvironmentStrings

$+114     757E3390  kernel32.GetVolumeInformationA

$+118     757D8FE0  kernel32.GetComputerNameA

$+11C     757E16C0  kernel32.GetVersionExA

$+120     757E0BE0  kernel32.GetStartupInfoA

$+124     757D83E0  kernel32.GetSystemDirectoryA

$+128     757E34C0  kernel32.SetFilePointerEx

$+12C     757E32D0  kernel32.GetFileSizeEx

$+130     757E32E0  kernel32.GetFileTime

$+134     757E34D0  kernel32.SetFileTime

$+138     757E22D0  kernel32.ExpandEnvironmentStringsA

$+13C     757E30C0  kernel32.DeleteFileA

$+140     757E34B0  kernel32.SetFilePointer

$+144     757E09C0  kernel32.GetModuleHandleA

$+148     757E0DB0  kernel32.GetModuleHandleW

$+14C     757E07C0  kernel32.GetEnvironmentVariableW

$+150     757E1E40  kernel32.GetCommandLineA

$+154     757D9420  kernel32.GetExitCodeProcess

$+158     757E1850  kernel32.ResumeThread

$+15C     757DF2F0  kernel32.GetSystemTimeAsFileTime

$+160     757E2ED0  kernel32.CreateMutexA

$+164     757D8AC0  kernel32.CopyFileA

$+168     757E3060  kernel32.CreateDirectoryA

$+16C     757E2040  kernel32.GetExitCodeThread

$+170     757DF490  kernel32.LocalFree

$+174     757DDF50  kernel32.WideCharToMultiByte

$+178     75130000  "MZ?"

$+17C     75155840  user32.wsprintfA

$+180     76EE6640  ntdll.NtdllDefWindowProc_A

$+184     7514F150  user32.RegisterClassA

$+188     75155580  user32.CreateWindowExA

$+18C     7516F7E0  user32.ShowWindow

$+190     75161970  user32.UpdateWindow

$+194     75150B90  user32.GetMessageA

$+198     75167660  user32.TranslateMessage

$+19C     75154EC0  user32.DispatchMessageA

$+1A0     75159350  user32.CharUpperA

$+1A4     751AD860  user32.MessageBoxA

$+1A8     751527A0  user32.GetCursorPos

$+1AC     751B7170  user32.FindWindowExA

$+1B0     75167AF0  user32.GetWindowThreadProcessId

$+1B4     75161ED0  user32.GetWindowRect

$+1B8     751660B0  user32.ScreenToClient

$+1BC     75162150  user32.GetClientRect

$+1C0     75154080  user32.SetWindowTextA

$+1C4     7516F040  user32.MoveWindow

$+1C8     751525B0  user32.GetAsyncKeyState

$+1CC     76580000  "MZ?"

$+1D0     7659F620  advapi32.SetServiceStatus

$+1D4     7659F8A0  advapi32.RegisterServiceCtrlHandlerW

$+1D8     7659DF20  advapi32.OpenProcessToken

$+1DC     765A3910  advapi32.LookupPrivilegeValueA

$+1E0     7659EF80  advapi32.AdjustTokenPrivileges

$+1E4     765B2990  advapi32.CreateProcessAsUserA

$+1E8     7659E7E0  advapi32.InitializeSecurityDescriptor

$+1EC     7659E7C0  advapi32.InitializeAcl

$+1F0     765C45D0  advapi32.LookupAccountNameA

$+1F4     7659E660  advapi32.AddAccessAllowedAce

$+1F8     7659E640  advapi32.SetSecurityDescriptorDacl

$+1FC     765A2840  advapi32.GetUserNameA

$+200     75530000  "MZ?"

$+204     755A59A0  msvcrt.sscanf

$+208     755B94D0  msvcrt.memset

$+20C     755B8CF0  msvcrt.memcpy

$+210     755A4CB0  msvcrt.printf

$+214     75596C30  msvcrt._beginthreadex

$+218     755B9EF0  msvcrt.strtok

$+21C     755B9E60  msvcrt.strstr

$+220     755BF140  msvcrt._time64

$+224     7558C650  msvcrt.rand

$+228     7558BAB0  "j\fh垜]u鐷\x11"

$+22C     755774F0  msvcrt.malloc

$+230     7558C680  msvcrt.srand

$+234     75577310  msvcrt.free

$+238     76E60000  "MZ?"

$+23C     76EBE1D0  ntdll.RtlInitializeCriticalSection

$+240     76E9E8E0  ntdll.RtlEnterCriticalSection

$+244     76E9DE00  ntdll.RtlLeaveCriticalSection

$+248     76EAF940  ntdll.RtlDeleteCriticalSection

$+24C     746A0000  "MZ?"

$+250     746A4FD0  wtsapi32.WTSEnumerateSessionsA

$+254     746A53A0  wtsapi32.WTSQuerySessionInformationA

$+258     746A24A0  wtsapi32.WTSFreeMemory

$+25C     746A1930  wtsapi32.QueryUserToken

$+260     75C60000  "MZ?"

$+264     75DBA520  shell32.CommandLineToArgvW

$+268     75E97CF0  shell32.ShellExecuteA

$+26C     76250000  "MZ?"

$+270     7626A1C0  shlwapi.PathFileExistsA

$+274     73B20000  "MZ?"

$+278     73DC1380  wininet.InternetOpenA

$+27C     73DD8640  wininet.InternetQueryOptionA

$+280     73DDA4B0  wininet.InternetSetOptionA

$+284     73E27000  wininet.InternetConnectA

$+288     73DD7D50  wininet.InternetReadFile

$+28C     73DE2950  wininet.InternetCloseHandle

$+290     73EC41F0  wininet.HttpOpenRequestA

$+294     73DF00F0  wininet.HttpAddRequestHeadersA

$+298     73E32B20  wininet.HttpSendRequestA

$+29C     73DD9EE0  wininet.HttpQueryInfoA

$+2A0     6F780000  "MZ?"

$+2A4     6F7D19B0  dnsapi.DnsGetCacheDataTable

$+2A8     6F7A1DE0  dnsapi.DnsFree

$+2AC     6F793530  dnsapi.DnsQuery_W

        最后初始化的是一个样本之后用到的数据,包括有创建文件的路径,自拷贝的路径等等。该函数是直接赋值,这里直接贴出他的内容。

$ ==>     00000201  

$+4       00000066  

$+8       00000002  

$+C       00000065  

$+10      00000001  

$+14      0123A601  

$+18      02D91248  "D:\\Tencent\\WeChat\\v7.0\nD:\\Tencent\\WeChat\\v7.0\n%ProgramData%\\Tencent\\WeChat\n"

$+1C      02D92448  "CrashReporter.exe"

$+20      02D92478  "%PUBLIC%\\unlimit.flag"

$+24      76ED9800  "鶅}\x08"

$+28      00000000  

$+2C      02D924A8  "%PUBLIC%\\Documents"

$+30      02D924D8  "new.doc"

$+34      76EA0100  ntdll.76EA0100

$+38      02D924F8  "%ProgramData%\\WeiXinCR01"

$+3C      02D92530  "%ProgramData%\\WeiXinCR02"

$+40      00000001  

$+44      00000014  

$+48      00000064  

$+4C      02D92884  

$+50      02D928A8  "Microsoft Word"

$+54      02D928B7  

$+58      00000064  

$+5C      0000000A  

$+60      01200200  

$+64      02D925E8  "127.0.0.\n.0.0.127\n192.168.\n172.16.\n0.0.0.0\n255.255.255.255\n"

$+68      02D92640  ".test\ntest.\n"

$+6C      00000000  

$+70      00000000  

$+74      00000001  

$+78      00000301  

$+7C      0001D4C0  

$+80      00000000  

$+84      00000BB8  

$+88      00026000  

$+8C      00000000  

$+90      02D92668  "WeiXinCrashReporter"

$+94      02D92698  "https://start.firefoxchina.cn\nhttps://www.msn.cn/zh-cn\n"

$+98      02D928BC  "http://39.99.57.67/grief-seed/ribbon-mummy.dat\nhttp://39.99.57.67/grief-seed/marmaid-conductor.dat\nhttp://39.99.57.67/grief-seed/candle-knight.dat\nhttp://39.99.57.67/grief-seed/gramphone-witch.dat\n"

$+9C      00001388  

$+A0      00007530  

$+A4      00000001  

$+A8      02D92982  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.104 Safari/537.36 Edg/89.0.774.76"

$+AC      02D92750  "###@@@WeiXin0099"

$+B0      00000000  

$+B4      00000000  

$+B8      00000003  

$+BC      02D92A06  

$+C0      02D92A09  "0d8d26376410b051421adee91163c5a54a5d5095d47cdf05ae5351de7ba0a153382c6d5778c21726"

$+C4      00EFF320  

$+C8      00000FDC  

$+CC      00000000  

$+D0      01200000  

$+D4      00001F18  

$+D8      00DEF000  

$+DC      01200000  

$+E0      00000000  

$+E4      01200000  

$+E8      00EFF390  

$+EC      00001F18  

$+F0      00001F18  

$+F4      00001F18  

$+F8      00DEF000  

$+FC      00000000  

$+100     00000000

        这里可以看到存在协议头,域名和IP列表,但是网络工具并没有监测到,说明样本没有触发。

        StartMainWork函数头首先是一个调用ExpandEnvironmentStringsA函数,来获取环境变量的值。

        通过前面他初始化的字符串得知这里的环境值为 %PUBLIC%\unlimit.flag,因为这个文件一直不存在,所以紧接着的PathFileExistsA返回0,不进入代码块。

        然后会对本层函数传进来的参数进行判断,因为打开程序时默认不带有命令参数,所以CmdLine为NULL。又因为上面判断flag文件不存在,所以对应的标志位也是为0。此处判断不成立。往下走会判断dataTable + 0x14位置的值是否为0。通过查看dataTable发现这个位置的值恒等于1,所以此处永远是执行的状态。

        进行自我复制的操作。

        因为v73在上面的if没有成立,所以此处的值为默认的1,故此处调用的后两个参数为1,0。然后整个WinMain的执行周期结束。明显关键函数为**CopySelf_And_DoWork**,接下来进入分析。


[2]CopySelf_And_DoWork分析

        进入函数后首先会调用一个popMsgBox_DnsCache,这个函数的是跳出一个信息框然后进行DNS一些查询操作。这里注意的是ida在这里显示的是+0xE的作为参数一,可是在我调试的时候发现这里实际上是0x38,具体原因是啥,我也不清楚。

        现在继续往下看看还会执行什么。

        这里会执行两个函数,通过动态调试得知这里的参数内容如下

pathTable = "D:\\Tencent\\WeChat\\v7.0\nD:\\Tencent\\WeChat\\v7.0\n%ProgramData%\\Tencent\\WeChat\n"

ExistPath = 上面一个函数创建new出来的地址,用于此处函数的out_buffer

        经过内部分析,这个函数作为为对参数一的路径以\r\n分割,然后逐一判断其是否存在,存在则返回到ExistPath。参数三的作用则是,传入0就直接判断路径是否存在,不创建。传入1就是如果路径不存在则创建。因为本人虚拟机只有C盘,故只有第三项路径存在C:\ProgramData\\Tencent\\WeChat。如果所有路径都不存在,则本层函数直接返回,反之执行下列代码。

        图片可能有点乱,大概的流程就是

if ( GetModuleFileNameA(0, &currentPath, 259) )// 获取当前运行时的路径

 {

    if ( lstrcmpA_0(&_crashReportPath, &_currentPath) )// 比较两个文件运行的路径

    {                                         

      // 这里是路径不相同时的处理

      if (CopyFileA(&currentPath, &CrashReportPath, 0) )// 将自身拷贝到目标路径

      {

          if ( PathFileExistsA(&CrashReportPath) )

          {

            wsprintf(&v226, &v395, &CrashReportPath);

            //运行拷贝后的程序

            if ( CreateProcessA(0, &v226, 0, 0, 0, 0, 0, 0, &lpStartupInfo, &lpProcessInformation) )// shellCmd

            {

              CloseHandle_0(lpProcessInformation);

              CloseHandle_0(v10);

            }

          }

      }

    }

    else

    {

        CrashReportMain((int)dataTable, a2, ExistFlag);// CrashReport.exe 执行的函数

    }

 }

        然后本层函数也执行完毕。现在就开始分析重中之中,CrashReportMain

[3]CrashReportMain分析

        首先在x32dbg进行头部下断,查看一下该函数的参数。

参数1 = dataTable

参数2 = 1

参数3 = 0

        函数进来后依旧是popMsgBox_DnsCache函数的调用,这个函数基本上不影响样本功能,所以略过。

        到了这里虽然里面有一个sub_511EB0函数,但是这个条件没有成立,0x24的位置始终为0。这里先继续往下走

        这里的话是判断互斥体名称是否存在,存在的话创建一个互斥体。

        往下继续分析,会看到这里会对上面的错误码进行判断,而且判断的文本为Error : A downloader instance is already,由此可知,这个当前分析的这个CrashReporter样本可能是一个下载器。

        往下执行会执行到这个条件,因为这个sub_4C7B40内部存在sleep函数,单步跳过时会直接卡住。如果返回为true,则会执行下面的sub_5176C0,然后本层函数直接结束掉。这里就直接从sub_4C7B40开始分析。

[4]sub_4C7B40分析

        首先执行第一个函数,CheckMachineIsMatch_FileExist,这个函数会检测是否存在文件C:\ProgramData\WeiXinCR02文件,该文件存放着C盘序列号的CRC32值。如果文件不存在则函数返回0,如果存在则获取C盘的序列号并且计算出CRC32值,然后与文件里的值对比,是否一致。这里由于文件是不存在的,所以返回的为0,下面0x40是1,条件成立直接执行下面的延迟函数。

        safeSleep通过isMatch来计算需要延迟的时间,如果isMatch == true,则延迟2分钟,反之延迟4分钟。

        这里因为为了分析直接先nop掉这个函数执行,并且让返回值为1。

        包括这里isMatch也是0,所以这里也需要改。

        紧接着执行这个位置,函数直接返回1。

        由于没有文件WeiXinCR02,所有在函数尾部,创建了该文件,并写入了C盘序列号的CRC32值,最后也返回1。这个函数整体大概是通过判断文件WeiXinCR02的存在来进行样本休眠,具体的作用可能为了躲过某些检测。

[5]sub_5176C0分析

        进入头部直接是一个urlList的初始化

        往下走会执行一个Requst函数,会对每一个url进行一个get请求和读取源码,之后会执行一个sub_5071A0,这里没分析出具体是干嘛。看到一些加密或解密的函数,估计是在读取网页源码的时候对内容进行解密然后形成shellcode?

        网页操作执行完后,就是文件下载了,这里通过查看数据表发现这里的字符串都是以url\filename的形式存在,然后下面只有一个函数在执行,所以这里基本上可以确定下面的函数是下载这些文件,在这里本人自己去访问一下这些地址,发现已经无法访问了,所以无法下载,这估计也是为什么该样本运行时只有一个信息框弹出,就没有其它反应了,这里进入downloader进行分析。

[6]downloader分析

函数头的字符串提示更加确定这是一个下载函数。

        往下走后会看到样本使用了strtok进行文本分割,然后传入startDownLoad开始下载,下载同时会记录下载的个数,当所有下载完成后,本层函数返回下载的总数。这里注意下上面CrashReporter函数中我少了一个函数没分析,那个函数其实就是这个函数。

[7]startDownLoad分析

        这里定义了一个结构体变量,newMem_8,结构体内容如下

struct unkown

{

  int* urlField;

  int* dataTable

};

        之后会根据参数3进行启动不同的下载线程。


[8]sub_50C610分析

        因为文件已经无法下载了,所以sub_5071A0本人没法继续跟入分析,因为此函数里,基本都是对下载的文件进行image,section校验,且对部分数据进行处理。由于没拿到原文件,所以本人无从下手。



[9]openDoc_download分析

        首先是是对保存路径初始化。

        然后是对文件路径判断是否存在,如果存在则打开改文档。

        否则进行下载。

        下载完成后创建路径,然后再去打开文档。同样,由于文档当前也是无法下载的,导致没法进一步分析。

        至此,该样本分析基本完了,且据目前分析结果来看,该样本也就是个下载器。

总结

        长达一周的分析,终于结束了。因为该样本添加了很多的垃圾代码,导致分析的时候需要翻来翻去,有些关键代码又夹在里面,分析的时候甚是头疼,并且还有很多没用的条件,看起来觉得他会执行,但是动态调试的时候就是不会执行,就很蛋疼。又因为该样本的下载文件地址全部失效,把样本跑起来后整个虚拟机啥问题都没有,监视工具也压根就没啥反应,压根就是一个正常的程序,这更增加了分析难度。刚刚开始接手这个样本时,运行起来和正常程序没什么区别,完全没有找到有关恶意代码的地方,最后被迫无奈,直接从WinMain手撕。整个样本,共106个函数,天天24小时肝。由于压根就没看到有什么恶意代码,使得产生自我怀疑,甚至产生了放弃的念头,但是想到已经分析那么多了,还不如坚持下去。最后把70多个函数全部给分析了,然后已经看出了个大概,其余的就没分析,只看了个流程。


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2021-10-27 12:16 被PlaneJun编辑 ,原因:
收藏
点赞9
打赏
分享
最新回复 (3)
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
葡萄成熟时 2021-10-29 09:24
2
0
可以发一下样本吗
游客
登录 | 注册 方可回帖
返回