對於擦除模塊痕跡,我實驗了兩種方法,下面一一闡述:
1.修改PEB結構,用代碼說話
{
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結構裏面也就不會有相應的模塊結構,也就達到了隱藏的目的。