進程中dll模組的隱藏

來源:互聯網
上載者:User

為了避免自己的某個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)+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

+0×000 InheritedAddressSpace : UChar

+0×001 ReadImageFileExecOptions : UChar

+0×002 BeingDebugged : UChar

+0×003 SpareBool : UChar

+0×004 Mutant : Ptr32 Void

+0×008 ImageBaseAddress : Ptr32 Void

+0×00c Ldr : Ptr32 _PEB_LDR_DATA

+0×010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS

……

+0C處是一個_PEB_LDR_DATA結構指標,裡麵包含了和LDR相關的一些資料,進程的模組鏈表就儲存在Ldr中。下面是_PEB_LDR_DATA的結構:

0: kd> dt nt!_PEB_LDR_DATA

+0×000 Length : Uint4B

+0×004 Initialized : UChar

+0×008 SsHandle : Ptr32 Void

+0×00c InLoadOrderModuleList : _LIST_ENTRY

+0×014 InMemoryOrderModuleList : _LIST_ENTRY

+0×01c InInitializationOrderModuleList : _LIST_ENTRY

+0×024 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%Xrn”, 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%Xrn”, 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“rn”);

 

    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%Xrn”, 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 HideMyselfrn”));

    return
TRUE;

}

這樣處理之後,通過常規的枚舉進程方式已經枚舉不到隱藏模組,ProcessExplorer也無法枚舉。但是,通過枚舉進程記憶體空間等非常規方法,仍然是可以找到的。關於PSAPI和Toolhelp函數枚舉模組的原理,可以逆向Windows代碼,或者尋找網上的代碼看看就明白了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.