
   Micro$oft Windows Sockets Guide
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   by Bumblebee/29a


   Index
   ~~~~~
        1.Overview
        2.What is windows sockets?
        3.Micro$oft extensions
        4.Step by step: make a connection
        5.Read and Write
        Apendix: wsocks.inc


   1.Overview
   ~~~~~~~~~~
  This is not a  'viral-specific'  guide.  I walk through win32 sockets
 implementation of  BSD  socket standards.  This can help you to make a
 remote  connection  with  your  virus to send  an e-mail,  as example.
  It's simply a description of a pieze of code from i-worm.Anaphylaxis.


   2.What is windows sockets?
   ~~~~~~~~~~~~~~~~~~~~~~~~~~
  The Windows Sockets  specification  defines a network programming in-
 terface for Microsoft Windows which  is based on the "socket" paradigm
 popularized in the Berkeley Software Distribution (BSD).It encompasses
 both familiar Berkeley socket style routines and a set of Windows-spe-
 cific extensions  designed to allow the programmer to take "advantage"
 of the message-driven nature of Windows.

  But, what  the hell is a socket? The idea of BSD was a file to remote
 machine.  Sokects are used in  BDS like simple files.  You can use the
 common  'write' and  'read' to write and read from the socket.  But M$
 changes this level of  abstraction and gives you spezial  functions to
 make you remember you're using their damn API.


   3.Micro$oft extensions
   ~~~~~~~~~~~~~~~~~~~~~~
  These are  the functions  provided by  M$ that  are not  avaliable in
 Berkeley:
	         WSAAsyncGetHostByAddr()
		 WSAAsyncGetHostByName()
		 WSAAsyncGetProtoByName()
		 WSAAsyncGetProtoByNumber()
		 WSAAsyncGetServByName()
		 WSAAsyncGetServByPort()
		 WSAAsyncSelect()
		 WSACancelAsyncRequest()
		 WSACancelBlockingCall()
		*WSACleanup()
		 WSAGetLastError()
		 WSAIsBlocking()
		 WSASetBlockingHook()
		 WSASetLastError()
		*WSAStartup()
		 WSAUnhookBlockingHook()

  M$  provides  this  shit  due to  its way to  do  multitasking.  What
 happens if an App waits for a connection?  The connection requires the
 App looks in a constant way if the connection is ok. So the App cannot
 get the messages that is  sending windows.  The functions showed after
 provide a nonblocking work.
  We  are  only  interested in the  funcs with a '*'. The other are not
 needed due to i'm going  to use socks in the  BSD way  (BSD=UNIX=LUNUX
 rulez!).


   4.Step by step: make a connection
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  The first step  is to  do a check of the wsocks  installation in  the
 comp.
 We are going to use  wsocks 1.1, so we make a  check with  WSAStartup.

        push    offset wsadata			; WSADATA struct
        push    VERSION1_1			; we want version 1.1
        call    WSAStartup                      ; check wsocks installation
        cmp     eax,0				; on error:
        jne     qApp				;  exit app

        mov     ax,VERSION1_1			; WSAStartup returns the version
        cmp     ax,word ptr [wsadata.mVersion]  ; test version
        jne     exitAppQsocks                   ; quit sockets and exit App

  
  WSAStartup  need 2  arguments:  a pointer to  WSADATA  struct and the
 version requested.  This  API retuns in the struct i nto .mVersion the
 number of the version  avaliable that you asked  for or the more close
 to your  ask.  Moreover  WSAStartup tells windows  you're going to use
 wsocks.  So a  WSACleanup call is needed  even if the version  not fit
 your requests:

        call    WSACleanup                      ; end wsocks use

  Assume now we have the the version we need.  At this point we need to
 open a socket.

        push    PCL_NONE			; protocol
        push    SOCK_STREAM			; type of socket
        push    AF_INET				; family
        call    socket                          ; open a socket
        cmp     eax,SOCKET_ERR			; on error:
        je      doCleanUp			;  WSACleanup


  Socket needs 3 arguments: the protocol, the type and the family.  The
 protocol can be set but this  make posible windows security fucks  our
 connection.  Example: we want to make a  telnet connection.  If we set
 the  protocol  to  telnet  protocol  and  windows  doesn't allows this
 protocol then our socket fails. So is better to set protocol to none.
  The type of socket can be:  STREAM or DATAGRAM.  First is oriented to
 connection and  second sends  packets that  can arrive to  receiver in
 different  order that they were sent.  Moreover the sender cannot know
 if the packet arrives without the help of the receiver.
  At last is  the  family  that can  be:  AI_UNIX, AF_INET...  but only
 AF_INET addresses are supported in the version i check.
  We use PCL_NONE, SOCK_STREAM and AF_INET. The socket function returns
 SOCKET_ERR (-1) if the  call fails and the  socket handle if  all goes
 fine.

  Last step is make  the connection.  In theory we connect the  socket,
 that is used to manage the connection,  to a remote machine.  First we
 need to fill  the SOCKADDR struct (this is a modified struct: i merged
 different structs due to we are going to use only AF_INET).

	SOCKADDR        struct
	sin_family	dw	0		; ever AF_INET
	sin_port	dw	0		; the port
	sin_addr        dd      0       	; addr of server node
	sin_zero	db	8 dup(0)	; not used 
	SOCKADDR        ends

  Sin_family is easy to fill, but  sin_port and  sin_addr are more com-
 plex.  Sin_port is the port where we want to connect.  But this number
 must be in network byte order. Sockets provides htons for this:

        push    PORT				; number of port
        call    htons                           ; get port in network byte
        mov     word ptr [sockaddr.sin_port],ax ; order

  Htons gets the port and returns a WORD with network byte order.

  Sin_addr  is  the  most complex.  We  need the  addr of  the host  to
 connect.  This is a number  that identifies  the node.  But usually we
 have the 'domain.ext' form (ex: IBM.com, netscape.com,...). So we must
 get it's IP (xxx.xxx.xxx....) that comes in the dotted format and then
 get its address.

        push    offset server			; addr of the string ('oeee.net')
        call    gethostbyname                   ; get the hostent struct
        cmp     eax,0				; on error:
        je      exitQsocksC			; close sock, cleanup and exit app
						; eax contains the pointer to HOSTENT

        mov     eax,dword ptr [eax+HOSTENT_IP]	; get pointer to IP into HOSTENT
        mov     eax,dword ptr [eax]		; get pointer to IP
        mov     dword ptr [sockaddr.sin_addr],eax ; that's all!

        push    sizeOfSockaddr			; the size of sockaddr struct
        push    offset sockaddr			; the addr of sockaddr
        push    dword ptr [fd]			; the handle of the socket
        call    connect                         ; connect now!
        cmp     ax,SOCKET_ERR			; on error:
        je      exitQsocksC			; close sock, cleanup and exit app

  This example is enough clear: we get the  HOSTENT structs that has in
 its  HOSTENT_IP  addr the  IP of the node.  Then fill sin_addr and the
 sockaddr struct  is now ready to  make the connection.  Connect needs:
 the size of the SOCKADDR  struct  (constant due to my modification ;),
 the pointer to SOCKADDR struct and the handle of the socket.

  That's  all.  we only  need to close  the  socket  when  the  work is
 finished using closesocket:

        push    dword ptr [fd]			; handle of the socket
        call    closesocket


    5.Read and Write
    ~~~~~~~~~~~~~~~~
  Miscro$oft provides differnt APIs to read and write but we are going
 to use: send and recv.

        push    0				; normal (can be OOBD too)
        push    ecx				; size of message to send
        push    esi				; addr to message
        push    eax				; socket handle
        call    send

        push    0				; normal
        push    4				; size to read
        push    offset response			; addr to store message
        push    eax				; soket handle
        call    recv

  Send  work  and gives  the same  errors  that _lwrite  and  the same
 occurs with recv and _lread.
  Send  and  recv  are  blocking.  This means  if  you're  sending  or
 receiving and no  data is to  send/receive, the socket blocks the app
 until  the  data is  avaliable,  the connection fails  or the process
 ends. This last is what we need to use.
  We create a thread and the thead makes the connection  and sends/re-
 ceives the messages  (make the communication).  The main process that
 creates the thread only  waits some time to let the  thread work. But
 if the thread is  blocked the time in the main expires. Then the main
 terminates the thread and continues its work.

  That's all folks!




 APENDIX: wsocks.inc

