进程中dll模块的隐藏

http://netroc682.spaces.live.com/          为了避免自己的某个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代码,或者查找网上的代码看看就明白了。

author:forget

HideModuleFromPEB proc hInstDLL:DWORD
         assume   fs:nothing
         mov      esi,hInstDLL
         xor      eax,eax
         mov      eax,fs:[eax].TEB.Peb
         mov      eax,[eax].PEB.Ldr
         lea      eax,[eax].PEB_LDR_DATA.InLoadOrderModuleList
         @@:
         mov      eax,[eax].LDR_MODULE.InLoadOrderModuleList.Flink
         cmp      esi,[eax].LDR_MODULE.BaseAddress
         jnz      @B
         mov      esi,[eax].LIST_ENTRY.Flink
         mov      ebx,[eax].LIST_ENTRY.Blink
         mov      [ebx].LIST_ENTRY.Flink,esi
         mov      esi,[eax].LIST_ENTRY.Blink
         mov      ebx,[eax].LIST_ENTRY.Flink
         mov      [ebx].LIST_ENTRY.Blink,esi
         lea      eax,[eax].LDR_MODULE.InMemoryOrderModuleList
         mov      esi,[eax].LIST_ENTRY.Flink
         mov      ebx,[eax].LIST_ENTRY.Blink
         mov      [ebx].LIST_ENTRY.Flink,esi
         mov      esi,[eax].LIST_ENTRY.Blink
         mov      ebx,[eax].LIST_ENTRY.Flink
         mov      [ebx].LIST_ENTRY.Blink,esi
         ret
HideModuleFromPEB endp

