文件名称:srv32.exe
蠕虫名称:Net-Worm.Win32.Opasoft.s
工具: IDA 4.5.1, SoftICE3.1
第3,4篇中我们一直在创建的那个线程(401DB0)里打转,跟着程序的思路走我们又回到
第2篇创建线程的位置:
CODE:004012C3 loc_4012C3:
CODE:004012C3 call sub_40148D
CODE:004012C8
CODE:004012C8 loc_4012C8:
CODE:004012C8 call sub_401575 ; 返回值1或0
CODE:004012CD test eax, eax ; 如果打开文件srv32tsk出错,eax == 0
CODE:004012CF jnz short loc_4012E5
CODE:004012D1 call sub_40148D ;---->线程(401DB0)在这里创建
CODE:004012D6 push 0FFFFFFFFh ; dwMilliseconds = INFINITE
CODE:004012D8 push ds:hThreadHandle ; hHandle
CODE:004012DE call WaitForSingleObject ; 等待线程结束
CODE:004012E3 jmp short loc_4012C8
CODE:004012E5 ; ///////////////////////////////////////////////////////////////////////////
CODE:004012E5
CODE:004012E5 loc_4012E5:
CODE:004012E5 push offset dword_406597
CODE:004012EA call sub_403332
CODE:004012EF add esp, 4
CODE:004012F2 mov ds:byte_406285, 1
CODE:004012F9 push ds:dword_4065A7
CODE:004012FF push offset unk_4065AB
CODE:00401304 push offset unk_40659F
CODE:00401309 call sub_403431
CODE:0040130E test ds:byte_406285, 1
CODE:00401315 jz short loc_4012A3
CODE:00401317 call sub_40178E
CODE:0040131C push eax
CODE:0040131D call sub_401675
CODE:00401322 call sub_401634
CODE:00401327 jmp short loc_4012C3
CODE:00401329 ; ///////////////////////////////////////////////////////////////////////////
CODE:00401329
CODE:00401329 locret_401329:
CODE:00401329 leave
CODE:0040132A retn
CODE:0040132A sub_40123E endp
在主线程sub_40123E 中调用call sub_40148D创建了第3,4篇中介绍的线程,随后主线程
又调用WaitForSingleObject(hThreadhandle, INFINITE)等待创建的线程(401DB0)
结束,WaitForSingleObject返回后主线程回跳倒loc_4012C8:在sub_401575中对文件
srv32tsk进行了读写操作如下:
CODE:00401575 sub_401575 proc near
CODE:00401575
CODE:00401575 var_ReturnValue = dword ptr -4
CODE:00401575
CODE:00401575 enter 4, 0
CODE:00401579 push esi
CODE:0040157A mov [ebp+var_ReturnValue], 0
CODE:00401581 push offset dword_406587
CODE:00401586 call icy_ReadFileSrv32tsk ; 读文件Srv32tsk的内容,存放到[406587]
CODE:0040158B cmp eax, 0FFFFFFFFh
CODE:0040158E jz short loc_4015E1 ; 打开文件srv32tsk失败则退出并返回0
CODE:00401590 mov esi, eax
CODE:00401592 mov [ebp+var_ReturnValue], 1
CODE:00401599 cmp ds:dword_406593, 0 ; 从文件srv32tsk开始的第4个DWORD值
CODE:004015A0 jz short loc_4015AA
CODE:004015A2 push esi ; hObject
CODE:004015A3 call CloseHandle ; 关闭文件
CODE:004015A8 jmp short loc_4015E1 ; 退出
CODE:004015AA ; ///////////////////////////////////////////////////////////////////////////
CODE:004015AA
CODE:004015AA loc_4015AA:
CODE:004015AA cmp ds:dword_40658B, 0 ; 从文件开始的第2个DWORD值
CODE:004015B1 jz short loc_4015D9
CODE:004015B3
CODE:004015B3 loc_4015B3:
CODE:004015B3 call sub_40171C
CODE:004015B8 mov ds:dword_406593, 1 ; 从文件srv32tsk开始的第4个DWORD值
CODE:004015C2 mov ds:dword_40658B, 0 ; 从文件srv32tsk开始的第2个DWORD值
CODE:004015CC push offset dword_406587
CODE:004015D1 push esi
CODE:004015D2 call icy_WriteFileSrv32tsk ; 写文件srv32tsk
CODE:004015D7 jmp short loc_4015E1
CODE:004015D9 ; ///////////////////////////////////////////////////////////////////////////
CODE:004015D9
CODE:004015D9 loc_4015D9:
CODE:004015D9 inc ds:dword_40658F ; 从文件srv32tsk开始的第3个DWORD值
CODE:004015DF jmp short loc_4015B3
CODE:004015E1 ; ///////////////////////////////////////////////////////////////////////////
CODE:004015E1
CODE:004015E1 loc_4015E1:
CODE:004015E1 mov eax, [ebp+var_ReturnValue]
CODE:004015E4 pop esi
CODE:004015E5 leave
CODE:004015E6 retn
CODE:004015E6 sub_401575 endp
先调用icy_ReadFileSrv32tsk 读文件srv32tsk,上一篇从Internet得到的srv32tsk的
结构如下:
struct tagSrv32tskFile
{
DWORD dwTValue; //ebp-834h
DWORD unknown1 = 1; //ebp-830h
DWORD dwKValue; //ebp-82Ch
DWORD unknown2 = 0; //ebp-828h
DWORD unknown3; //ebp-824h
DWORD unknown4; //ebp-820h
INT64 PValue; //ebp-81Ch
DWORD dwCount; //ebp-814h
BYTE CValue[744] //ebp-810h
};
判断第4个DWORD值是否为0,0表示第一次操作srv32tsk文件,需要调用下面的一些函数对文件srv32tsk
的某些字段进行转换,1表示已经操作过srv32tsk,在sub_40171C中对dwKValue和存放srv32tsk内容的
缓冲区地址的值 进行RCL移位等转换操作后把结果存到srv32tsk的第5个DW值,把第6个DWORD值清0。
call sub_40171C:
CODE:0040171C sub_40171C proc near ; CODE XREF: sub_401575+3Ep
CODE:0040171C mov eax, ds:dword_40658F ; dword_40658F:dwKValue
CODE:00401721 rcl eax, 0Dh
CODE:00401724 rcl edx, 1 ; edx为内存中srv32tsk的缓冲区地址
CODE:00401726 rcl eax, 1
CODE:00401728 rcl edx, 1
CODE:0040172A rcl eax, 1
CODE:0040172C rcl edx, 1
CODE:0040172E rcl eax, 1
CODE:00401730 rcl edx, 1
CODE:00401732 rcl eax, 1
CODE:00401734 rcl edx, 4
CODE:00401737 rcl eax, 1
CODE:00401739 rcl edx, 1
CODE:0040173B rcl eax, 1
CODE:0040173D rcl edx, 3
CODE:00401740 rcl eax, 1
CODE:00401742 rcl edx, 1
CODE:00401744 rcl eax, 1
CODE:00401746 rcl edx, 1
CODE:00401748 rcl eax, 1
CODE:0040174A rcl edx, 2
CODE:0040174D rcl eax, 1
CODE:0040174F rcl edx, 1
CODE:00401751 rcl eax, 1
CODE:00401753 rcl edx, 1
CODE:00401755 rcl eax, 1
CODE:00401757 rcl edx, 1
CODE:00401759 rcl eax, 1
CODE:0040175B rcl edx, 1
CODE:0040175D rcl eax, 1
CODE:0040175F rcl edx, 1
CODE:00401761 rcl eax, 1
CODE:00401763 rcl edx, 1
CODE:00401765 rcl eax, 1
CODE:00401767 rcl edx, 2
CODE:0040176A rcl eax, 1
CODE:0040176C rcl edx, 1
CODE:0040176E rcl eax, 1
CODE:00401770 rcl edx, 1
CODE:00401772 rcl eax, 1
CODE:00401774 rcl edx, 6
CODE:00401777 and edx, 0F8CEFEE0h
CODE:0040177D bswap edx
CODE:0040177F mov ds:dword_406597, edx ; 文件srv32tsk的第5个DW值
CODE:00401785 xor edx, edx
CODE:00401787 mov ds:dword_40659B, edx ; 文件srv32tsk的第6个DW值
CODE:0040178D retn
CODE:0040178D sub_40171C endp
接下来icy_WriteFileSrv32tsk用更改后的缓冲区内容重写srv32tsk文件,随后sub_401575退出返回值1。
CODE:004012C8 call sub_401575 ; 返回值1或0
CODE:004012CD test eax, eax ; 如果打开文件srv32tsk出错,eax == 0
CODE:004012CF jnz short loc_4012E5
跳转实现,jmp到:
CODE:004012E5 ; ///////////////////////////////////////////////////////////////////////////
CODE:004012E5
CODE:004012E5 loc_4012E5:
CODE:004012E5 push offset dword_406597 ; srv32tsk第5个DWORD值
CODE:004012EA call sub_403332
CODE:004012EF add esp, 4
CODE:004012F2 mov ds:byte_406285, 1
CODE:004012F9 push ds:dword_4065A7
CODE:004012FF push offset unk_4065AB
CODE:00401304 push offset unk_40659F
CODE:00401309 call sub_403431
CODE:0040130E test ds:byte_406285, 1
CODE:00401315 jz short loc_4012A3
CODE:00401317 call sub_40178E
CODE:0040131C push eax
CODE:0040131D call sub_401675
CODE:00401322 call sub_401634
CODE:00401327 jmp short loc_4012C3
CODE:00401329 ; ///////////////////////////////////////////////////////////////////////////
CODE:00401329
CODE:00401329 locret_401329:
CODE:00401329 leave
CODE:0040132A retn
CODE:0040132A sub_40123E endp
这里本应该调用几个函数sub_403332,sub_403431,sub_40178E,sub_401675,sub_401634
Jmp到loc_4012C3继续call sub_40148D,可在sub_403431中一直循环好像出不来了,
我想作者不会是为了耗系统资源而写的这个函数吧,不过偶实属菜鸟,希望能看得懂函数sub_403431
的大虾们指点一二,到这里整个程序的执行已经基本结束,你也许认为srv32没有传播自己,也没对
网络进行任何得攻击;作为蠕虫怎么会不传播自己呢,还记得在第4篇得时候有两个线程没有被执行吗.
在如下位置:
CODE:00402224 call sub_401C49 ; 写注册表 srv32
CODE:00402229 cmp ds:Data, 0
CODE:00402230 jz short loc_402239
CODE:00402232 call sub_4030EB <<<<<这里创建了两个线程,做个标记
CODE:00402237 jmp short loc_40223E
由于每次ds:Data的值都为0,所以这两个线程被跳过;Data的值为从http://63.246.135.48/r.php?t=0
读到的D=?的值,srv32的作者可能是通过D=0中止了蠕虫的继续传播。
附件:srv32 IDA 反汇编文件
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)