隐藏DLL模块

1. 数据类型 LIST_ENTRY
说明:内核使用该结构将所有对象维护在一个双向链表中。一个对象分属多个链表是很常见的, Flink 成员是一个向前链接指向下一个 LIST_ENTRY 结构, Blink 成员则是一个向后链接,指向前一个 LIST_ENTRY 结构。通常情况下,这些链表都成环形,也就是说,最后一个 Flink 指向链表中的第一个 LIST_ENTRY 结构,而第一个 Blink 指向最后一个。这样就很容易双向遍历该链表。如果一个程序要遍历整个链表,它需要保存第一个 LIST_ENTRY 结构的地址,以判断是否已遍历了整个链表。如果链表仅包含一个 LIST_ENTRY 结构,那么该 LIST_ENTRY 结构必须引用其自身,也就是说,Flink 和 Blink 都指向其自己。
 
typedef struct _LIST_ENTRY
{
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
}LIST_ENTRY, *PLIST_ENTRY;

0:000> dt _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace    : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged            : UChar
   +0x003 SpareBool                : UChar
   +0x004 Mutant                   : Ptr32 Void
   +0x008 ImageBaseAddress         : Ptr32 Void
   +0x00c Ldr                      : Ptr32 _PEB_LDR_DATA
   …
0:000> dt _PEB_LDR_DATA
ntdll!_PEB_LDR_DATA
   +0x000 Length                          : Uint4B
   +0x004 Initialized                     : UChar
   +0x008 SsHandle                        : Ptr32 Void
   +0x00c InLoadOrderModuleList           : _LIST_ENTRY
   +0x014 InMemoryOrderModuleList         : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY
   +0x024 EntryInProgress                 : Ptr32 Void


