擦除模块痕迹

来源:互联网 发布:javascript框架是什么 编辑:程序博客网 时间:2024/04/28 15:48

对于擦除模块痕迹,我实验了两种方法,下面一一阐述:

1.修改PEB结构,用代码说话

typedef struct _PEB_LDR_DATA
 
{
  ULONG               Length;
  BOOLEAN             Initialized;
  BYTE    reserved[
3];
  PVOID               SsHandle;
  LIST_ENTRY          InLoadOrderModuleList;
  LIST_ENTRY          InMemoryOrderModuleList;
  LIST_ENTRY          InInitializationOrderModuleList;
 }
 PEB_LDR_DATA, *PPEB_LDR_DATA;

 typedef 
struct _UNICODE_STRING
 
{
  USHORT Length;
  USHORT MaximumLength;
  PWSTR Buffer;
 }
 UNICODE_STRING, *PUNICODE_STRING;

 typedef 
struct _LDR_MODULE {
  LIST_ENTRY InLoadOrderModuleList;
  LIST_ENTRY InMemoryOrderModuleList;
  LIST_ENTRY InInitializationOrderModuleList;
  PVOID BaseAddress;
  PVOID EntryPoint;
  ULONG SizeOfImage;
  UNICODE_STRING FullDllName;
  UNICODE_STRING BaseDllName;
  ULONG Flags;
  SHORT LoadCount;
  SHORT TlsIndex;
  LIST_ENTRY HashTableEntry;
  ULONG TimeDateStamp;
 }
 LDR_MODULE, *PLDR_MODULE;


 typedef 
struct RTL_DRIVE_LETTER_CURDIR
 
{
  USHORT              Flags;
  USHORT              Length;
  ULONG               TimeStamp;
  UNICODE_STRING      DosPath;
 }
 RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

 typedef 
struct _RTL_USER_PROCESS_PARAMETERS
 
{
  ULONG               AllocationSize;
  ULONG               Size;
  ULONG               Flags;
  ULONG               DebugFlags;
  HANDLE              hConsole;
  ULONG               ProcessGroup;
  HANDLE              hStdInput;
  HANDLE              hStdOutput;
  HANDLE              hStdError;
  UNICODE_STRING      CurrentDirectoryName;
  HANDLE              CurrentDirectoryHandle;
  UNICODE_STRING      DllPath;
  UNICODE_STRING      ImagePathName;
  UNICODE_STRING      CommandLine;
  PWSTR               Environment;
  ULONG               dwX;
  ULONG               dwY;
  ULONG               dwXSize;
  ULONG               dwYSize;
  ULONG               dwXCountChars;
  ULONG               dwYCountChars;
  ULONG               dwFillAttribute;
  ULONG               dwFlags;
  ULONG               wShowWindow;
  UNICODE_STRING      WindowTitle;
  UNICODE_STRING      Desktop;
  UNICODE_STRING      ShellInfo;
  UNICODE_STRING      RuntimeInfo;
  RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[
0x20];
 }
 RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

 typedef VOID (_stdcall 
*PPEBLOCKROUTINE)(PVOID);

 typedef 
struct _PEB_FREE_BLOCK
 
{
  
struct _PEB_FREE_BLOCK* Next;
  ULONG Size;
 }
 PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;

 
struct _NT_PEB 
 
{
  BOOLEAN InheritedAddressSpace;
  BOOLEAN ReadImageFileExecOptions;
  BOOLEAN BeingDebugged;
  BOOLEAN Spare;
  HANDLE Mutant;
  PVOID ImageBaseAddress;
  PPEB_LDR_DATA LoaderData;
  PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
  PVOID SubSystemData;
  PVOID ProcessHeap;
  PVOID FastPebLock;
  PPEBLOCKROUTINE FastPebLockRoutine;
  PPEBLOCKROUTINE FastPebUnlockRoutine;
  ULONG EnvironmentUpdateCount;
  PVOID 
*KernelCallbackTable;
  PVOID EventLogSection;
  PVOID EventLog;
  PPEB_FREE_BLOCK FreeList;
  ULONG TlsExpansionCounter;
  PVOID TlsBitmap;
  ULONG TlsBitmapBits[
0x2];
  PVOID ReadOnlySharedMemoryBase;
  PVOID ReadOnlySharedMemoryHeap;
  PVOID 
*ReadOnlyStaticServerData;
  PVOID AnsiCodePageData;
  PVOID OemCodePageData;
  PVOID UnicodeCaseTableData;
  ULONG NumberOfProcessors;
  ULONG NtGlobalFlag;
  BYTE Spare2[
0x4];
  LARGE_INTEGER CriticalSectionTimeout;
  ULONG HeapSegmentReserve;
  ULONG HeapSegmentCommit;
  ULONG HeapDeCommitTotalFreeThreshold;
  ULONG HeapDeCommitFreeBlockThreshold;
  ULONG NumberOfHeaps;
  ULONG MaximumNumberOfHeaps;
  PVOID 
**ProcessHeaps;
  PVOID GdiSharedHandleTable;
  PVOID ProcessStarterHelper;
  PVOID GdiDCAttributeList;
  PVOID LoaderLock;
  ULONG OSMajorVersion;
  ULONG OSMinorVersion;
  ULONG OSBuildNumber;
  ULONG OSPlatformId;
  ULONG ImageSubSystem;
  ULONG ImageSubSystemMajorVersion;
  ULONG ImageSubSystemMinorVersion;
  ULONG GdiHandleBuffer[
0x22];
  ULONG PostProcessInitRoutine;
  ULONG TlsExpansionBitmap;
  BYTE TlsExpansionBitmapBits[
0x80];
  ULONG SessionId;
 }