我也来段 占内存用的,其中testdll是隐式连接。

   void *PEB = NULL;
   void *Ldr = NULL;
   _LIST_ENTRY *Flink = NULL;
   _LIST_ENTRY *p = NULL;
   BYTE   *BaseAddress = NULL;
   BYTE   *FullDllName = NULL;
   __asm
   {
     mov eax,fs:[0x30]
     mov PEB,eax
   }
   Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) );
   Flink = (_LIST_ENTRY*)*( ( void ** )( ( unsigned char * )Ldr+ 0x0c ) );
   p = Flink;
   do
   {
     BaseAddress = *( ( BYTE ** )( ( unsigned char * )p+ 0x18 ) );
     FullDllName = *( ( BYTE ** )( ( unsigned char * )p+ 0x28 ) );
     LPSTR strFullDllName;
     UnicodeToAnsi((LPCOLESTR)FullDllName,&strFullDllName);
     if( strFullDllName )
     {
       if( strstr(strFullDllName,"testdll") )
       {
         *(LPDWORD)((LPBYTE)p + 0x38) = 1;
       }
     }
     CO_SAFE_DELETE(strFullDllName);
     p = p->Flink;
   }
   while ( Flink != p );

   FreeLibrary(GetModuleHandle("testdll.dll"));

   LPVOID lpdata = VirtualAlloc((LPVOID)NULL,1024*1024*6,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
   if( lpdata != (LPVOID)0x400000 )
   {
     return FALSE;
   }

都发代码片段,我也来一个

     while(modulo->BaseAddress != 0)
   {
        if( (ULONG_PTR)modulo->BaseAddress == DllHandle)
      {
           if(modulo->InInitializationOrderModuleList.Blink == NULL) return FALSE;

           prec = (LDR_MODULE*)(ULONG_PTR)((ULONG_PTR)modulo->InInitializationOrderModuleList.Blink - 16);
           next = (LDR_MODULE*)(ULONG_PTR)((ULONG_PTR)modulo->InInitializationOrderModuleList.Flink - 16);

           prec->InInitializationOrderModuleList.Flink = modulo->InInitializationOrderModuleList.Flink;
           next->InInitializationOrderModuleList.Blink = modulo->InInitializationOrderModuleList.Blink;  

           prec = (LDR_MODULE*)modulo->InLoadOrderModuleList.Blink;
           next = (LDR_MODULE*)modulo->InLoadOrderModuleList.Flink;

           prec->InLoadOrderModuleList.Flink = modulo->InLoadOrderModuleList.Flink;
           prec->InMemoryOrderModuleList.Flink = modulo->InMemoryOrderModuleList.Flink;

           next->InLoadOrderModuleList.Blink = modulo->InLoadOrderModuleList.Blink;
           next->InMemoryOrderModuleList.Blink = modulo->InMemoryOrderModuleList.Blink;
          
           return TRUE;
      }
           modulo = (LDR_MODULE*)modulo->InLoadOrderModuleList.Flink;
   }

通过VirtualQueryEx函数列举出进程内虚拟内存的段,然后根据PE结构和内存属性来定位Image文件的映像基地址,即可确认以下三项数据,     该数据是连续的,
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
在内存中搜索这个三个数据,即可定位LDR。

iceword 可能查出

from pediy

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 提取进程所有DLL文件的工具是一种用于获取一个正在运行的进程所加载的所有动态链接库文件的软件工具。通过使用该工具,我们可以快速、方便地获取这些DLL文件,并进行分析、调试或其他进一步的处理。 这样的工具通常具有以下功能: 1. 进程选择:可以从当前正在运行的进程列表选择要提取DLL文件的目标进程。 2. DLL文件列表:显示目标进程已加载的所有DLL文件,包括它们的名称、路径和版本信息等。 3. 提取DLL文件:提供一键提取目标进程加载的所有DLL文件的功能。一旦点击提取按钮,工具将自动将DLL文件保存到指定的目录。 4. 进度跟踪:显示提取过程的进度,以便确定提取是否正在进行,以及何时完成。 通过使用这样的工具,我们可以更好地了解一个进程运行时所依赖的DLL文件。这对于调试过程的问题定位、恶意软件分析和逆向工程等活动非常有用。对于开发人员和系统管理员来说,提取进程所有DLL的工具也是一种有助于进行性能优化和冲突解决的实用程序。 当然,使用这样的工具需要注意保护个人隐私和合法性。确保在合法授权和合规的情况下使用该工具,以避免滥用和非法使用。 ### 回答2: 提取进程所有 DLL 的工具是指一个可以帮助提取指定进程运行时加载的所有动态链接库(DLL)文件的辅助工具。一些开发者和研究人员可能会使用这样的工具来分析特定进程的依赖关系、检查运行时加载的 DLL 文件以及帮助解决问题的需要。 这种工具通常会提供一个用户界面或命令行界面,能够让用户选择要检查的进程和提取 DLL 文件的保存路径。它会扫描选择的进程的内存,并找到每个加载的 DLL 文件。提取的 DLL 文件将被保存到指定的文件夹,以便进一步分析。 使用这种工具可以有很多应用场景。例如,当一个进程运行异常或崩溃时,提取进程所有 DLL 的工具可以帮助开发者分析问题的根本原因,查找是否存在错误的或冲突的 DLL 文件。另外,这些工具还可以用于检查一个已知进程的依赖关系,帮助开发者确定是否缺少某些必需的 DLL 文件。 总结而言,提取进程所有 DLL 的工具是一种方便的辅助工具,可帮助开发者分析和处理进程相关的 DLL 文件问题。通过提取并保存 DLL 文件,开发者可以更好地了解进程的运行环境,并解决与 DLL 文件相关的错误和冲突。 ### 回答3: 提取进程所有DLL的工具是指能够将运行进程所加载的DLL文件提取出来的软件工具。这种工具的主要应用场景是在进行软件逆向工程、系统调试以及恶意软件分析等方面。 一种常用的提取进程所有DLL的工具是Process Explorer。它是一款由微软提供的免费软件,可以用于监视系统上的进程活动情况。在Process Explorer,我们可以通过选择目标进程,然后在菜单栏点击"View" -> "Lower Pane View" -> "DLLs",即可显示该进程所加载的所有DLL文件。然后,我们可以将这些DLL文件以二进制形式导出,以供进一步分析和处理。 另外,还有一些第三方工具也可以用于提取进程所有DLL。例如,有一款叫做PE-bear的工具,它是一款功能强大的二进制文件编辑器,可以用于查看和编辑PE文件(可执行文件、DLL等)。我们可以使用PE-bear打开一个进程所在的PE文件,然后在其导出目录查找并导出所有的DLL文件。这种方式相对灵活,可以针对某个特定的进程进行DLL提取,同时也能够在提取过程进行一些其他的编辑和调试操作。 总体来说,提取进程所有DLL的工具有很多种,选择合适的工具取决于具体的需求和场景。这些工具都可以帮助我们从运行进程提取所加载的DLL文件,并在进行软件逆向工程、系统调试和恶意软件分析等方面发挥关键作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值