原理
PEB 中有一个成员 Ldr:
typedef struct _PEB
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
ULONG ImageUsesLargePages: 1;
ULONG IsProtectedProcess: 1;
ULONG IsLegacyProcess: 1;
ULONG IsImageDynamicallyRelocated: 1;
ULONG SpareBits: 4;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr; // <----------
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
ULONG CrossProcessFlags;
ULONG ProcessInJob: 1;
ULONG ProcessInitializing: 1;
ULONG ReservedBits0: 30;
union
{
PVOID KernelCallbackTable;
PVOID UserSharedInfoPtr;
};
ULONG SystemReserved[1];
ULONG SpareUlong;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[2];
PVOID ReadOnlySharedMemoryBase;
PVOID HotpatchInformation;
VOID * * ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
VOID * * ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
ULONG GdiDCAttributeList;
PRTL_CRITICAL_SECTION LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
ULONG ImageProcessAffinityMask;
ULONG GdiHandleBuffer[34];
PVOID PostProcessInitRoutine;
PVOID TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[32];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
PVOID pShimData;
PVOID AppCompatInfo;
UNICODE_STRING CSDVersion;
_ACTIVATION_CONTEXT_DATA * ActivationContextData;
_ASSEMBLY_STORAGE_MAP * ProcessAssemblyStorageMap;
_ACTIVATION_CONTEXT_DATA * SystemDefaultActivationContextData;
_ASSEMBLY_STORAGE_MAP * SystemAssemblyStorageMap;
ULONG MinimumStackCommit;
_FLS_CALLBACK_INFO * FlsCallback;
LIST_ENTRY FlsListHead;
PVOID FlsBitmap;
ULONG FlsBitmapBits[4];
ULONG FlsHighIndex;
PVOID WerRegistrationData;
PVOID WerShipAssertPtr;
} PEB, *PPEB;
这个 Ldr 的数据类型是 _PEB_LDR_DATA:
typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList; // <---------
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA,*PPEB_LDR_DATA;
InLoadOrderModuleList 成员保存了模块信息,而模块信息的结构为 _LDR_DATA_TABLE_ENTRY。
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG32 SizeOfImage;
UINT8 Unknow0[0x4];
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
所以 ,我们获取到了这个结构.因为是链表.可以遍历链表. 根据DllBase判断 你的模块基址跟这个模块基址是否一样.如果一样那么我们就断开链表,从而实现 dll 的隐藏。
代码参考来自:https://cloud.tencent.com/developer/article/1432475
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
DWORD g_isHide = 0;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LDR_MODULE
{
LIST_ENTRY InLoadOrderModuleList; //+0x00
LIST_ENTRY InMemoryOrderModuleList; //+0x08
LIST_ENTRY InInitializationOrderModuleList; //+0x10
void* BaseAddress; //+0x18
void* EntryPoint; //+0x1c
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
HANDLE SectionHandle;
ULONG CheckSum;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
void HideDll() //这个函数是主要的
{
HMODULE hMod = ::GetModuleHandle("ntdll.dll");
PLIST_ENTRY Head, Cur;
PPEB_LDR_DATA ldr;
PLDR_MODULE ldm;
__asm
{
mov eax, fs:[0x30] //获取PEB结构
mov ecx, [eax + 0x0c] //Ldr //获取_PEB_LDR_DATA结构
mov ldr, ecx
}
Head = &(ldr->InLoadOrderModuleList); //获取模块链表地址
Cur = Head->Flink; //获取指向的结点.
do
{
ldm = CONTAINING_RECORD(Cur, LDR_MODULE, InLoadOrderModuleList); //获取 _LDR_DATA_TABLE_ENTRY结构体地址
//printf("EntryPoint [0x%X]\n",ldm->BaseAddress);
if (hMod == ldm->BaseAddress) //判断要隐藏的DLL基址跟结构中的基址是否一样
{
g_isHide = 1; //如果进入.则标志置为1,表示已经开始进行隐藏了.
ldm->InLoadOrderModuleList.Blink->Flink = //双向链表. 断开链表
ldm->InLoadOrderModuleList.Flink;
ldm->InLoadOrderModuleList.Flink->Blink =
ldm->InLoadOrderModuleList.Blink;
ldm->InInitializationOrderModuleList.Blink->Flink =
ldm->InInitializationOrderModuleList.Flink;
ldm->InInitializationOrderModuleList.Flink->Blink =
ldm->InInitializationOrderModuleList.Blink;
ldm->InMemoryOrderModuleList.Blink->Flink =
ldm->InMemoryOrderModuleList.Flink;
ldm->InMemoryOrderModuleList.Flink->Blink =
ldm->InMemoryOrderModuleList.Blink;
break;
}
Cur = Cur->Flink;
} while (Head != Cur);
}
int main()
{
printf("按键开始隐藏\r\n");
getchar();
HideDll();
if (g_isHide == 0)
{
printf("没有成功隐藏\r\n");
system("pause");
return 0;
}
printf("成功隐藏\r\n");
system("pause");
return 0;
}