進程中dll模塊的隱藏

進程中dll模塊的隱藏

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

NetRoc

http://www.DbgTech.net/

        爲了避免自己的某個dll模塊被別人檢測出來,有時候希望在自己加載一個dll之後,或者將dll注入到他人進程之後避免被檢查出來。這就需要想辦法抹掉這個dll的模塊信息,使得Toolhelppsapi等枚舉模塊的API無法枚舉它。

        我們可以先簡單看看Windows枚舉進程內模塊的辦法吧:

        首先是BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);

        EnumProcessModules實際調用EnumProcessModulesInternal進行枚舉。下面是vistapsapi的代碼片斷:

.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)+24j

.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)+3Ej

.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

其中,InLoadOrderModuleListInMemoryOrderModuleListInInitializationOrderModuleList就是進程當前已加載模塊的鏈表,只是按照不同的方式排序。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也無法枚舉。但是,通過枚舉進程內存空間等非常規方法,仍然是可以找到的。關於PSAPIToolhelp函數枚舉模塊的原理,可以逆向Windows代碼,或者查找網上的代碼看看就明白了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章