Jump to content
me.mello

The covert way to find the Reference Count of DLL

Recommended Posts

Un articol super, daca iti intra in mana cu usurinta vei invata sa injectezi/elimini un .dll din orice remote process vei dori.

About the DLL Reference Count

Reference count or load count of the DLL is the number of times the DLL is loaded into the process. Each time the DLL is loaded (through LoadLibrary) into the process its reference count is incremented by 1 and each time the DLL is freed (through FreeLibrary) from the process, reference count is decremented by 1. When the reference count reaches 0, the DLL is completely unmapped from the process.

Windows APIs does not give much information about loaded DLLs. Windows provides Tool Help library to retrieve information about DLLs loaded into process but it gives very basic information such as name, handle of DLL. In order to get more information, one need to dig deeper into the windows world.

How to find the DLL Reference Count?

Reference count for the DLL is stored in the PEB (Process Environment Block) for that process. PEB contains the linked list of DLL Module structures which contain complete information about that particular DLL.

Here are the detailed steps.

1. Get address of PEB block

PEB block for any process is usually found at address 0x7ffdf000. However there is standard way to get this address. There is undocumented function ZwQueryInformationProcess from NTDLL.DLL which can be used to retrieve the PROCESS_BASIC_INFORMATION. The PBI structure is shown below.


struct _PROCESS_BASIC_INFORMATION
{
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

The second member PebBaseAddress contains the address of PEB which can be used to get the list of loaded modules.

2. Get list of loaded DLLs from PEB.

Once you get the address of PEB, you can use use ReadProcessMemory API to read the PEB from the target process.


PEB peb;
ReadProcessMemory(hprocess, pbi.PebBaseAddress, &peb, 16, &dwSize)

PEB is a big structure hence I cannot dump it here. One of the member that is interesting to us is PPEB_LDR_DATA which is pointer to loader data structure containing linked list of loaded modules. Now from PEB, you can get PEB_LDR_DATA structure as follows.


PEB_LDR_DATA peb_ldr_data;
ReadProcessMemory(hprocess, peb.Ldr, &peb_ldr_data, sizeof(peb_ldr_data), &dwSize);

struct _PEB_LDR_DATA
{
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

PEB_LDR_DATA structure contains the pointers to 3 linked lists each of which list the modules in different order. Now its just a matter of going through each module by following one of this linked list.

3. Retrieve load count of the DLL.

Now we will go through each of the modules by following the InLoadOrderModuleList pointer. Information about each of these modules is retrieved using ReadProcessMemory function. The structure LDR_MODULE representing each module is given below.


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;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;

It contains lot of information about a module which you don't get using high level APIs. One of the member is LoadCount which is nothing but the reference count of the DLL.


LDR_MODULE peb_ldr_module;
void *readAddr = (void*) peb_ldr_data.InLoadOrderModuleList.Flink;

// Go through each modules one by one in their load order.
while( ReadProcessMemory(hprocess, readAddr, &peb_ldr_module, sizeof(peb_ldr_module), &dwSize) )
{
// Get the reference count of the DLL
loadCount = (signed short)peb_ldr_module.LoadCount;

readAddr = (void *) peb_ldr_module.InLoadOrderModuleList.Flink;
}

If load count for a DLL is -1 then the DLL is statically linked otherwise its dynamically loaded.

Where this will be usefull?

There are number of instances when there is a need to know the reference count of DLL. One typical case is when you want to free the DLL from the remote process. Many spyware programs uses the DLL injection or similar technique to get loaded themselves into the legitimate windows process and remain hidden from normal user. In order to free such hidden DLLs from that process one must know its reference count so that it can be completely freed from that process. Unless the DLL is freed from the process, it cannot be removed from the disk.

Reference count is also useful to determine if the DLL is statically or dynamically loaded.

Edited by me.mello
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...