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

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

2021-10-27 05:07
19760

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


MD5    fdd9fd0249d48d8c6d991741c67fcfeb

SHA-1    ff0181242825b5bb8cac1d4d17e8377352e3aa55

SHA-256    6a9bdabc4599618513de5c963972929de9322c486e84e101e177c0868e7c5fb7

File size    1.34 MB (1408512 bytes)

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

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

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

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

        途中创建了一些文件

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

ABC

AAC

AAD

BBC

BAC

BAD

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

D2 C2 7E AD 52 06 C4 93

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

        HttpDebuger无任何发现。


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

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


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

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

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

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

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


        在这个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


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

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