;

 typedef 
struct _CLIENT_ID
 
{
  HANDLE UniqueProcess;
  HANDLE UniqueThread;
 }
 CLIENT_ID, *PCLIENT_ID;

 typedef 
struct _GDI_TEB_BATCH
 
{
  ULONG Offset;
  ULONG HDC;
  ULONG Buffer[
0x136];
 }
 GDI_TEB_BATCH, *PGDI_TEB_BATCH;

 
struct _NT_TEB
 
{
  NT_TIB Tib;                         
/* 00h */
  PVOID EnvironmentPointer;           
/* 1Ch */
  CLIENT_ID Cid;                      
/* 20h */
  PVOID ActiveRpcInfo;                
/* 28h */
  PVOID ThreadLocalStoragePointer;    
/* 2Ch */
  _NT_PEB 
*Peb;                       /* 30h */
  ULONG LastErrorValue;               
/* 34h */
  ULONG CountOfOwnedCriticalSections; 
/* 38h */
  PVOID CsrClientThread;              
/* 3Ch */
  
void* Win32ThreadInfo;    /* 40h */
  ULONG Win32ClientInfo[
0x1F];        /* 44h */
  PVOID WOW32Reserved;                
/* C0h */
  LCID CurrentLocale;                 
/* C4h */
  ULONG FpSoftwareStatusRegister;     
/* C8h */
  PVOID SystemReserved1[
0x36];        /* CCh */
  PVOID Spare1;                       
/* 1A4h */
  LONG ExceptionCode;                 
/* 1A8h */
  UCHAR SpareBytes1[
0x28];            /* 1ACh */
  PVOID SystemReserved2[
0xA];         /* 1D4h */
  GDI_TEB_BATCH GdiTebBatch;          
/* 1FCh */
  ULONG gdiRgn;                       
/* 6DCh */
  ULONG gdiPen;                       
/* 6E0h */
  ULONG gdiBrush;                     
/* 6E4h */
  CLIENT_ID RealClientId;             
/* 6E8h */
  PVOID GdiCachedProcessHandle;       
/* 6F0h */
  ULONG GdiClientPID;                 
/* 6F4h */
  ULONG GdiClientTID;                 
/* 6F8h */
  PVOID GdiThreadLocaleInfo;          
/* 6FCh */
  PVOID UserReserved[
5];              /* 700h */
  PVOID glDispatchTable[
0x118];       /* 714h */
  ULONG glReserved1[
0x1A];            /* B74h */
  PVOID glReserved2;                  
/* BDCh */
  PVOID glSectionInfo;                
/* BE0h */
  PVOID glSection;                    
/* BE4h */
  PVOID glTable;                      
/* BE8h */
  PVOID glCurrentRC;                  
/* BECh */
  PVOID glContext;                    
/* BF0h */
  LONG LastStatusValue;    
/* BF4h */
  UNICODE_STRING StaticUnicodeString; 
/* BF8h */
  WCHAR StaticUnicodeBuffer[
0x105];   /* C00h */
  PVOID DeallocationStack;            
/* E0Ch */
  PVOID TlsSlots[
0x40];               /* E10h */
  LIST_ENTRY TlsLinks;                
/* F10h */
  PVOID Vdm;                          
/* F18h */
  PVOID ReservedForNtRpc;             
/* F1Ch */
  PVOID DbgSsReserved[
0x2];           /* F20h */
  ULONG HardErrorDisabled;            
/* F28h */
  PVOID Instrumentation[
0x10];        /* F2Ch */
  PVOID WinSockData;                  
/* F6Ch */
  ULONG GdiBatchCount;                
/* F70h */
  USHORT Spare2;                      
/* F74h */
  BOOLEAN IsFiber;                    
/* F76h */
  UCHAR Spare3;                       
/* F77h */
  ULONG Spare4;                       
/* F78h */
  ULONG Spare5;                       
/* F7Ch */
  PVOID ReservedForOle;               
/* F80h */
  ULONG WaitingOnLoaderLock;          
/* F84h */
  ULONG Unknown[
11];                  /* F88h */
  PVOID FlsSlots;                     
/* FB4h */
  PVOID WineDebugInfo;                
/* Needed for WINE DLL's  */
 }
