吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11450|回复: 10
收起左侧

[调试逆向] 进程中dll模块的隐藏 转

  [复制链接]
Ruin 发表于 2012-6-15 00:19
进程中dll模块的隐藏


        为了避免自己的某个dll模块被别人检测出来,有时候希望在自己加载一个dll之后,或者将dll注入到他人进程之后避免被检查出来。这就需要想办法抹掉这个dll的模块信息,使得Toolhelp、psapi等枚举模块的API无法枚举它。
        我们可以先简单看看Windows枚举进程内模块的办法吧:
        首先是BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
        EnumProcessModules实际调用EnumProcessModulesInternal进行枚举。下面是vista下psapi的代码片断:
.text:514024B8                 push    ebx
.text:514024B9                 push    18h
.text:514024BB                 lea     eax, [ebp+stProcessBasicInfo]
.text:514024BE                 push    eax
.text:514024BF                 push    ebx  ;ebx=0
.text:514024C0                 push    [ebp+hProcess]
.text:514024C3                 call    ds:__imp__NtQueryInformationProcess@20 ; NtQueryInformationProcess(x,x,x,x,x)
.text:514024C9                 cmp     eax, ebx
.text:514024CB                 jge     short loc_514024E0
        调用NtQueryInformationProcess获得ProcessBasicInformation,在PROCESS_BASIC_INFORMATION结构中取得PEB地址。然后读取指定进程PEB中的数据
