Kernel mode sockets library for the masses[zt]

Kernel mode sockets library for the masses
By: valerino

Kernel mode sockets library

It's my birthday today (just turned 31 the 31st december, funny eh ?!), i wanted to publish something,
it makes me feel alive. Christ lived 33 years only, if i'd be the new Christ
i've only 2 years left, so better to share my knowledge now :)

Well, here you have a fully functional TDI sockets library. You can connect,
send, receive, all from your supa-dupa-l333t kernelmode rootkit. Yes, you can
bypass lame TDI firewalls with this. No, you can't bypass ndis firewalls.
(read : you can bypass norton's firewall).

Consider that something like this worths $400+ from PCAUSA, and maybe more
from OSR (KSOCKS)..... enough for a new year's present :)

Usage : you have to hook //device/tcp yourself and set the global variable TcpIpDevice.
Then call KSocketInitialize and you're done. Refer to the source for usage.... it shouldn't be hard.

have fun, and happy 2006 to everyone ! Ciao! :)




-----------------------------------------sockets.c------------------------------

//************************************************************************
//                                                                      
// sockets.c
// (c) valerino/xOANINO 2003/2004/2005
//
// this module implements a generic kernel sockets library.
// ** Beware that this is optimized for single thread use if REUSE_SOCKETSIRP is defined.**
//*****************************************************************************

#include "ntifs.h"

#define MODULE "**SOCKETS**"

#ifdef DBG
#ifdef NO_SOCKETS_DBGMSG
#undef KDebugPrint
#define KDebugPrint(DbgLevel,_x)
#endif
#endif

/************************************************************************/
// BOOL KSocketInitialize()
//
// Initialize kernelsockets library
//
/************************************************************************/
BOOL KSocketInitialize()
{
    ExInitializePagedLookasideList(&LookasideSocketMem, NULL, NULL, 0, 1024, 'lskN', 0);
    ExInitializePagedLookasideList(&LookasideSocket,NULL,NULL,0,sizeof (KSOCKET),'cosN',0);
    
#ifdef REUSE_SOCKETSIRP
    // check for tcpdevice
    if (!TcpIpDevice)
        return TRUE;
    
    // allocate the single irp we use throughout the sockets library
    SocketsIrp = IoAllocateIrp(TcpIpDevice->StackSize + 1, FALSE);
    if (!SocketsIrp)
        return FALSE;
#endif
    return TRUE;
}

/************************************************************************/
// PVOID KSocketAllocatePool(VOID)
//
// Allocate memory from sockets lookaside                                                                     
//
/************************************************************************/
PVOID KSocketAllocatePool(VOID)
{
    PCHAR    p    = NULL;

    p = ExAllocateFromPagedLookasideList(&LookasideSocketMem);
    if (p)
        memset(p, 0, SMALLBUFFER_SIZE);
    return p;
}

/************************************************************************/
// void KSocketFreePool(PVOID pBuffer)
//
// Free memory to sockets lookaside                                                                     
//
/************************************************************************/
void KSocketFreePool(PVOID pBuffer)
{
    ExFreeToPagedLookasideList(&LookasideSocketMem, pBuffer);
}

/************************************************************************/
// NTSTATUS KSocketCloseObject(HANDLE Handle, PFILE_OBJECT FileObject)
//
// Release a socket object
//
/************************************************************************/
NTSTATUS KSocketCloseObject(HANDLE Handle, PFILE_OBJECT FileObject)
{
    NTSTATUS    Status    = STATUS_SUCCESS;
    
    // dereference referenced object (called for connection and address)
    if (FileObject)
        ObDereferenceObject(FileObject);
    
    // close socket
    if (Handle)
        Status = ZwClose(Handle);
    
    return Status;
}

/************************************************************************/
// PFILE_FULL_EA_INFORMATION KSocketBuildEaValues(PVOID EaName, ULONG NameLength, PVOID EaValue,
//    ULONG ValueLength, PULONG EaLength)
//
// Build EA information for the socket object
//
/************************************************************************/
PFILE_FULL_EA_INFORMATION KSocketBuildEaValues(PVOID EaName, ULONG NameLength, PVOID EaValue,
    ULONG ValueLength, PULONG EaLength)
{
    PFILE_FULL_EA_INFORMATION    Ea;

    *EaLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + NameLength + 1 + ValueLength;

    // allocate ea buffer
    Ea = ExAllocatePool(PagedPool, *EaLength);
    if (!Ea)
        return NULL;

    // fill buffer with EA values requested
    Ea->NextEntryOffset = 0;
    Ea->Flags = 0;
    Ea->EaNameLength = (UCHAR) NameLength;
    Ea->EaValueLength = (USHORT) ValueLength;
    memcpy (Ea->EaName,EaName,Ea->EaNameLength + 1);
    if (EaValue && EaLength)
        memcpy (&Ea->EaName[NameLength + 1],EaValue,ValueLength);
    
    return Ea;
}

/************************************************************************/
// NTSTATUS KSocketOpenAddress(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
//
// Open address                                                                    
//
/************************************************************************/
NTSTATUS KSocketOpenAddress(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
{
    UNICODE_STRING                Name;
    OBJECT_ATTRIBUTES            ObjectAttributes;
    PFILE_FULL_EA_INFORMATION    Ea    = NULL;
    ULONG                        EaLength;
    IO_STATUS_BLOCK                Iosb;
    NTSTATUS                    Status;
    TA_IP_ADDRESS                Sin;

    // initialize address
    Sin.TAAddressCount = 1;
    Sin.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    Sin.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
    Sin.Address[0].Address[0].sin_port = 0; // INADDR_ANY;
    Sin.Address[0].Address[0].in_addr = 0;

    // get EA values for address
    Ea = KSocketBuildEaValues(TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH, &Sin,
            sizeof(TA_IP_ADDRESS), &EaLength);
    if (!Ea)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto __exit;
    }

    // open tcp device
    RtlInitUnicodeString(&Name, TCPIP_DEVICE);
    InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, 0);
    Status = ZwCreateFile(Handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &Iosb, 0,
        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,FILE_OPEN_IF,0, Ea, EaLength);
    if (!NT_SUCCESS(Status))
        goto __exit;
    
    Status = ObReferenceObjectByHandle(*Handle, FILE_ANY_ACCESS, 0, KernelMode, FileObject, NULL);

__exit:
    if (Ea)
        ExFreePool(Ea);

    return Status;
}

