前幾篇文章,是通過遠端線程的方式來注入目标程序,來實作DLL注入的,這次我們換一個新的方式注入,那就是通過
SetWindowsHookEx來遠端注入。
介紹:
SetWindowsHookEx
HHOOK WINAPI SetWindowsHookEx(
__in int idHook, \\鈎子類型
__in HOOKPROC lpfn, \\回調函數位址
__in HINSTANCE hMod, \\執行個體句柄
__in DWORD dwThreadId); \\線程ID
int idHook:
指的是鈎子的類型,鈎子類型有很多種,一般分為常用的幾種:WH_KEYBOARD、WH_MOUSE
詳情:https://blog.csdn.net/linux7985/article/details/39643577
HOOKPROC lpfn:
回調函數位址,如果dwThreadId ==0 ,或者說是dwThreadId是其他程序下的線程,那麼lpfn必須是DLL中的一個函數位址,否則不做要求。
HINSTANCE hMod:
DLL的基址,也就是DLL子產品句柄,是l包含lpfn函數的DLL基址,如果 dwThreadId 是目前程序下的一個線程,那麼該參數必須為NULL。
DWORD dwThreadId:
線程ID
步驟:
和之前的注入過程基本相同
- 擷取程序ID 通過程序名稱
- 編寫DLL,将需要的函數進行導出
- 擷取目标程序中的線程ID,為了保證線程ID的有效性,把所有的線程ID都擷取出來,一一注入,直到注入成功
- SetWindowsHookEx,實作鈎子注入
擷取程序ID:
https://blog.csdn.net/qq_42021840/article/details/106137368
編寫DLL,将需要的函數進行導出:
要在def檔案中将Sub_1導出
LIBRARY
EXPORTS
Sub_1 @1
BOOL WINAPI DllMain(
HMODULE hinstDLL,
DWORD fdwReason,
LPVOID lpReserved
) //dll main 函數
{
printf("%p\r\n", hinstDLL);
switch (fdwReason)
{
case DLL_PROCESS_DETACH: //0
{
break;
}
case DLL_PROCESS_ATTACH: //1
{
HANDLE ProcessID = (HANDLE)GetCurrentProcessId();
TCHAR v1[MAX_PATH]{ 0 };
_stprintf(v1, _T("%d Success"), ProcessID);
MessageBox(NULL, v1, _T("Matthew"), 4);
break;
}
case DLL_THREAD_ATTACH: //2
{
break;
}
case DLL_THREAD_DETACH: //3
{
break;
}
}
return TRUE;
}
void Sub_1()
{
HANDLE ProcessIdentify = (HANDLE)GetCurrentProcessId();
TCHAR v1[MAX_PATH] = { 0 };
_stprintf(v1, _T("%d Sub_1()"), ProcessIdentify);
MessageBox(NULL, v1, _T("Injection"), 0);
}
擷取目标程序中的線程ID,為了保證線程ID的有效性,把所有的線程ID都擷取出來,一一注入,直到注入成功:
BOOL GetThreadIdentify(HANDLE ProcessIdentify, vector<HANDLE>& ThreadIdentify)
{
BOOL IsOk = FALSE;
HANDLE SnapshotHandle = INVALID_HANDLE_VALUE;
THREADENTRY32 ThreadEntry32 = { 0 };
ThreadEntry32.dwSize = sizeof(THREADENTRY32);
int LastError = 0;
if (IsBadReadPtr(&ProcessIdentify, sizeof(HANDLE)))
{
LastError = ERROR_INVALID_PARAMETER;
goto Exit;
}
SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (SnapshotHandle == INVALID_HANDLE_VALUE)
{
LastError = GetLastError();
goto Exit;
}
if (!Thread32First(SnapshotHandle, &ThreadEntry32))
{
LastError = GetLastError();
goto Exit;
}
do
{
if (ThreadEntry32.th32OwnerProcessID == (DWORD)ProcessIdentify)
{
ThreadIdentify.emplace_back((HANDLE)ThreadEntry32.th32ThreadID);
IsOk = TRUE;
}
} while (Thread32Next(SnapshotHandle, &ThreadEntry32));
Exit:
if (SnapshotHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(SnapshotHandle);
}
SnapshotHandle = INVALID_HANDLE_VALUE;
SetLastError(LastError);
return IsOk;
}
SetWindowsHookEx,實作鈎子注入 :
ModuleBase = LoadLibrary(BufferData);
if (ModuleBase == NULL)
{
LastError = GetLastError();
goto Exit;
}
Sub_1 = GetProcAddress(ModuleBase, "Sub_1");
if (Sub_1 == NULL)
{
LastError = GetLastError();
goto Exit;
}
for (int i = 0; i < ThreadID.size(); ++i)
{
HookHandle = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)Sub_1, ModuleBase, (DWORD)ThreadID[i]);
if (HookHandle != NULL)
{
break;
}
}
效果展示:
DLL加載成功