text:514024E0 loc_514024E0:                           ; CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+24 j
.text:514024E0                 mov     eax, [ebp+stProcessBasicInfo.PebBaseAddress]
.text:514024E3                 cmp     eax, ebx
.text:514024E5                 jnz     short loc_514024EE
.text:514024E7                 push    8000000Dh
.text:514024EC                 jmp     short loc_514024CE
.text:514024EE ; ---------------------------------------------------------------------------
.text:514024EE
.text:514024EE loc_514024EE:                           ; CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+3E j
.text:514024EE                 push    ebx             ; lpNumberOfBytesRead
.text:514024EF                 push    4               ; nSize
.text:514024F1                 lea     ecx, [ebp+Ldr]
.text:514024F4                 push    ecx             ; lpBuffer
.text:514024F5                 add     eax, 0Ch
.text:514024F8                 push    eax             ; lpBaseAddress
.text:514024F9                 push    [ebp+hProcess]  ; hProcess
.text:514024FC                 mov     edi, ds:__imp__ReadProcessMemory@20 ; ReadProcessMemory(x,x,x,x,x)
.text:51402502                 call    edi ; ReadProcessMemory(x,x,x,x,x) ; ReadProcessMemory(x,x,x,x,x)
这里读取的是PEB地址+0C处的四个字节。
通过WinDbg我们可以看看nt!_PEB的结构
0: kd> dt nt!_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
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
……
+0C处是一个_PEB_LDR_DATA结构指针,里面包含了和LDR相关的一些数据,进程的模块链表就保存在Ldr中。下面是_PEB_LDR_DATA的结构:
0: kd> dt nt!_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
其中,InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList就是进程当前已加载模块的链表,只是按照不同的方式排序。EnumProcessModules是通过InMemoryOrderModuleList链表枚举的,而根据Win2k代码,ToolHelp32函数是通过InLoadOrderModuleList枚举。这三个_LIST_ENTRY都是在一个RTL_PROCESS_MODULE_INFORMATION结构中的成员。这个结构在2k代码中有引用,不过没有确切的定义,下面是ReactOS中的定义,不过看起来我的vista PSAPI中使用的结构已经有所变化了,这里只作参考。
//
// Loader Data Table Entry
//
typedef struct _LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    ULONG Flags;
    USHORT LoadCount;
    USHORT TlsIndex;
    union
    {
        LIST_ENTRY HashLinks;
        PVOID SectionPointer;
    };
    ULONG CheckSum;
    union
    {
        ULONG TimeDateStamp;
        PVOID LoadedImports;
    };
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
到这里,隐藏模块的方法就已经明了了:通过PEB取得Ldr数据,拿到三个模块链表,并将要隐藏的模块断链即可。下面是主要代码实现:
BOOL HideMyself()
{
  HMODULE hMod = GetModuleHandle( _T( "ntdll.dll"));
  HMODULE hModMyself = GetModuleHandle( _T("dll.dll"));
  pfnNtQueryInformationProcess p = (pfnNtQueryInformationProcess)::GetProcAddress( hMod, "NtQueryInformationProcess");

  PROCESS_BASIC_INFORMATION stInfo = {0};
  DWORD dwRetnLen = 0;
  DWORD dw = p( GetCurrentProcess(), 0, &stInfo, sizeof(stInfo), &dwRetnLen);

  PPEB pPeb = stInfo.PebBaseAddress;
  PLIST_ENTRY ListHead, Current;
  PLDR_DATA_TABLE_ENTRY pstEntry = NULL;

  ListHead = &( stInfo.PebBaseAddress->Ldr->InLoadOrderModuleList);
  Current = ListHead->Flink;
  while ( Current != ListHead)
  {
    pstEntry = CONTAINING_RECORD( Current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
    //DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint);
    if ( pstEntry->DllBase == hModMyself)
    {
      pstEntry->InLoadOrderLinks.Flink->Blink = pstEntry->InLoadOrderLinks.Blink;
      pstEntry->InLoadOrderLinks.Blink->Flink = pstEntry->InLoadOrderLinks.Flink;
      DebugOut( _T( "Hide injected dll."));
      break;
    }
    Current = pstEntry->InLoadOrderLinks.Flink;
  }

  ListHead = &( stInfo.PebBaseAddress->Ldr->InMemoryOrderModuleList);
  Current = ListHead->Flink;
  while ( Current != ListHead)
  {
    pstEntry = CONTAINING_RECORD( Current, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);
    DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint);
    if ( pstEntry->DllBase == hModMyself)
    {
      pstEntry->InMemoryOrderModuleList.Flink->Blink = pstEntry->InMemoryOrderModuleList.Blink;
      pstEntry->InMemoryOrderModuleList.Blink->Flink = pstEntry->InMemoryOrderModuleList.Flink;
      DebugOut( _T( "Hide injected dll."));
      break;
    }
    Current = pstEntry->InMemoryOrderModuleList.Flink;
  }
  DebugOutW( L"\r\n");

  ListHead = &( stInfo.PebBaseAddress->Ldr->InInitializationOrderModuleList);
  Current = ListHead->Flink;
  while ( Current != ListHead)
  {
    pstEntry = CONTAINING_RECORD( Current, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
    DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint);
    if ( pstEntry->DllBase == hModMyself)
    {
      pstEntry->InInitializationOrderModuleList.Flink->Blink = pstEntry->InInitializationOrderModuleList.Blink;
      pstEntry->InInitializationOrderModuleList.Blink->Flink = pstEntry->InInitializationOrderModuleList.Flink;
      DebugOut( _T( "Hide injected dll."));
      break;
    }
    Current = pstEntry->InInitializationOrderModuleList.Flink;
  }
  //DebugOut( _T("Out HideMyself\r\n"));
  return TRUE;
}
        这样处理之后,通过常规的枚举进程方式已经枚举不到隐藏模块,ProcessExplorer也无法枚举。但是,通过枚举进程内存空间等非常规方法,仍然是可以找到的。关于PSAPI和Toolhelp函数枚举模块的原理,可以逆向Windows代码,或者查找网上的代码看看就明白了。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

hexi7164 发表于 2012-8-2 18:49
都是高手 看不懂啊
1002217709 发表于 2012-8-7 17:08
dec0y 发表于 2012-8-7 16:42
Chenxs110 发表于 2012-8-8 17:30
最好再把vad的属性也改掉
NikolayD 发表于 2012-8-29 14:38
Helpful info. Thanks, Ruin.
半斤八兩 发表于 2012-9-2 23:00
我还以为是原创呢.
satan8 发表于 2012-9-3 02:02

我还以为是原创呢.
头像被屏蔽
vk929495v 发表于 2014-7-21 01:31
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽
苏烟式 发表于 2014-7-21 19:42
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 00:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表