typedef struct _PEB_LDR_DATA {
 ULONG                   Length;
 BOOLEAN                 Initialized;
 PVOID                   SsHandle;
 LIST_ENTRY              InLoadOrderModuleList;          //按加载顺序
 LIST_ENTRY              InMemoryOrderModuleList;        //按内存顺序
 LIST_ENTRY              InInitializationOrderModuleList;//按初始化顺序
 PVOID   EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
该结构的黑体三个成员是指向LDR_MODULE链表结构中相应三条双向链表头的指针,分别是按照加载顺序、在内存中地址顺序和初始化顺序排列的模块信息结构的指针.
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 _UNICODE_STRING {
 USHORT  Length;
 USHORT  MaximumLength;
 PWSTR   Buffer;
} UNICODE_STRING, *PUNICODE_STRING

汇编:
MOV EAX, DWORD PTR FS:[30] ;获取PEB基址
MOV EAX, DWORD PTR DS:[EAX+C] ;获取PEB_LDR_DATA结构指针
MOV ESI, DWORD PTR DS:[EAX+1C] ;获取InInitializationOrderModuleList成员指针
LODS DWORD PTR DS:[ESI] ;获取双向链表当前节点的后继指针
MOV EBX, DWORD PTR DS:[EAX+8] ;取其基地址,该结构当前包含的是kernel32.dll

2 遍历双向链表
PEB_LDR_DATA  *pPEBLDR;
LDR_MODULE    *pLdrMod;
LIST_ENTRY *pListEntry, *pStart;
void *p, *BaseAddress, *FullDllName;
_asm
{
     mov eax, fs:[0x30]
     mov eax, [eax + 0x0C]
     mov pPEBLDR, eax
}
printf("PEB_LDR_DATA:0x%08x\n",pPEBLDR);
printf("LDR->Length:0x%08x\n",pPEBLDR->Length);
printf("LDR->InLoadOrderModuleList:\t0x%08x\n",pPEBLDR->InLoadOrderModuleList);
printf("LDR->InMemoryOrderModuleList:\t0x%08x\n",pPEBLDR->InMemoryOrderModuleList);
printf("LDR->InInitializationOrderModuleList:\t0x%08x\n",pPEBLDR->InInitializationOrderModuleList);
//遍历双向链表
pListEntry = (LIST_ENTRY*)(PUCHAR)&(pPEBLDR -> InLoadOrderModuleList);
pStart = pListEntry;
printf("BaseAddress\t\tFullDllName\n====================================\n");
do
{
       pListEntry = pListEntry -> Flink;
       pLdrMod = (LDR_MODULE*)pListEntry;
       printf("0x%08x\t\t",pLdrMod->BaseAddress);
wprintf(L"%s\n",pLdrMod->FullDllName.Buffer);
}while(pListEntry != pStart);

3高级应用(隐藏模块)
#include<windows.h>
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;//按初始化顺序
 PVOID          EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

//每个模块信息的LDR_MODULE部分
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;
//隐藏模块
VOID HideModule(HMODULE hLibrary);

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 HMODULE hMod = NULL;
 switch( ul_reason_for_call )
 {
 case DLL_PROCESS_ATTACH:
  HideModule((HMODULE)hModule);
  break;
 }
    return TRUE;
}
VOID HideModule(HMODULE hLibrary)
{
     PPEB_LDR_DATA pLdr = NULL;
     PLDR_MODULE FirstModule = NULL, GurrentModule = NULL;
     __try
 {
          __asm
         {
               mov esi, fs:[0x30]
               mov esi, [esi + 0x0C]
               mov pLdr,esi
}
FirstModule = (pLDR_MODULE)(pLdr -> InLoadOrderModuleList.Flink);
         CurrentModule = FirstModule;
         while(!(CurrentModule ->BaseAddress == hLibrary))
         {
               CurrentModule = (PLDR_MODULE)(CurrentModule
-> InLoadOrderModuleList.Blink );
               if(CurrentModule == FirstModule)
               break;
}
if(CurrentModule -> BaseAddress != hLibrary) return;
//Dll解除链接
((PLDR_MODULE)(CurrentModule -> InLoadOrderModuleList.Flink))
-> InLoadOrderModuleList.Blink = CurrentModule -> InLoadOrderModuleList.Blink;
((PLDR_MODULE)(CurrentModule->InLoadOrderModuleList.Blink))
->InLoadOrderModuleList.Flink = CurrentModule->InLoadOrderModuleList.Flink;
memset(CurrentModule->FullDllName.Buffer, 0, CurrentModule->FullDllName.Length);
memset(CurrentModule, 0, sizeof(PLDR_MODULE));
__except(EXCEPTION_EXECUTE_HANDLER)
 {
  return;
 }
}

3 检测隐藏进程
说明: 对于Windows下的每一个进程,系统都会给它分配一个excutive process (EPROCESS) block。该结构包含和指向一系列其他相关的数据结构,比如每个进程的所有线程信息。EPROCESS及其所有相关数据结构都位于系统空间,只有Process environment block(peb)是位于进程地址空间,因为它包含由用户模式代码所决定的信息.
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER
   +0x078 ExitTime         : _LARGE_INTEGER
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : Ptr32 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY
   +0x090 QuotaUsage       : [3] Uint4B
   +0x09c QuotaPeak        : [3] Uint4B
   +0x0a8 CommitCharge     : Uint4B
   +0x0ac PeakVirtualSize  : Uint4B
   +0x0b0 VirtualSize      : Uint4B
   +0x0b4 SessionProcessLinks : _LIST_ENTRY
   +0x0bc DebugPort        : Ptr32 Void
   +0x0c0 ExceptionPort    : Ptr32 Void
   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : Uint4B
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   …

0:000> dt _LIST_ENTRY
ntdll!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

0:000> dt _HANDLE_TABLE
ntdll!_HANDLE_TABLE
   +0x000 TableCode        : Uint4B
   +0x004 QuotaProcess     : Ptr32 _EPROCESS
   +0x008 UniqueProcessId  : Ptr32 Void
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : Ptr32 _HANDLE_TRACE_DEBUG_INFO
   +0x02c ExtraInfoPages   : Int4B
   +0x030 FirstFree        : Uint4B
   +0x034 LastFree         : Uint4B
   +0x038 NextHandleNeedingPool : Uint4B
   +0x03c HandleCount      : Int4B
   +0x040 Flags            : Uint4B
   +0x040 StrictFIFO       : Pos 0, 1 Bit

注意:ObjectTable结构体内偏移0x008处的UniqueProcessId就是当前EPROCESS对应进程的ID号。同时,ObjectTable结构体内偏移0x004处有一个指针QuotaProcess,指向了当前进程的EPROCESS结构(Sytem进程比较特殊,对应的指针为空)。因而,我们不仅能够得到进程的ID号,而且可以获得进程的其他信息.
对于偏移0x088处的ActiveProcessLinks,我们先通过函数PsGetCurrentProcess获得任意进程的EPROCESS的地址,该结构偏移0x084处存放进程ID的指针,读取该指针处的ID作为循环的终止判断条件。到EPROCESS的偏移0x088处ActiveProcessLinks中读取当前进程之后的进程的ActiveProcessLinks指针,通过该指针计算其EPROCESS地址。如此循环,即可以获得所有活动进程的信息.

 

 
 
1. 数据类型 LIST_ENTRY
说明:内核使用该结构将所有对象维护在一个双向链表中。一个对象分属多个链表是很常见的, Flink 成员是一个向前链接指向下一个 LIST_ENTRY 结构, Blink 成员则是一个向后链接,指向前一个 LIST_ENTRY 结构。通常情况下,这些链表都成环形,也就是说,最后一个 Flink 指向链表中的第一个 LIST_ENTRY 结构,而第一个 Blink 指向最后一个。这样就很容易双向遍历该链表。如果一个程序要遍历整个链表,它需要保存第一个 LIST_ENTRY 结构的地址,以判断是否已遍历了整个链表。如果链表仅包含一个 LIST_ENTRY 结构,那么该 LIST_ENTRY 结构必须引用其自身,也就是说,Flink 和 Blink 都指向其自己。
 
typedef struct _LIST_ENTRY
{
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
}LIST_ENTRY, *PLIST_ENTRY;

0:000> dt _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace    : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged            : UChar
   +0x003 SpareBool                : UChar
   +0x004 Mutant                   : Ptr32 Void
   +0x008 ImageBaseAddress         : Ptr32 Void
   +0x00c Ldr                      : Ptr32 _PEB_LDR_DATA
   …
0:000> dt _PEB_LDR_DATA
ntdll!_PEB_LDR_DATA
   +0x000 Length                          : Uint4B
   +0x004 Initialized                     : UChar
   +0x008 SsHandle                        : Ptr32 Void
   +0x00c InLoadOrderModuleList           : _LIST_ENTRY
   +0x014 InMemoryOrderModuleList         : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY
   +0x024 EntryInProgress                 : Ptr32 Void


typedef struct _PEB_LDR_DATA {
 ULONG                   Length;
 BOOLEAN                 Initialized;
 PVOID                   SsHandle;
 LIST_ENTRY              InLoadOrderModuleList;          //按加载顺序
 LIST_ENTRY              InMemoryOrderModuleList;        //按内存顺序
 LIST_ENTRY              InInitializationOrderModuleList;//按初始化顺序
 PVOID   EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
该结构的黑体三个成员是指向LDR_MODULE链表结构中相应三条双向链表头的指针,分别是按照加载顺序、在内存中地址顺序和初始化顺序排列的模块信息结构的指针.
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 _UNICODE_STRING {
 USHORT  Length;
 USHORT  MaximumLength;
 PWSTR   Buffer;
} UNICODE_STRING, *PUNICODE_STRING

汇编:
MOV EAX, DWORD PTR FS:[30] ;获取PEB基址
MOV EAX, DWORD PTR DS:[EAX+C] ;获取PEB_LDR_DATA结构指针
MOV ESI, DWORD PTR DS:[EAX+1C] ;获取InInitializationOrderModuleList成员指针
LODS DWORD PTR DS:[ESI] ;获取双向链表当前节点的后继指针
MOV EBX, DWORD PTR DS:[EAX+8] ;取其基地址,该结构当前包含的是kernel32.dll

2 遍历双向链表
PEB_LDR_DATA  *pPEBLDR;
LDR_MODULE    *pLdrMod;
LIST_ENTRY *pListEntry, *pStart;
void *p, *BaseAddress, *FullDllName;
_asm
{
     mov eax, fs:[0x30]
     mov eax, [eax + 0x0C]
     mov pPEBLDR, eax
}
printf("PEB_LDR_DATA:0x%08x\n",pPEBLDR);
printf("LDR->Length:0x%08x\n",pPEBLDR->Length);
printf("LDR->InLoadOrderModuleList:\t0x%08x\n",pPEBLDR->InLoadOrderModuleList);
printf("LDR->InMemoryOrderModuleList:\t0x%08x\n",pPEBLDR->InMemoryOrderModuleList);
printf("LDR->InInitializationOrderModuleList:\t0x%08x\n",pPEBLDR->InInitializationOrderModuleList);
//遍历双向链表
pListEntry = (LIST_ENTRY*)(PUCHAR)&(pPEBLDR -> InLoadOrderModuleList);
pStart = pListEntry;
printf("BaseAddress\t\tFullDllName\n====================================\n");
do
{
       pListEntry = pListEntry -> Flink;
       pLdrMod = (LDR_MODULE*)pListEntry;
       printf("0x%08x\t\t",pLdrMod->BaseAddress);
wprintf(L"%s\n",pLdrMod->FullDllName.Buffer);
}while(pListEntry != pStart);

3高级应用(隐藏模块)
#include<windows.h>
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;//按初始化顺序
 PVOID          EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

//每个模块信息的LDR_MODULE部分
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;
//隐藏模块
VOID HideModule(HMODULE hLibrary);

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 HMODULE hMod = NULL;
 switch( ul_reason_for_call )
 {
 case DLL_PROCESS_ATTACH:
  HideModule((HMODULE)hModule);
  break;
 }
    return TRUE;
}
VOID HideModule(HMODULE hLibrary)
{
     PPEB_LDR_DATA pLdr = NULL;
     PLDR_MODULE FirstModule = NULL, GurrentModule = NULL;
     __try
 {
          __asm
         {
               mov esi, fs:[0x30]
               mov esi, [esi + 0x0C]
               mov pLdr,esi
}
FirstModule = (pLDR_MODULE)(pLdr -> InLoadOrderModuleList.Flink);
         CurrentModule = FirstModule;
         while(!(CurrentModule ->BaseAddress == hLibrary))
         {
               CurrentModule = (PLDR_MODULE)(CurrentModule
-> InLoadOrderModuleList.Blink );
               if(CurrentModule == FirstModule)
               break;
}
if(CurrentModule -> BaseAddress != hLibrary) return;
//Dll解除链接
((PLDR_MODULE)(CurrentModule -> InLoadOrderModuleList.Flink))
-> InLoadOrderModuleList.Blink = CurrentModule -> InLoadOrderModuleList.Blink;
((PLDR_MODULE)(CurrentModule->InLoadOrderModuleList.Blink))
->InLoadOrderModuleList.Flink = CurrentModule->InLoadOrderModuleList.Flink;
memset(CurrentModule->FullDllName.Buffer, 0, CurrentModule->FullDllName.Length);
memset(CurrentModule, 0, sizeof(PLDR_MODULE));
__except(EXCEPTION_EXECUTE_HANDLER)
 {
  return;
 }
}

3 检测隐藏进程
说明: 对于Windows下的每一个进程,系统都会给它分配一个excutive process (EPROCESS) block。该结构包含和指向一系列其他相关的数据结构,比如每个进程的所有线程信息。EPROCESS及其所有相关数据结构都位于系统空间,只有Process environment block(peb)是位于进程地址空间,因为它包含由用户模式代码所决定的信息.
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER
   +0x078 ExitTime         : _LARGE_INTEGER
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : Ptr32 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY
   +0x090 QuotaUsage       : [3] Uint4B
   +0x09c QuotaPeak        : [3] Uint4B
   +0x0a8 CommitCharge     : Uint4B
   +0x0ac PeakVirtualSize  : Uint4B
   +0x0b0 VirtualSize      : Uint4B
   +0x0b4 SessionProcessLinks : _LIST_ENTRY
   +0x0bc DebugPort        : Ptr32 Void
   +0x0c0 ExceptionPort    : Ptr32 Void
   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : Uint4B
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   …

0:000> dt _LIST_ENTRY
ntdll!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

0:000> dt _HANDLE_TABLE
ntdll!_HANDLE_TABLE
   +0x000 TableCode        : Uint4B
   +0x004 QuotaProcess     : Ptr32 _EPROCESS
   +0x008 UniqueProcessId  : Ptr32 Void
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : Ptr32 _HANDLE_TRACE_DEBUG_INFO
   +0x02c ExtraInfoPages   : Int4B
   +0x030 FirstFree        : Uint4B
   +0x034 LastFree         : Uint4B
   +0x038 NextHandleNeedingPool : Uint4B
   +0x03c HandleCount      : Int4B
   +0x040 Flags            : Uint4B
   +0x040 StrictFIFO       : Pos 0, 1 Bit

注意:ObjectTable结构体内偏移0x008处的UniqueProcessId就是当前EPROCESS对应进程的ID号。同时,ObjectTable结构体内偏移0x004处有一个指针QuotaProcess,指向了当前进程的EPROCESS结构(Sytem进程比较特殊,对应的指针为空)。因而,我们不仅能够得到进程的ID号,而且可以获得进程的其他信息.
对于偏移0x088处的ActiveProcessLinks,我们先通过函数PsGetCurrentProcess获得任意进程的EPROCESS的地址,该结构偏移0x084处存放进程ID的指针,读取该指针处的ID作为循环的终止判断条件。到EPROCESS的偏移0x088处ActiveProcessLinks中读取当前进程之后的进程的ActiveProcessLinks指针,通过该指针计算其EPROCESS地址。如此循环,即可以获得所有活动进程的信息.

 

 

posted @ 2012-12-07 09:35  小金马  阅读(752)  评论(0编辑  收藏  举报