/************************************************************************/
// NTSTATUS KSocketOpenConnection(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
//
// open connection                                                                    
//
/************************************************************************/
NTSTATUS KSocketOpenConnection(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
{
    UNICODE_STRING                Name;
    OBJECT_ATTRIBUTES            ObjectAttributes;
    PFILE_FULL_EA_INFORMATION    Ea    = NULL;
    ULONG                        EaLength;
    IO_STATUS_BLOCK                Iosb;
    NTSTATUS                    Status;

    // get EA values for connection
    Ea = KSocketBuildEaValues(TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH, &Context,
            sizeof(PKSOCKET), &EaLength);
    if (!Ea)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto __exit;
    }

    // open tcp device
    RtlInitUnicodeString(&Name, TCPIP_DEVICE);
    InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, 0);
    Status = ZwCreateFile(Handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &Iosb, 0,
        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,FILE_OPEN_IF, 0, Ea, EaLength);
    if (!NT_SUCCESS(Status))
        goto __exit;

    Status = ObReferenceObjectByHandle(*Handle, FILE_ANY_ACCESS, 0, KernelMode, FileObject, NULL);

__exit:
    if (Ea)
        ExFreePool(Ea);

    return Status;
}

//************************************************************************
// NTSTATUS KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)                                                                     
//  
// Socket completion routine
//************************************************************************/
NTSTATUS KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    PMDL mdl = NULL;
    PMDL nextMdl = NULL;
    PKSOCKET_CTX Ctx = (PKSOCKET_CTX)Context;
    
    // set status block
    Ctx->Iosb.Status = Irp->IoStatus.Status;
    Ctx->Iosb.Information = Irp->IoStatus.Information;
    
    // Free any associated MDL.
    if (Irp->MdlAddress != NULL)
    {
        for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl)
        {
            nextMdl = mdl->Next;
            MmUnlockPages(mdl);
            
            // This function will also unmap pages.
            IoFreeMdl(mdl);
        }

        // set mdl address to null, to prevent iofreeirp to attempt to free it again
        Irp->MdlAddress = NULL;
    }
        
#ifdef REUSE_SOCKETSIRP
    // set irp for reuse
    IoReuseIrp (Irp,STATUS_SUCCESS);
#else
    // free irp
    IoFreeIrp (Irp);
#endif
    // set event
    if (Ctx)
        KeSetEvent (&Ctx->Event,IO_NO_INCREMENT,FALSE);
    
    return STATUS_MORE_PROCESSING_REQUIRED;
}

//************************************************************************
// NTSTATUS KSocketAssociateAddress(HANDLE Address, PFILE_OBJECT Connection)                                                                     
//  
// Associate address
//************************************************************************/
NTSTATUS KSocketAssociateAddress(HANDLE Address, PFILE_OBJECT Connection)
{
    PDEVICE_OBJECT    DeviceObject;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    KSOCKET_CTX        Ctx;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
    
    // allocate TDI_ASSOCIATE_ADDRESS irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build irp (this set completion routine too)
    TdiBuildAssociateAddress(Irp, DeviceObject, Connection,KSocketComplete, &Ctx, Address);
    
    // call tcpip
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketAssociateAddress timeout occurred ***************** cancelling IRP/n", MODULE));
                
            // cancel irp
            IoCancelIrp(Irp);
            
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }    
    }

    return Status;
}

//************************************************************************
// NTSTATUS KSocketConnect(PKSOCKET pSocket, ULONG Address, USHORT Port)
//  
// Connect socket to address:port                                                                   
//************************************************************************/
NTSTATUS KSocketConnect(PKSOCKET pSocket, ULONG Address, USHORT Port)
{
    PDEVICE_OBJECT        DeviceObject;
    PIRP                Irp = NULL;
    NTSTATUS            Status = STATUS_TIMEOUT;
    KSOCKET_CTX            Ctx;
    TDI_CONNECTION_INFORMATION    RequestInfo;
    TA_IP_ADDRESS            RemoteAddress;
    PFILE_OBJECT            Connection;
    
    KDebugPrint (2,("%s KSocketConnect called./n",MODULE));

    if (!pSocket)
        return STATUS_UNSUCCESSFUL;
    
    // set parameters
    Connection = pSocket->ConnectionFile;
    memset (&RequestInfo,0, sizeof(TDI_CONNECTION_INFORMATION));
    memset (&RemoteAddress,0,sizeof (TA_IP_ADDRESS));
    
    RemoteAddress.TAAddressCount = 1;
    RemoteAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    RemoteAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
    RemoteAddress.Address[0].Address[0].sin_port = Port;
    RemoteAddress.Address[0].Address[0].in_addr = Address;
    
    RequestInfo.UserDataLength = 0;
    RequestInfo.UserData = NULL;
    RequestInfo.OptionsLength = 0;
    RequestInfo.Options = NULL;
    RequestInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
    RequestInfo.RemoteAddress = &RemoteAddress;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
    
    // allocate TDI_CONNECT irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    
    // build irp (this set completion routine too)
    TdiBuildConnect (Irp, DeviceObject,Connection,KSocketComplete, &Ctx,NULL, &RequestInfo,&RequestInfo);
    
    // call tcpip
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketConnect timeout occurred ***************** cancelling IRP/n", MODULE));
                
            // cancel irp
            IoCancelIrp(Irp);
            
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
            // ok
            Status = Ctx.Iosb.Status;
    }
    
    if (Status == STATUS_SUCCESS)
        pSocket->Connected = TRUE;
    
       return Status;
}


//************************************************************************
// NTSTATUS KSocketDisconnect(PKSOCKET pSocket
//  
// Disconnect socket                                                                   
//************************************************************************/
NTSTATUS KSocketDisconnect(PKSOCKET pSocket)
{
    PDEVICE_OBJECT    DeviceObject;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    TDI_CONNECTION_INFORMATION    ReqDisconnect;
    PFILE_OBJECT    Connection;
    ULONG Flags;
    KSOCKET_CTX    Ctx;
    
    // check if socket is already disconnected
    if (!pSocket)
        return STATUS_UNSUCCESSFUL;
    
    if (!pSocket->Connected)
        return STATUS_ALREADY_DISCONNECTED;
    
    // set parameters
    Connection = pSocket->ConnectionFile;
    memset(&ReqDisconnect,0,sizeof (TDI_CONNECTION_INFORMATION));
    Flags = TDI_DISCONNECT_ABORT;

       // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
        
    // allocate TDI_DISCONNECT irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build irp (this set completion routine too)
    TdiBuildDisconnect (Irp, DeviceObject,Connection,KSocketComplete, &Ctx, NULL,Flags,&ReqDisconnect,&ReqDisconnect);
    
    // call tcpip
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketDisconnect timeout occurred ***************** cancelling IRP/n", MODULE));
                    
            // cancel irp
            IoCancelIrp(Irp);
                
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }    
    }
    
    if (NT_SUCCESS (Status))
        pSocket->Connected = FALSE;
    
    return Status;
}

