當我們運行程序時,一般情況下會默認加載Ntdll.dll和Kernel32.dll這兩個鏈接庫,在進程未被創建之前Ntdll.dll庫就被默認加載了,三環下任何對其劫持都是無效的,除了該Dll外,其他的Dll都是在程序運行時,在輸入表中查找到對應關系后才會被裝載到內存中的,理論上來說對除NtDll以外的其他庫都是可操作的。
工具下載:工具下載地址:http://lyshark.github.io/soft/PETools.zip
而DLL的裝載是存在先后順序的,當系統開機時smss.exe會將系統中常用的DLL緩存到注冊表計算機\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
中的位置上,我們可以跳轉過去看看里面存放的內容,都是一些常用的函數庫。
當指定DLL需要加載時,系統會首先查詢該表中是否存在有緩存數據,如果有則就直接調用NtMapViewOfSection函數將其映射到特定進程的內存中,如果沒有則就需要根據如下順序動態的查找。
- 先查找,正在加載DLL進程的可執行目錄。
- 查找系統的system32目錄下是否存在。
- 查找,正在加載DLL進程的當前目錄。
- Path環境變量中的定義。
這里就先來演示一下簡單的Dll劫持,首先我們必須指定要劫持的Dll文件,將其中的導出函數全部導出來,導出的輸入表項目只能比原來的多,不能少,導出的方式有很多,比如可以使用AheadLib等工具,快速生成利用代碼,通常可用於劫持的DLL有 lpk.dll,version.dll 等系統DLL,當前程序的第三方DLL同樣可以,本教程並不適用AheadLib工具,而是使用GenEAT.exe工具:
1.先來創建一個DLL並導出兩個函數,然后創建主程序動態的加載這個DLL。
lyshark.cpp 編譯生成為DLL
#include <Windows.h>
extern "C" int __declspec(dllexport)add(int x, int y)
{
return x + y;
}
extern "C" int __declspec(dllexport)sub(int x, int y)
{
return x - y;
}
extern "C" int __declspec(dllexport)mul(int x, int y)
{
return x * y;
}
extern "C" int __declspec(dllexport)divs(int x, int y)
{
return x / y;
}
BOOL APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{
return true;
}
編譯后使用上次制作的PETools工具,執行命令PETools c://lyshark.dll --ShowExport
可看到其導出的函數。
編譯main.cpp 動態加載函數,將lyshark.dll放入同一個目錄下即可,程序運行后會動態調用DLL中的導出函數。
#include <stdio.h>
#include <Windows.h>
typedef int(*lpAdd)(int, int);
typedef int(*lpSub)(int, int);
typedef int(*lpMul)(int, int);
typedef int(*lpDiv)(int, int);
int main(int argc, char *argv[])
{
HINSTANCE DllAddr;
lpAdd addFun;
DllAddr = LoadLibrary(L"lyshark.dll");
addFun = (lpAdd)GetProcAddress(DllAddr, "add");
if (NULL != addFun)
{
int res = addFun(100, 200);
printf("結果: %d \n", res);
}
FreeLibrary(DllAddr);
system("pause");
return 0;
}
下面就來實現函數轉發功能,當程序訪問原DLL時直接將請求轉發到我們自己的DLL中,我們的DLL再將請求轉發到真實的DLL上面,使用本節課的小工具可以快速構建轉發函數表,執行如下命令即可:GenEAT.exe -d c://lyshark.dll -c inject.cpp -n Lok
默認會生成如下樣子,直接在里面加上一個彈窗,然后編譯DLL。
將生成的Dll改名為lyshark.dll把原來的lyshark.dll改為lok.dll
當再次打開時,會先加載彈窗,然后才會完成計算功能,也算是中轉成功了。
你可以對其導出函數進行Hook轉向,讀取參數啥的都沒問題,自由發揮吧。