;
;      WSocks.inc: include file for windows sockets .
;      Designed for TASM5 and Win32.
;
;      (C) 1999 Bumblebee.
;
;       This file contains basic structures and stuff to work
;       with windows sockets.
;

; Descriptions of the API:
;  arguments in order of PUSH ;)

; only for debug
extrn   WSAGetLastError:PROC

; starts the use of winsock dll
; addr WSADATA, version requested
; returns: 0 ok
extrn	WSAStartup:PROC

; terminates the use of winsock dll
; returns: SOCK_ERR on error
extrn	WSACleanup:PROC

; opens a new socket
; protocol (PCL_NONE), type (SOCK_??), addr format (AF_??)
; returns: socket id or SOCKET_ERR (socket is dw)
extrn	socket:PROC

; closes a socket
; socket descriptor
;
extrn   closesocket:PROC

; sends data (this socks are a shit... Unix uses simple write)
; flags (1  OOB data or 0 normal ) , length, addr of buffer, socket
; returns: caracters sent or SOCKET_ERR on error
extrn   send:PROC

; reveives data (this socks are a shit... Unix uses simple read)
; flags (use 0), length, addr of buffer, socket
; returns: caracters sent or SOCKET_ERR on error
extrn   recv:PROC

; connects to a server
; sizeof struct SOCKADDR, struct SOCKADDR, socket
; returns: SOCKET_ERR on error
extrn	connect:PROC