//************************************************************************
// NTSTATUS KSocketSend(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesSent)
//  
// Send buffer thru socket                                                                   
//************************************************************************/
NTSTATUS KSocketSend(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesSent)
{
    PDEVICE_OBJECT    DeviceObject;
    PFILE_OBJECT    Connection;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    KSOCKET_CTX Ctx;
    PMDL            Mdl;
    
    KDebugPrint (2,("%s KSocketSend called./n",MODULE));
    
    if (!pSocket)
        return STATUS_UNSUCCESSFUL;

    // set parameters
    Connection = pSocket->ConnectionFile;
    *BytesSent = 0;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
            
    // allocate TDI_SEND irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build mdl
    Mdl = IoAllocateMdl(Buffer, Size, FALSE, FALSE, NULL);
    if (!Mdl)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        IoFreeIrp (Irp);
        return Status;
    }
    
    __try
    {
        MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        IoFreeMdl (Mdl);
        IoFreeIrp (Irp);
        Status = STATUS_UNSUCCESSFUL;
        return Status;
    }
    Mdl->Next = NULL;
    
    // build irp (this set completion routine too)
    TdiBuildSend (Irp, DeviceObject,Connection,KSocketComplete, &Ctx,Mdl,0,Size);
    
    // call tcp
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
               KDebugPrint (1, ("%s ***************** KSocketSend timeout occurred ***************** cancelling IRP/n", MODULE));
                    
            // cancel irp
            IoCancelIrp(Irp);
                    
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);
            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }
    }
    
    // return sent bytes
    *BytesSent = Ctx.Iosb.Information;
    
    // check transferred bytes
    if (Ctx.Iosb.Information != Size)
        Status = STATUS_CONNECTION_ABORTED;

    if (!NT_SUCCESS(Status))
    {
        KDebugPrint(1, ("%s KSocketSend returned error %08x (ReqSent:%d,OkSent:%d)/n", MODULE, Status,
            Size, *BytesSent));
    }
    
    return Status;
}

//************************************************************************
// NTSTATUS KSocketReceive(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesReceived, BOOLEAN ReceivePeek)
//  
// Receive buffer thru socket                                                                   
//************************************************************************/
NTSTATUS KSocketReceive(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesReceived, BOOLEAN ReceivePeek)
{
    PDEVICE_OBJECT    DeviceObject;
    PFILE_OBJECT    Connection;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    PMDL            Mdl;
    ULONG            Flags;
    KSOCKET_CTX        Ctx;
        
    KDebugPrint (2,("%s KSocketReceive called./n",MODULE));
    
    if (!pSocket)
        return STATUS_UNSUCCESSFUL;
    
    // set parameters
    Connection = pSocket->ConnectionFile;
    *BytesReceived = 0;
    
    if (ReceivePeek)
        Flags = TDI_RECEIVE_PEEK;
    else
        Flags = TDI_RECEIVE_NORMAL;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
                
    // allocate TDI_RECEIVE irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build mdl
    Mdl = IoAllocateMdl(Buffer, Size, FALSE, FALSE, NULL);
    if (!Mdl)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        IoFreeIrp (Irp);
        return Status;
    }
    
    __try
    {
        MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        IoFreeMdl (Mdl);
        IoFreeIrp (Irp);
        Status = STATUS_UNSUCCESSFUL;
        return Status;
    }
    Mdl->Next = NULL;
    
    // build irp (this set completion routine too)
    TdiBuildReceive (Irp, DeviceObject,Connection,KSocketComplete, &Ctx,Mdl,Flags,Size);
    
    // call tcp
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketReceive timeout occurred ***************** cancelling IRP/n", MODULE));
                    
            // cancel irp
            IoCancelIrp(Irp);
                    
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }
    }
    
    // return received bytes
    *BytesReceived = Ctx.Iosb.Information;
    
    // check received bytes
    if (Ctx.Iosb.Information == 0)
        Status = STATUS_CONNECTION_ABORTED;

    if (!NT_SUCCESS(Status))
    {
        KDebugPrint(1, ("%s KSocketReceive returned error %08x (ReqRecv:%d,OkRecv:%d)/n", MODULE, Status,
            Size, *BytesReceived));
    }
    
    return Status;
}

//************************************************************************
// VOID KSocketClose(PKSOCKET Socket)                                                                     
//  
// Close socket and Release socket memory                                                                   
//************************************************************************/
VOID KSocketClose(PKSOCKET Socket)
{
    if (Socket == NULL)
    {
        return;
    }

    KSocketCloseObject(Socket->TransportAddressHandle, Socket->TransportAddress);
    KSocketCloseObject(Socket->ConnectionFileHandle, Socket->ConnectionFile);

    ExFreeToPagedLookasideList (&LookasideSocket,Socket);

    Socket = NULL;
}

//************************************************************************
// NTSTATUS KSocketCreate(OUT PKSOCKET* Socket)                                                                     
//  
// Create socket                                                                   
//************************************************************************/
NTSTATUS KSocketCreate(OUT PKSOCKET* Socket)
{
    NTSTATUS    Status    = STATUS_SUCCESS;
    PKSOCKET    iSocket    = NULL;

#ifdef ALWAYS_DISABLESOCKETS
    KDebugPrint(1,("%s Sockets disabled, connect skipped./n", MODULE));
    return STATUS_UNSUCCESSFUL;
#endif
    
    // check disabled sockets
    if (DisableSockets)
    {
        KDebugPrint(1,("%s Sockets disabled, connect skipped./n", MODULE));
        return STATUS_UNSUCCESSFUL;
    }
    
    // handle KAV (crash if not patched)
    ModulePatchKAV();

    // allocate memory for a new socket
    iSocket = ExAllocateFromPagedLookasideList(&LookasideSocket);
    if (!iSocket)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto __exit;
    }
    memset (iSocket,0, sizeof(KSOCKET));

    // open transport address
    Status = KSocketOpenAddress(&iSocket->TransportAddressHandle, &iSocket->TransportAddress,
        iSocket);
    if (!NT_SUCCESS(Status))
        goto __exit;

    // create connection endpoint
    Status = KSocketOpenConnection(&iSocket->ConnectionFileHandle, &iSocket->ConnectionFile,
                iSocket);
    if (!NT_SUCCESS(Status))
        goto __exit;

    // associate address with connection
    Status = KSocketAssociateAddress(iSocket->TransportAddressHandle, iSocket->ConnectionFile);
    if (!NT_SUCCESS(Status))
        goto __exit;
    
