Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Snorting coke (and packets)

GriYo
29a [6]
March 2002

[Back to index] [Comments]

Windows 2000 introduces a new concept for Windows users: The possibility of creating raw-sockets. We will use this new Windows capacity to capture network traffic on a net. What to make with captured packets is your decision, some suggestions are:

As limitation we find that only users with administrator priviledges are allowed to create raw-sockets.

First of all, we have to initialize Windows Sockets, by calling WSAStartup. We must tell WSAStartup that we need Winsock version 2.2+, which will only succeed on windows 2000 or XP.

        invoke WSAStartup,00000202h,addr wsaDATA

        .if eax != 0

                ;Error: WSAStartup

                jmp ExitApp

        .endif
 

The second thing is to create a socket to listen at. Its not a bad idea to run this code in a separate thread, so its execution does not disturb the rest of the application.

        WSA_FLAG_OVERLAPPED     equ     00000001h

        WSockThread             proc    pParam          :DWORD

        LOCAL   s               :SOCKET
        LOCAL   if0             :sockaddr_in
        LOCAL   optval          :DWORD
        LOCAL   dwBytesRet      :DWORD
        LOCAL   dwFlags         :DWORD
        LOCAL   wbuf[8]         :BYTE
                       
        invoke  WSASocket,
                AF_INET,
                SOCK_RAW,
                IPPROTO_IP,
                0,
                0,
                WSA_FLAG_OVERLAPPED

        .if eax == INVALID_SOCKET

                ;Error: WSASocket

                return 0

        .endif
                       
        mov s,eax

        invoke ZeroFill,addr if0,SIZE sockaddr_in

        invoke  WSockGetInterfase,
                s,
                addr if0,
                0

        .if eax == 0

                ;Error: GetInterface

                return 0

        .endif
 

There is a call to a function called WSockGetInterfase in the above code. Dont browse Winsock exported functions looking for it. The code for this function is the next step to code.

WSockGetInterfase is used to obtain a list of available network interfases. To get it we will use SIO_ADDRESS_LIST_QUERY Winsock IOCTL:

        SIO_ADDRESS_LIST_QUERY  equ     48000016h

        WSockGetInterfase       proc    s               :SOCKET,
                                        ifx             :DWORD,
                                        num             :DWORD

        LOCAL   BytesRet        :DWORD
        LOCAL   if_LIST[2048]   :BYTE

        invoke ZeroFill,addr if_LIST,2048

        mov BytesRet,0

        invoke  WSAIoctl,
                s,
                SIO_ADDRESS_LIST_QUERY,
                NULL,
                0,
                addr if_LIST,
                2048,
                addr BytesRet,
                NULL,
                NULL

        .if eax == SOCKET_ERROR

                ;Error: WSAIoctl

                return 0

        .endif

        mov ecx,num

        lea esi,if_LIST
        cld
        lodsd
                       
        .if eax == 0

                ;Error: No interface found

                return 0

        .elseif ecx >= eax

                ;Error: Device number too high

                return 0

        .endif
               
        shl ecx,3
        add esi,ecx
        cld
        lodsd
        add eax,sockaddr_in.sin_addr
        mov esi,eax

        mov edi,ifx
        add edi,sockaddr_in.sin_addr

        cld
        lodsd
        stosd

        return 1

        WSockGetInterfase       endp
 

We call WSAIoctl with the SIO_ADDRESS_LIST_QUERY to obtain a list of local transport addresses of the socket's protocol family to which the application can bind. The list returned in the output buffer using the following format:

        SOCKET_ADDRESS_LIST     STRUCT

        iAddressCount           dd ?
        Address                 dd ?

        SOCKET_ADDRESS_LIST     ENDS
 

WSockGetInterfase uses 3 entry parameters:

Once we have created the socket and we have selected the interface we can call bind to asociated them.

        mov if0.sin_family,AF_INET

        invoke htons,0

        mov if0.sin_port,ax

        invoke  bind,
                s,
                addr if0,
                SIZE sockaddr_in

        .if eax == SOCKET_ERROR

                ;Error: bind

                return 0

        .endif
 

The final trick is to set the SIO_RCVALL mode on the socket, by calling WSAIoctl. Lets have a look at what MSDN Library says about this IOCTL:

SIO_RCVALL:

Enables a socket to receive all IP packets on the network. The socket handle passed to the WSAIoctl function must be of AF_INET address family, SOCK_RAW socket type, and IPPROTO_IP protocol. The socket also must be bound to an explicit local interface, which means that you cannot bind to INADDR_ANY.

Once the socket is bound and the IOCTL set, calls to the WSARecv or recv functions return IP datagrams passing through the given interface.

Note that you must supply a sufficiently large buffer. Setting this IOCTL requires Administrator privilege on the local machine.

SIO_RCVALL is available in Windows 2000 and later versions of Windows.

Well, water clear, lets do it.

        SIO_RCVALL              equ     98000001h

        mov dwBytesRet,0
        mov optval,1

        invoke  WSAIoctl,
                s,
                SIO_RCVALL,
                addr optval,
                4,
                0,
                0,
                addr dwBytesRet,
                0,
                0

        .if eax == SOCKET_ERROR

                ;Error: WSAIoctl

                return 0

        .endif
 

Done, now, on result to WSARecv on this socket we will receive IP packets running around the network, lets see an example.

        lea edi,wbuf
        cld
        mov eax,PACKET_BUFFER_SIZE
        stosd
        lea eax,pcap_buffer
        stosd

        mov dwBytesRet,0
        mov dwFlags,0

        invoke  WSARecv,
                s,
                addr wbuf,
                1,
                addr dwBytesRet,
                addr dwFlags,
                0,
                0

        .if eax == SOCKET_ERROR

                ;Error: WSARecv

                return 0

        .endif

        ;Decode IP header!

        invoke DecodeIpHeader,addr wbuf
 

The DecodeIpHeader function uses a pointer to a WSABUF structure, which contains information about captured network frame. Lets see an example on how to extract the information from it.

        IP_HEADER               STRUCT

        Version_and_HdrLen      db ?
        ServiceType             db ?
        TotalLen                dw ?
        ID                      dw ?
        Flags_and_FragOff       dw ?
        TimeToLive              db ?
        Protocol                db ?
        HdrChksum               dw ?
        SrcAddr                 dd ?
        DstAddr                 dd ?

        IP_HEADER               ENDS

DecodeIpHeader                  proc    Buffer          :DWORD

        LOCAL   szSrcIp[16]     :BYTE

        mov eax,Buffer
        mov esi,[eax+4] ;Buffer points to a WSABUF structure

        mov eax,[esi+IP_HEADER.DstAddr]

        ;Do something here with destination ip address
        ;...
        ;...
        ;...

        mov eax,[esi+IP_HEADER.SrcAddr]

        ;Or do something using source ip address
        ;...
        ;...
        ;...

        mov al,[esi+IP_HEADER.Protocol]

        ;You can also check for specific protocols

        .if al == IPPROTO_TCP

        ;...
        ;...
        ;...

        .elseif al == IPPROTO_UDP

        ;...
        ;...
        ;...

        .elseif al == IPPROTO_ICMP

        ;...
        ;...
        ;...

        .endif

        ret

DecodeIpHeader          endp
 

Thats all folks, happy snorting!

By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxheaven.org aka vx.netlux.org
deenesitfrplruua