文件名称: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 反汇编文件