__exit:
    if (!NT_SUCCESS(Status))
    {
        if (iSocket)
            KSocketClose(iSocket);
        *Socket = NULL;
    }
    else
        *Socket = iSocket;

    return Status;
}

/************************************************************************/
// NTSTATUS KSocketReadLine(PKSOCKET pSocket, PCHAR buf, SIZE_T maxlen, PSIZE_T ReceivedBytes)
//
// Read line (ascii) from network
//
/************************************************************************/
NTSTATUS KSocketReadLine(PKSOCKET pSocket, PCHAR buf, SIZE_T maxlen, PSIZE_T ReceivedBytes)
{
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    UCHAR c = 0;
    ULONG i = 0;
    ULONG received = 0;

    // check params
    if (!pSocket || !buf || !ReceivedBytes || !maxlen)
        goto __exit;
    
    *ReceivedBytes = 0;
    if (!pSocket->Connected)
        goto __exit;
    
    // read line char by char, and stop at EOL
    memset (buf, 0, maxlen);
    while (TRUE)
    {
        if (i == maxlen)
            break;
        
        // get char from socket
        Status = KSocketReceive (pSocket,&c,1,&received,FALSE);
        if (!NT_SUCCESS (Status) || received == 0)
            break;
        
        // write char into buffer and advance
        *buf = c;
        buf++;
        i++;
        
        // check for EOL
        if (c == '/n')
        {
            *ReceivedBytes = i;
            break;
        }
    }
    
__exit:
    // treat 0 size received as error
    if (received == 0)
        Status = STATUS_NO_DATA_DETECTED;
    
    return Status;
}

/************************************************************************/
// NTSTATUS KSocketWriteLine(PKSOCKET pSocket, const char* format, ...)
//
// write formatted line (ascii) to network
//
/************************************************************************/
NTSTATUS KSocketWriteLine(PKSOCKET pSocket, const char* format, ...)
{
    va_list        ap;
    char*        buf;
    ULONG        len;
    NTSTATUS    Status;
    SIZE_T        BytesSent    = 0;

    // allocate memory
    buf = KSocketAllocatePool();
    if (!buf)
        return STATUS_INSUFFICIENT_RESOURCES;

    // build line
    va_start(ap, format);
    _vsnprintf(buf, SMALLBUFFER_SIZE, format, ap);
    va_end(ap);
    len = strlen(buf);
    
    // send
    Status = KSocketSend(pSocket, buf, len, &BytesSent);

    // free buffer
    KSocketFreePool(buf);

    // check if we've sent all bytes
    if (BytesSent < len)
        return STATUS_UNSUCCESSFUL;
    
    return Status;
}

-----------------------------------------sockets.h------------------------------

#ifndef __sockets_h__
#define __sockets_h__

#define REUSE_SOCKETSIRP

// debugprint with debuglevel (if dbglevel == debug level, it triggers)
#if DBG
#define KDebugPrint(DbgLevel,_x) { /
if (DbgLevel == DEBUG_LEVEL)       
{                                  
DbgPrint _x;                       
}                                  
}
#else
#define KDebugPrint(DbgLevel,_x)
#endif //DBG

//#define ALWAYS_DISABLESOCKETS

//************************************************************************
// kernel sockets                                                                     
//                                                                      
//************************************************************************/
PDEVICE_OBJECT            TcpIpDevice;

typedef struct __tagKSOCKET
{
    PFILE_OBJECT                TransportAddress;
    HANDLE                        TransportAddressHandle;
    PFILE_OBJECT                ConnectionFile;
    HANDLE                        ConnectionFileHandle;
    BOOLEAN                        Connected;
}KSOCKET, * PKSOCKET;

typedef struct _tagKSOCKET_CTX {
    KEVENT Event;
    IO_STATUS_BLOCK Iosb;
} KSOCKET_CTX, *PKSOCKET_CTX;

PAGED_LOOKASIDE_LIST    LookasideSocketMem;
PAGED_LOOKASIDE_LIST    LookasideSocket;
KEVENT                    NoNetworkFailures;
BOOLEAN                    DisableSockets;                    // flag to disable sockets if needed
PDRIVER_DISPATCH        OriginalTcpInternalDeviceControl;
PIRP                    SocketsIrp;

// all paged code except the completion routine
BOOL                    KSocketInitialize();
#pragma alloc_text        (PAGEboom,KSocketInitialize)

NTSTATUS                KSocketCreate(OUT PKSOCKET* Socket);

VOID                    KSocketClose(PKSOCKET Socket);

PVOID                    KSocketAllocatePool();

void                    KSocketFreePool(PVOID pBuffer);

NTSTATUS                KSocketSend(PKSOCKET pSocket, PVOID  Buffer, SIZE_T Size,
                                    PSIZE_T BytesSent);

NTSTATUS                KSocketConnect(PKSOCKET pSocket, ULONG Address, USHORT Port);
NTSTATUS                KSocketDisconnect(PKSOCKET pSocket);

NTSTATUS                KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);

NTSTATUS                KSocketReceive(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesReceived,
                            BOOLEAN ReceivePeek);

NTSTATUS                KSocketReadLine(PKSOCKET pSocket, PCHAR buf, SIZE_T maxlen, PSIZE_T  ReceivedBytes);

NTSTATUS                KSocketWriteLine(PKSOCKET pSocket, const char* format, ...);


#endif // __sockets_h__

Kernel mode sockets library

It's my birthday today (just turned 31 the 31st december, funny eh ?!), i wanted to publish something,
it makes me feel alive. Christ lived 33 years only, if i'd be the new Christ
i've only 2 years left, so better to share my knowledge now :)

Well, here you have a fully functional TDI sockets library. You can connect,
send, receive, all from your supa-dupa-l333t kernelmode rootkit. Yes, you can
bypass lame TDI firewalls with this. No, you can't bypass ndis firewalls.
(read : you can bypass norton's firewall).

Consider that something like this worths $400+ from PCAUSA, and maybe more
from OSR (KSOCKS)..... enough for a new year's present :)

Usage : you have to hook //device/tcp yourself and set the global variable TcpIpDevice.
Then call KSocketInitialize and you're done. Refer to the source for usage.... it shouldn't be hard.

have fun, and happy 2006 to everyone ! Ciao! :)




-----------------------------------------sockets.c------------------------------

//************************************************************************
//                                                                      
// sockets.c
// (c) valerino/xOANINO 2003/2004/2005
//
// this module implements a generic kernel sockets library.
// ** Beware that this is optimized for single thread use if REUSE_SOCKETSIRP is defined.**
//*****************************************************************************

#include "ntifs.h"

#define MODULE "**SOCKETS**"