;

 
static struct _NT_TEB* GetCurrentThreadTEB()                     //获得TEB
 {
  
struct _NT_TEB *pTeb=NULL;

  _asm
  
{
   mov  eax,fs:[
0x18]
   mov  pTeb,eax
  }

  
return pTeb;
 }


 
void HideModule(std::string strModuleName)
 
{
  
struct _NT_TEB *pTeb = GetCurrentThreadTEB();
  
struct _NT_PEB *pPeb = pTeb->Peb;                                //由TEB获得PEB
  PPEB_LDR_DATA pLdrData = pPeb->LoaderData;
  PLDR_MODULE pFirstLdrModule 
= (PLDR_MODULE)pLdrData->InLoadOrderModuleList.Flink; 
  PLDR_MODULE pLdrModule 
= pFirstLdrModule;
  PLDR_MODULE pLastModule,pNextModule;

  
//名字通通转为WideChar,因此Windows内部是Unicode的
  WCHAR pWStrModuleName[MAX_PATH] = {WCHAR(0)};
  MultiByteToWideChar(CP_ACP,
0,strModuleName.c_str(), -1,pWStrModuleName,strModuleName.size()); 

  
//PEB里面有当前进程的模块列表,ToolHelp里面的函数就是根据这个列表来遍历的因此,修改此列表可以达到隐藏的目的
  do 
  
{
   
//判断是否是我们要屏蔽的模块
   if(wcscmp(pLdrModule->BaseDllName.Buffer, pWStrModuleName) == 0)
   
{
    
//更改指针,达到隐藏的目的
    pLastModule = (PLDR_MODULE)(pLdrModule->InLoadOrderModuleList.Blink);
    pNextModule 
= (PLDR_MODULE)(pLdrModule->InLoadOrderModuleList.Flink);
    pLastModule
->InLoadOrderModuleList.Flink = (PLIST_ENTRY)pNextModule;
    pNextModule
->InLoadOrderModuleList.Blink = (PLIST_ENTRY)pLastModule;

    
//因为PEB里面有三个列表(分别是以Load顺序、地址顺序、初始化顺序来排序),所以通过覆盖的方式修改另外两个列表,达到隐藏的目的
    pLdrModule->BaseAddress = pLastModule->BaseAddress;
    pLdrModule
->BaseDllName = pLastModule->BaseDllName;
    pLdrModule
->EntryPoint = pLastModule->EntryPoint;
    pLdrModule
->Flags = pLastModule->Flags;
    pLdrModule
->FullDllName = pLastModule->FullDllName;
    pLdrModule
->HashTableEntry = pLastModule->HashTableEntry;
    pLdrModule
->LoadCount = pLastModule->LoadCount;
    pLdrModule
->SizeOfImage = pLastModule->SizeOfImage;
    pLdrModule
->TimeDateStamp = pLastModule->TimeDateStamp;
    pLdrModule
->TlsIndex = pLastModule->TlsIndex;
   }

   pLdrModule 
= (PLDR_MODULE)pLdrModule->InLoadOrderModuleList.Flink;

  }
 while(pLdrModule != pFirstLdrModule);
 }

 2.手动完成dll的加载:刚开始研究手动加载的时候觉得比较复杂,但是通过实践之后,其实还是很简单的,代码比较长这里就不详加叙述了,我就用下面几个步骤来分别叙述:

  • 首先要分配一个空间给dll,可以根据PE结构里面的SizeOfImage来分配;
  • 然后把dll加载到分配的空间里面去,需要注意的是不能单纯拷贝,对于每个Section而言,需要安排到Section列表里面指定的虚拟地址偏移里面去(即RAV + 分配到的空间开始地址<可以称为模块句柄>);
  • 然后要做的就是完成IAT的填写(根据INT)以及重定位表的处理
  • ok,打完收工(还有些比较复杂的处理我还不太明白,比如TLS,努力学习中)

    因为手动加载dll没有经过系统的干涉,所以上面的PEB结构里面也就不会有相应的模块结构,也就达到了隐藏的目的。