Author:   Polymorphours
Email:   Polymorphours@whitecell.org
Homepage:http://www.whitecell.org 
Date:     2005-11-17
				
						
/*++
         Author: Polymorphours
 Date: 2005/1/10
				 通过对 NtReadVirtualMemory 挂钩,防止其他进程对保护的模块进行扫描,
 如果发现其他进程读被保护模块的内存,则返回0
				--*/
				
						
typedef struct _LDR_DATA_TABLE_ENTRY {
 LIST_ENTRY InLoadOrderLinks;
 LIST_ENTRY InMemoryOrderLinks;
 LIST_ENTRY InInitializationOrderLinks;
 PVOID DllBase;
 PVOID EntryPoint;
 ULONG SizeOfImage;
 UNICODE_STRING FullDllName;
 UNICODE_STRING BaseDllName;
 /*
 +0x034 Flags             : Uint4B
 +0x038 LoadCount         : Uint2B
 +0x03a TlsIndex          : Uint2B
 +0x03c HashLinks         : _LIST_ENTRY
 +0x03c SectionPointer    : Ptr32 Void
 +0x040 CheckSum          : Uint4B
 +0x044 TimeDateStamp     : Uint4B
 +0x044 LoadedImports     : Ptr32 Void
 +0x048 EntryPointActivationContext : Ptr32 Void
 +0x04c PatchInformation : Ptr32 Void 
 */
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
				/*++
				 函数名: MyNtReadVirtualMemory
 参数:
   IN HANDLE ProcessHandle,
   IN PVOID BaseAddress,
   OUT PVOID Buffer,
   IN ULONG BufferLength,
   OUT PULONG ReturnLength OPTIONAL
  
 功能:
   隐藏保护模块的内存,如果发现有内存扫描到这块内存,则返回加密后的数据扰乱扫描过程
  
 返回:
   NTSTATUS
  
--*/
				
						
NTSTATUS
MyNtReadVirtualMemory(
 IN HANDLE ProcessHandle,
 IN PVOID BaseAddress,
 OUT PVOID Buffer,
 IN ULONG BufferLength,
 OUT PULONG ReturnLength OPTIONAL
 )
{
 NTSTATUS status;
 PEPROCESS eProcess;
 PVOID   Peb;
 PPEB_LDR_DATA PebLdrData;
 PLDR_DATA_TABLE_ENTRY LdrDataTableHeadList;
 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
 PLIST_ENTRY    Blink;
 PPROTECT_NODE   FileNode = NULL;
 BOOLEAN     bHideFlag = FALSE;
 ULONG     ImageMaxAddress = 0;
				/*
#ifdef _DEBUG
 DbgPrint( "Call Process: %s, BaseAddress: %08x\n", PsGetProcessImageFileName( PsGetCurrentProcess() ), BaseAddress );
#endif
*/
				 status =ObReferenceObjectByHandle(
     ProcessHandle,
     FILE_READ_DATA,
     PsProcessType,
     KernelMode,
     (PVOID)&eProcess,
     NULL
     );
 if ( NT_SUCCESS(status) ) {
  
   //
   // 得到PEB的地址
   //
  
   Peb = (PVOID)(*(PULONG)((PCHAR)eProcess + PebOffset));
  
   //
   // 切换到目标进程空间
   //
  
  
   KeAttachProcess( eProcess );
  
   //
   // 判断PEB是否有效,如果有效,那么准备利用PEB结构遍历进程加载的模块
   //
				   if ( !MmIsAddressValid( Peb ) ) {
				/*
#ifdef _DEBUG
    DbgPrint( "PEB is error.\n" );
#endif
*/
   
    KeDetachProcess();
    ObDereferenceObject( eProcess );
   
    goto CLEANUP;
   }
  
   PebLdrData = (PPEB_LDR_DATA)(*(PULONG)( (PCHAR)Peb + 0xc ));
  
   if ( !PebLdrData ) {
   
    KeDetachProcess();
    ObDereferenceObject( eProcess );
   
    goto CLEANUP;
   }
  
   try {
   
    ProbeForRead ( 
     PebLdrData,
     sizeof(PEB_LDR_DATA),
     sizeof(ULONG)
     );
    
    //
    // 遍历模块链表
    //
   
    LdrDataTableHeadList = (PLDR_DATA_TABLE_ENTRY)PebLdrData->InLoadOrderModuleList.Flink;
    LdrDataTableEntry = LdrDataTableHeadList;
   
   
    do {
    
     ProbeForRead(
      LdrDataTableEntry,
      sizeof(LDR_DATA_TABLE_ENTRY),
      sizeof(ULONG)
      );
     
     if ( !LdrDataTableEntry->DllBase ) {
				      LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)LdrDataTableEntry->InLoadOrderLinks.Flink;
      continue; 
     }
				    
     //
     // 判断读的内存属于那一个模块,如果都不属于,那么放过
     //
				     ImageMaxAddress = (ULONG)((ULONG)LdrDataTableEntry->DllBase + LdrDataTableEntry->SizeOfImage);
    
     if ( (ULONG)( (ULONG)BaseAddress + BufferLength) < (ULONG)LdrDataTableEntry->DllBase ||
       (ULONG)BaseAddress > ImageMaxAddress ) {
				       //
       // 如果不是读模块区域,那么枚举下一个
       // 
				      LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)LdrDataTableEntry->InLoadOrderLinks.Flink;
      continue; 
     }
    
     //
     // 如果是被保护的模块,那么返回虚假数据
     //
				     bHideFlag = FALSE;
     Blink = ProtectFile.Blink;
    
				     while ( Blink != &ProtectFile ) {
				      FileNode = CONTAINING_RECORD( Blink, PROTECT_NODE, ActiveLink );
     
      //
      // 如果发现当前文件存在于隐藏列表,那么设置隐藏标志隐藏它
      //
				      if ( wcsstr( FileNode->ProtectName, LdrDataTableEntry->FullDllName.Buffer ) ) {
				       bHideFlag = TRUE;
       break;
      }
				      Blink = Blink->Blink;
     }
    
     if ( bHideFlag ) {
     
      //
      // 返回原本的进程空间进行处理
      //
				      KeDetachProcess();
      ObDereferenceObject( eProcess );
				      ProbeForWrite(
       Buffer,
       BufferLength,
       sizeof(ULONG)
       );
      
      memset( Buffer, 0x00, BufferLength );
     
      ProbeForWrite(
       ReturnLength,
       sizeof(PULONG),
       sizeof(ULONG)
       );
     
      *ReturnLength = BufferLength;
     
      return STATUS_SUCCESS;
     }
   
     LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)LdrDataTableEntry->InLoadOrderLinks.Flink;
    
    } while ( LdrDataTableEntry != LdrDataTableHeadList );
   
				   } except( EXCEPTION_EXECUTE_HANDLER ) {
				    if ( !bHideFlag ) {
    
     KeDetachProcess();
     ObDereferenceObject( eProcess );
    }
				    goto CLEANUP;
   }
				
						
   KeDetachProcess();
   ObDereferenceObject( eProcess );
 }
CLEANUP:
				 return NtReadVirtualMemory(
    ProcessHandle,
    BaseAddress,
    Buffer,
    BufferLength,
    ReturnLength
    );
}