#ifdef DBG
#ifdef NO_SOCKETS_DBGMSG
#undef KDebugPrint
#define KDebugPrint(DbgLevel,_x)
#endif
#endif

/************************************************************************/
// BOOL KSocketInitialize()
//
// Initialize kernelsockets library
//
/************************************************************************/
BOOL KSocketInitialize()
{
    ExInitializePagedLookasideList(&LookasideSocketMem, NULL, NULL, 0, 1024, 'lskN', 0);
    ExInitializePagedLookasideList(&LookasideSocket,NULL,NULL,0,sizeof (KSOCKET),'cosN',0);
    
#ifdef REUSE_SOCKETSIRP
    // check for tcpdevice
    if (!TcpIpDevice)
        return TRUE;
    
    // allocate the single irp we use throughout the sockets library
    SocketsIrp = IoAllocateIrp(TcpIpDevice->StackSize + 1, FALSE);
    if (!SocketsIrp)
        return FALSE;
#endif
    return TRUE;
}

/************************************************************************/
// PVOID KSocketAllocatePool(VOID)
//
// Allocate memory from sockets lookaside                                                                     
//
/************************************************************************/
PVOID KSocketAllocatePool(VOID)
{
    PCHAR    p    = NULL;

    p = ExAllocateFromPagedLookasideList(&LookasideSocketMem);
    if (p)
        memset(p, 0, SMALLBUFFER_SIZE);
    return p;
}

/************************************************************************/
// void KSocketFreePool(PVOID pBuffer)
//
// Free memory to sockets lookaside                                                                     
//
/************************************************************************/
void KSocketFreePool(PVOID pBuffer)
{
    ExFreeToPagedLookasideList(&LookasideSocketMem, pBuffer);
}

/************************************************************************/
// NTSTATUS KSocketCloseObject(HANDLE Handle, PFILE_OBJECT FileObject)
//
// Release a socket object
//
/************************************************************************/
NTSTATUS KSocketCloseObject(HANDLE Handle, PFILE_OBJECT FileObject)
{
    NTSTATUS    Status    = STATUS_SUCCESS;
    
    // dereference referenced object (called for connection and address)
    if (FileObject)
        ObDereferenceObject(FileObject);
    
    // close socket
    if (Handle)
        Status = ZwClose(Handle);
    
    return Status;
}

/************************************************************************/
// PFILE_FULL_EA_INFORMATION KSocketBuildEaValues(PVOID EaName, ULONG NameLength, PVOID EaValue,
//    ULONG ValueLength, PULONG EaLength)
//
// Build EA information for the socket object
//
/************************************************************************/
PFILE_FULL_EA_INFORMATION KSocketBuildEaValues(PVOID EaName, ULONG NameLength, PVOID EaValue,
    ULONG ValueLength, PULONG EaLength)
{
    PFILE_FULL_EA_INFORMATION    Ea;

    *EaLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + NameLength + 1 + ValueLength;

    // allocate ea buffer
    Ea = ExAllocatePool(PagedPool, *EaLength);
    if (!Ea)
        return NULL;

    // fill buffer with EA values requested
    Ea->NextEntryOffset = 0;
    Ea->Flags = 0;
    Ea->EaNameLength = (UCHAR) NameLength;
    Ea->EaValueLength = (USHORT) ValueLength;
    memcpy (Ea->EaName,EaName,Ea->EaNameLength + 1);
    if (EaValue && EaLength)
        memcpy (&Ea->EaName[NameLength + 1],EaValue,ValueLength);
    
    return Ea;
}

/************************************************************************/
// NTSTATUS KSocketOpenAddress(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
//
// Open address                                                                    
//
/************************************************************************/
NTSTATUS KSocketOpenAddress(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
{
    UNICODE_STRING                Name;
    OBJECT_ATTRIBUTES            ObjectAttributes;
    PFILE_FULL_EA_INFORMATION    Ea    = NULL;
    ULONG                        EaLength;
    IO_STATUS_BLOCK                Iosb;
    NTSTATUS                    Status;
    TA_IP_ADDRESS                Sin;

    // initialize address
    Sin.TAAddressCount = 1;
    Sin.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    Sin.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
    Sin.Address[0].Address[0].sin_port = 0; // INADDR_ANY;
    Sin.Address[0].Address[0].in_addr = 0;

    // get EA values for address
    Ea = KSocketBuildEaValues(TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH, &Sin,
            sizeof(TA_IP_ADDRESS), &EaLength);
    if (!Ea)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto __exit;
    }

    // open tcp device
    RtlInitUnicodeString(&Name, TCPIP_DEVICE);
    InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, 0);
    Status = ZwCreateFile(Handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &Iosb, 0,
        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,FILE_OPEN_IF,0, Ea, EaLength);
    if (!NT_SUCCESS(Status))
        goto __exit;
    
    Status = ObReferenceObjectByHandle(*Handle, FILE_ANY_ACCESS, 0, KernelMode, FileObject, NULL);

__exit:
    if (Ea)
        ExFreePool(Ea);

    return Status;
}

/************************************************************************/
// NTSTATUS KSocketOpenConnection(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
//
// open connection                                                                    
//
/************************************************************************/
NTSTATUS KSocketOpenConnection(PHANDLE Handle, PFILE_OBJECT* FileObject, PVOID Context)
{
    UNICODE_STRING                Name;
    OBJECT_ATTRIBUTES            ObjectAttributes;
    PFILE_FULL_EA_INFORMATION    Ea    = NULL;
    ULONG                        EaLength;
    IO_STATUS_BLOCK                Iosb;
    NTSTATUS                    Status;

    // get EA values for connection
    Ea = KSocketBuildEaValues(TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH, &Context,
            sizeof(PKSOCKET), &EaLength);
    if (!Ea)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto __exit;
    }

    // open tcp device
    RtlInitUnicodeString(&Name, TCPIP_DEVICE);
    InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, 0);
    Status = ZwCreateFile(Handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &Iosb, 0,
        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,FILE_OPEN_IF, 0, Ea, EaLength);
    if (!NT_SUCCESS(Status))
        goto __exit;

    Status = ObReferenceObjectByHandle(*Handle, FILE_ANY_ACCESS, 0, KernelMode, FileObject, NULL);

__exit:
    if (Ea)
        ExFreePool(Ea);

    return Status;
}