; gets the name of the current host
; length of the buffer for name, addr of buffer for name
; return: SOCKET_ERR on error
extrn   gethostname:PROC

; gets strcut hostent
; addr of name
; returns: ponter to the struct or 0 on error
extrn   gethostbyname:PROC

; converts a zstring like "xxx.xxx.xx...." to netw byte order
; zstring ptr to change to dotted addr format
; returns: in_addr (dd)
extrn 	inet_addr:PROC

; dw to convert into netw byte order (usually the port)
; returns: the value in network byte order (dw)
extrn   htons:PROC

; Structs :o

; sockaddr struct for connection
; modified (for better use)
; if you want the original look for it into a winsock.h
SOCKADDR        struct
sin_family	dw	0	; ex. AF_INET
sin_port	dw	0	; use htons for this
sin_addr        dd      0       ; here goes server node (from inet_addr)
sin_zero	db	8 dup(0)
SOCKADDR        ends

; for WSAStartup diagnose
WSADATA		struct
mVersion	dw	0
mHighVersion	dw	0
szDescription	db	257 dup(0)
szSystemStatus	db	129 dup(0)
iMaxSockets	dw	0
iMaxUpdDg	dw	0
lpVendorInfo	dd	0
WSADATA		ends

; Some nice equs 

; what version of winsock do you need? (usually 1.1)
VERSION1_0      equ     0100h
VERSION1_1      equ     0101h
VERSION2_0      equ     0200h

AF_UNIX		equ	1	; local host
AF_INET         equ     2       ; internet (most used)
AF_IMPLINK	equ	3	; arpanet
AF_NETBIOS	equ	17	; NetBios style addresses

; types of sockets
SOCK_STREAM     equ     1       ; stream (connection oriented; telnet like)
SOCK_DGRAM      equ     2       ; datagram (packets, packets, packets)

; protocol
PCL_NONE        equ     0       ; none (define the protocol not needed)

SOCKET_ERR      equ     -1      ; standard winsock error

HOSTENT_IP      equ     10h     ; where is the IP into the hostent struct


APENDIX ENDS