//************************************************************************
// NTSTATUS KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)                                                                     
//  
// Socket completion routine
//************************************************************************/
NTSTATUS KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    PMDL mdl = NULL;
    PMDL nextMdl = NULL;
    PKSOCKET_CTX Ctx = (PKSOCKET_CTX)Context;
    
    // set status block
    Ctx->Iosb.Status = Irp->IoStatus.Status;
    Ctx->Iosb.Information = Irp->IoStatus.Information;
    
    // Free any associated MDL.
    if (Irp->MdlAddress != NULL)
    {
        for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl)
        {
            nextMdl = mdl->Next;
            MmUnlockPages(mdl);
            
            // This function will also unmap pages.
            IoFreeMdl(mdl);
        }

        // set mdl address to null, to prevent iofreeirp to attempt to free it again
        Irp->MdlAddress = NULL;
    }
        
#ifdef REUSE_SOCKETSIRP
    // set irp for reuse
    IoReuseIrp (Irp,STATUS_SUCCESS);
#else
    // free irp
    IoFreeIrp (Irp);
#endif
    // set event
    if (Ctx)
        KeSetEvent (&Ctx->Event,IO_NO_INCREMENT,FALSE);
    
    return STATUS_MORE_PROCESSING_REQUIRED;
}

//************************************************************************
// NTSTATUS KSocketAssociateAddress(HANDLE Address, PFILE_OBJECT Connection)                                                                     
//  
// Associate address
//************************************************************************/
NTSTATUS KSocketAssociateAddress(HANDLE Address, PFILE_OBJECT Connection)
{
    PDEVICE_OBJECT    DeviceObject;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    KSOCKET_CTX        Ctx;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
    
    // allocate TDI_ASSOCIATE_ADDRESS irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build irp (this set completion routine too)
    TdiBuildAssociateAddress(Irp, DeviceObject, Connection,KSocketComplete, &Ctx, Address);
    
    // call tcpip
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketAssociateAddress timeout occurred ***************** cancelling IRP/n", MODULE));
                
            // cancel irp
            IoCancelIrp(Irp);
            
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }    
    }

    return Status;
}

//************************************************************************
// NTSTATUS KSocketConnect(PKSOCKET pSocket, ULONG Address, USHORT Port)
//  
// Connect socket to address:port                                                                   
//************************************************************************/
NTSTATUS KSocketConnect(PKSOCKET pSocket, ULONG Address, USHORT Port)
{
    PDEVICE_OBJECT        DeviceObject;
    PIRP                Irp = NULL;
    NTSTATUS            Status = STATUS_TIMEOUT;
    KSOCKET_CTX            Ctx;
    TDI_CONNECTION_INFORMATION    RequestInfo;
    TA_IP_ADDRESS            RemoteAddress;
    PFILE_OBJECT            Connection;
    
    KDebugPrint (2,("%s KSocketConnect called./n",MODULE));

    if (!pSocket)
        return STATUS_UNSUCCESSFUL;
    
    // set parameters
    Connection = pSocket->ConnectionFile;
    memset (&RequestInfo,0, sizeof(TDI_CONNECTION_INFORMATION));
    memset (&RemoteAddress,0,sizeof (TA_IP_ADDRESS));
    
    RemoteAddress.TAAddressCount = 1;
    RemoteAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    RemoteAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
    RemoteAddress.Address[0].Address[0].sin_port = Port;
    RemoteAddress.Address[0].Address[0].in_addr = Address;
    
    RequestInfo.UserDataLength = 0;
    RequestInfo.UserData = NULL;
    RequestInfo.OptionsLength = 0;
    RequestInfo.Options = NULL;
    RequestInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
    RequestInfo.RemoteAddress = &RemoteAddress;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
    
    // allocate TDI_CONNECT irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    
    // build irp (this set completion routine too)
    TdiBuildConnect (Irp, DeviceObject,Connection,KSocketComplete, &Ctx,NULL, &RequestInfo,&RequestInfo);
    
    // call tcpip
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketConnect timeout occurred ***************** cancelling IRP/n", MODULE));
                
            // cancel irp
            IoCancelIrp(Irp);
            
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
            // ok
            Status = Ctx.Iosb.Status;
    }
    
    if (Status == STATUS_SUCCESS)
        pSocket->Connected = TRUE;
    
       return Status;
}


//************************************************************************
// NTSTATUS KSocketDisconnect(PKSOCKET pSocket
//  
// Disconnect socket                                                                   
//************************************************************************/
NTSTATUS KSocketDisconnect(PKSOCKET pSocket)
{
    PDEVICE_OBJECT    DeviceObject;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    TDI_CONNECTION_INFORMATION    ReqDisconnect;
    PFILE_OBJECT    Connection;
    ULONG Flags;
    KSOCKET_CTX    Ctx;
    
    // check if socket is already disconnected
    if (!pSocket)
        return STATUS_UNSUCCESSFUL;
    
    if (!pSocket->Connected)
        return STATUS_ALREADY_DISCONNECTED;
    
    // set parameters
    Connection = pSocket->ConnectionFile;
    memset(&ReqDisconnect,0,sizeof (TDI_CONNECTION_INFORMATION));
    Flags = TDI_DISCONNECT_ABORT;

       // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
        
    // allocate TDI_DISCONNECT irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build irp (this set completion routine too)
    TdiBuildDisconnect (Irp, DeviceObject,Connection,KSocketComplete, &Ctx, NULL,Flags,&ReqDisconnect,&ReqDisconnect);
    
    // call tcpip
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketDisconnect timeout occurred ***************** cancelling IRP/n", MODULE));
                    
            // cancel irp
            IoCancelIrp(Irp);
                
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }    
    }
    
    if (NT_SUCCESS (Status))
        pSocket->Connected = FALSE;
    
    return Status;
}

//************************************************************************
// NTSTATUS KSocketSend(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesSent)
//  
// Send buffer thru socket                                                                   
//************************************************************************/
NTSTATUS KSocketSend(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesSent)
{
    PDEVICE_OBJECT    DeviceObject;
    PFILE_OBJECT    Connection;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    KSOCKET_CTX Ctx;
    PMDL            Mdl;
    
    KDebugPrint (2,("%s KSocketSend called./n",MODULE));
    
    if (!pSocket)
        return STATUS_UNSUCCESSFUL;

    // set parameters
    Connection = pSocket->ConnectionFile;
    *BytesSent = 0;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
            
    // allocate TDI_SEND irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build mdl
    Mdl = IoAllocateMdl(Buffer, Size, FALSE, FALSE, NULL);
    if (!Mdl)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        IoFreeIrp (Irp);
        return Status;
    }
    
    __try
    {
        MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        IoFreeMdl (Mdl);
        IoFreeIrp (Irp);
        Status = STATUS_UNSUCCESSFUL;
        return Status;
    }
    Mdl->Next = NULL;
    
    // build irp (this set completion routine too)
    TdiBuildSend (Irp, DeviceObject,Connection,KSocketComplete, &Ctx,Mdl,0,Size);
    
    // call tcp
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
               KDebugPrint (1, ("%s ***************** KSocketSend timeout occurred ***************** cancelling IRP/n", MODULE));
                    
            // cancel irp
            IoCancelIrp(Irp);
                    
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);
            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }
    }
    
    // return sent bytes
    *BytesSent = Ctx.Iosb.Information;
    
    // check transferred bytes
    if (Ctx.Iosb.Information != Size)
        Status = STATUS_CONNECTION_ABORTED;

    if (!NT_SUCCESS(Status))
    {
        KDebugPrint(1, ("%s KSocketSend returned error %08x (ReqSent:%d,OkSent:%d)/n", MODULE, Status,
            Size, *BytesSent));
    }
    
    return Status;
}

//************************************************************************
// NTSTATUS KSocketReceive(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesReceived, BOOLEAN ReceivePeek)
//  
// Receive buffer thru socket                                                                   
//************************************************************************/
NTSTATUS KSocketReceive(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesReceived, BOOLEAN ReceivePeek)
{
    PDEVICE_OBJECT    DeviceObject;
    PFILE_OBJECT    Connection;
    PIRP            Irp = NULL;
    NTSTATUS        Status = STATUS_TIMEOUT;
    PMDL            Mdl;
    ULONG            Flags;
    KSOCKET_CTX        Ctx;
        
    KDebugPrint (2,("%s KSocketReceive called./n",MODULE));
    
    if (!pSocket)
        return STATUS_UNSUCCESSFUL;
    
    // set parameters
    Connection = pSocket->ConnectionFile;
    *BytesReceived = 0;
    
    if (ReceivePeek)
        Flags = TDI_RECEIVE_PEEK;
    else
        Flags = TDI_RECEIVE_NORMAL;
    
    // initialize event and device
    KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);    
    DeviceObject = TcpIpDevice;
                
    // allocate TDI_RECEIVE irp
#ifdef REUSE_SOCKETSIRP
    Irp = SocketsIrp;
#else
    Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
#endif
    if (!Irp)
        return STATUS_INSUFFICIENT_RESOURCES;
    
    // build mdl
    Mdl = IoAllocateMdl(Buffer, Size, FALSE, FALSE, NULL);
    if (!Mdl)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        IoFreeIrp (Irp);
        return Status;
    }
    
    __try
    {
        MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        IoFreeMdl (Mdl);
        IoFreeIrp (Irp);
        Status = STATUS_UNSUCCESSFUL;
        return Status;
    }
    Mdl->Next = NULL;
    
    // build irp (this set completion routine too)
    TdiBuildReceive (Irp, DeviceObject,Connection,KSocketComplete, &Ctx,Mdl,Flags,Size);
    
    // call tcp
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        // returned status pending
        Status = KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, &SockTimeout);
        if (Status == STATUS_TIMEOUT)
        {
            KDebugPrint (1, ("%s ***************** KSocketReceive timeout occurred ***************** cancelling IRP/n", MODULE));
                    
            // cancel irp
            IoCancelIrp(Irp);
                    
            // wait for completion routine to be called
            KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);

            Status = STATUS_CONNECTION_ABORTED;
        }
        else
        {
            // ok
            Status = Ctx.Iosb.Status;
        }
    }
    
    // return received bytes
    *BytesReceived = Ctx.Iosb.Information;
    
    // check received bytes
    if (Ctx.Iosb.Information == 0)
        Status = STATUS_CONNECTION_ABORTED;

    if (!NT_SUCCESS(Status))
    {
        KDebugPrint(1, ("%s KSocketReceive returned error %08x (ReqRecv:%d,OkRecv:%d)/n", MODULE, Status,
            Size, *BytesReceived));
    }
    
    return Status;
}

//************************************************************************
// VOID KSocketClose(PKSOCKET Socket)                                                                     
//  
// Close socket and Release socket memory                                                                   
//************************************************************************/
VOID KSocketClose(PKSOCKET Socket)
{
    if (Socket == NULL)
    {
        return;
    }

    KSocketCloseObject(Socket->TransportAddressHandle, Socket->TransportAddress);
    KSocketCloseObject(Socket->ConnectionFileHandle, Socket->ConnectionFile);

    ExFreeToPagedLookasideList (&LookasideSocket,Socket);

    Socket = NULL;
}

//************************************************************************
// NTSTATUS KSocketCreate(OUT PKSOCKET* Socket)                                                                     
//  
// Create socket                                                                   
//************************************************************************/
NTSTATUS KSocketCreate(OUT PKSOCKET* Socket)
{
    NTSTATUS    Status    = STATUS_SUCCESS;
    PKSOCKET    iSocket    = NULL;

#ifdef ALWAYS_DISABLESOCKETS
    KDebugPrint(1,("%s Sockets disabled, connect skipped./n", MODULE));
    return STATUS_UNSUCCESSFUL;
#endif
    
    // check disabled sockets
    if (DisableSockets)
    {
        KDebugPrint(1,("%s Sockets disabled, connect skipped./n", MODULE));
        return STATUS_UNSUCCESSFUL;
    }
    
    // handle KAV (crash if not patched)
    ModulePatchKAV();

    // allocate memory for a new socket
    iSocket = ExAllocateFromPagedLookasideList(&LookasideSocket);
    if (!iSocket)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto __exit;
    }
    memset (iSocket,0, sizeof(KSOCKET));

    // open transport address
    Status = KSocketOpenAddress(&iSocket->TransportAddressHandle, &iSocket->TransportAddress,
        iSocket);
    if (!NT_SUCCESS(Status))
        goto __exit;

    // create connection endpoint
    Status = KSocketOpenConnection(&iSocket->ConnectionFileHandle, &iSocket->ConnectionFile,
                iSocket);
    if (!NT_SUCCESS(Status))
        goto __exit;

    // associate address with connection
    Status = KSocketAssociateAddress(iSocket->TransportAddressHandle, iSocket->ConnectionFile);
    if (!NT_SUCCESS(Status))
        goto __exit;
    
__exit:
    if (!NT_SUCCESS(Status))
    {
        if (iSocket)
            KSocketClose(iSocket);
        *Socket = NULL;
    }
    else
        *Socket = iSocket;

    return Status;
}

/************************************************************************/
// NTSTATUS KSocketReadLine(PKSOCKET pSocket, PCHAR buf, SIZE_T maxlen, PSIZE_T ReceivedBytes)
//
// Read line (ascii) from network
//
/************************************************************************/
NTSTATUS KSocketReadLine(PKSOCKET pSocket, PCHAR buf, SIZE_T maxlen, PSIZE_T ReceivedBytes)
{
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    UCHAR c = 0;
    ULONG i = 0;
    ULONG received = 0;

    // check params
    if (!pSocket || !buf || !ReceivedBytes || !maxlen)
        goto __exit;
    
    *ReceivedBytes = 0;
    if (!pSocket->Connected)
        goto __exit;
    
    // read line char by char, and stop at EOL
    memset (buf, 0, maxlen);
    while (TRUE)
    {
        if (i == maxlen)
            break;
        
        // get char from socket
        Status = KSocketReceive (pSocket,&c,1,&received,FALSE);
        if (!NT_SUCCESS (Status) || received == 0)
            break;
        
        // write char into buffer and advance
        *buf = c;
        buf++;
        i++;
        
        // check for EOL
        if (c == '/n')
        {
            *ReceivedBytes = i;
            break;
        }
    }
    
__exit:
    // treat 0 size received as error
    if (received == 0)
        Status = STATUS_NO_DATA_DETECTED;
    
    return Status;
}

/************************************************************************/
// NTSTATUS KSocketWriteLine(PKSOCKET pSocket, const char* format, ...)
//
// write formatted line (ascii) to network
//
/************************************************************************/
NTSTATUS KSocketWriteLine(PKSOCKET pSocket, const char* format, ...)
{
    va_list        ap;
    char*        buf;
    ULONG        len;
    NTSTATUS    Status;
    SIZE_T        BytesSent    = 0;

    // allocate memory
    buf = KSocketAllocatePool();
    if (!buf)
        return STATUS_INSUFFICIENT_RESOURCES;

    // build line
    va_start(ap, format);
    _vsnprintf(buf, SMALLBUFFER_SIZE, format, ap);
    va_end(ap);
    len = strlen(buf);
    
    // send
    Status = KSocketSend(pSocket, buf, len, &BytesSent);

    // free buffer
    KSocketFreePool(buf);

    // check if we've sent all bytes
    if (BytesSent < len)
        return STATUS_UNSUCCESSFUL;
    
    return Status;
}

-----------------------------------------sockets.h------------------------------

#ifndef __sockets_h__
#define __sockets_h__

#define REUSE_SOCKETSIRP

// debugprint with debuglevel (if dbglevel == debug level, it triggers)
#if DBG
#define KDebugPrint(DbgLevel,_x) { /
if (DbgLevel == DEBUG_LEVEL)       
{                                  
DbgPrint _x;                       
}                                  
}
#else
#define KDebugPrint(DbgLevel,_x)
#endif //DBG

//#define ALWAYS_DISABLESOCKETS

//************************************************************************
// kernel sockets                                                                     
//                                                                      
//************************************************************************/
PDEVICE_OBJECT            TcpIpDevice;

typedef struct __tagKSOCKET
{
    PFILE_OBJECT                TransportAddress;
    HANDLE                        TransportAddressHandle;
    PFILE_OBJECT                ConnectionFile;
    HANDLE                        ConnectionFileHandle;
    BOOLEAN                        Connected;
}KSOCKET, * PKSOCKET;

typedef struct _tagKSOCKET_CTX {
    KEVENT Event;
    IO_STATUS_BLOCK Iosb;
} KSOCKET_CTX, *PKSOCKET_CTX;

PAGED_LOOKASIDE_LIST    LookasideSocketMem;
PAGED_LOOKASIDE_LIST    LookasideSocket;
KEVENT                    NoNetworkFailures;
BOOLEAN                    DisableSockets;                    // flag to disable sockets if needed
PDRIVER_DISPATCH        OriginalTcpInternalDeviceControl;
PIRP                    SocketsIrp;

// all paged code except the completion routine
BOOL                    KSocketInitialize();
#pragma alloc_text        (PAGEboom,KSocketInitialize)

NTSTATUS                KSocketCreate(OUT PKSOCKET* Socket);

VOID                    KSocketClose(PKSOCKET Socket);

PVOID                    KSocketAllocatePool();

void                    KSocketFreePool(PVOID pBuffer);

NTSTATUS                KSocketSend(PKSOCKET pSocket, PVOID  Buffer, SIZE_T Size,
                                    PSIZE_T BytesSent);

NTSTATUS                KSocketConnect(PKSOCKET pSocket, ULONG Address, USHORT Port);
NTSTATUS                KSocketDisconnect(PKSOCKET pSocket);

NTSTATUS                KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);

NTSTATUS                KSocketReceive(PKSOCKET pSocket, PVOID Buffer, SIZE_T Size, PSIZE_T BytesReceived,
                            BOOLEAN ReceivePeek);

NTSTATUS                KSocketReadLine(PKSOCKET pSocket, PCHAR buf, SIZE_T maxlen, PSIZE_T  ReceivedBytes);

NTSTATUS                KSocketWriteLine(PKSOCKET pSocket, const char* format, ...);


#endif // __sockets_h__
基于STM32设计的数字示波器全套资料(原理图、PCB图、源代码) 硬件平台: 主控器:STM32F103ZET6 64K RAM 512K ROM 屏幕器:SSD1963 分辨率:480*272 16位色 触摸屏:TSC2046 模拟电路: OP-TL084 OP-U741 SW-CD4051 CMP-LM311 PWR-LM7805 -LM7905 -MC34063 -AMS1117-3.3 DRT-ULN2003 6.继电器:信号继电器 7.电源:DC +12V 软件平台: 开发环境:RealView MDK-ARM uVision4.10 C编译器:ARMCC ASM编译器:ARMASM 连机器:ARMLINK 实时内核:UC/OS-II 2.9实时操作系统 GUI内核:uC/GUI 3.9图形用户接口 底层驱动:各个外设驱动程序 数字示波器功能: 波形发生器:使用STM32一路DA实现正弦,三角波,方波,白噪声输出。 任意一种波形幅值在0-3.3V任意可调、频率在一定范围任意可调、方波占空比可调。调节选项可以通过触摸屏完成设置。 SD卡存储: SD卡波形存储输出,能够对当前屏幕截屏,以JPG格式存储在SD卡上。能够存储1S内的波形数据,可以随时调用查看。 数据传输:用C#编写上位机,通过串口完成对下位机的控制。(1)实现STOP/RUN功能(2)输出波形电压、时间参数(3)控制截屏(4)控制波形发生器(5)控制完成FFT(6)波形的存储和显示 图形接口: UCGUI 水平扫速: 250 ns*、500ns、1μs、5 μs、10μs、50μs、500 μs、5ms 、50ms 垂直电压灵敏度:10mV/div, 20mV/div, 50mV/div, 0.1V/div, 0,2V/div, 0.5V/div, 1V/div,2V/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值