日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

redistemplate注入为null_Windows DLL 注入技术

發布時間:2023/12/13 windows 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redistemplate注入为null_Windows DLL 注入技术 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Windows DLL 注入技術

本文主要介紹四種常見的 Windows DLL 注入技術。

分別為全局鉤子、遠線程鉤子、突破 SESSION 0 隔離的遠線程注入和 APC 注入。

全局鉤子注入

Windows 中大部分應用是基于 Windows 的消息機制,Windows提供截獲這些消息的鉤子函數。

根據鉤子作用的不同范圍,鉤子可以被分為全局和局部鉤子。局部鉤子是針對某個線程的,全局鉤子是只要有使用消息機制的應用。接下來我們主要來看下利用SetWindowsHookEx實現全局鉤子。

SetWindowsHookEx函數介紹

HHOOK?SetWindowsHookEx(int???????idHook,?//?要安裝的鉤子程序的類型
??HOOKPROC??lpfn,?//?指向鉤子函數的指針
??HINSTANCE?hmod,?//?指向鉤子過程的DLL的句柄
??DWORD?????dwThreadId?//?與鉤子進程關聯的線程標識符
);
//?具體詳細介紹可以查閱msdn文檔,里面有更為詳細的介紹

實現過程

首先我們需要創建一個windowsHookDll DLL,這個DLL在安裝全局鉤子后只要系統中的其他進程接收到可以發出鉤子的消息,這個DLL就會被加載到此進程的地址空間中。這樣便實現了Dll注入。

具體實現代碼如下:

#include?"Hook.h"
#include?

extern?HMODULE?g_hDllModule;
//?共享內存
#pragma?data_seg("mydata")?
HHOOK?g_hHook?=?NULL;
#pragma?data_seg()
#pragma?comment(linker,?"/SECTION:mydata,RWS")


//?鉤子回調函數
LRESULT?GetMsgProc(int?code,
?WPARAM?wParam,
?LPARAM?lParam){
?return?::CallNextHookEx(g_hHook,?code,?wParam,?lParam);
}

//?注冊鉤子
BOOL?SetHook(){
?g_hHook?=?SetWindowsHookEx(WH_GETMESSAGE,?(HOOKPROC)GetMsgProc,?g_hDllModule,?0);?//使用WH_GETMESSAGE?確保DLL能夠注入所有的進程
?if?(g_hHook)
?{
??return?TRUE;
?}
?return?FALSE;
}

//?卸載鉤子
BOOL?UnSetHook(){
?if?(g_hHook)
?{
??UnhookWindowsHookEx(g_hHook);
?}
?return?TRUE;
}

試驗結果

新建TestHook.exe程序,首先加載windowsHookDll.dll導出函數SetHook并調用。在注冊成功后用ProcessExplorer.exe察看explorer.exe中的加載情況。

windowsHookDll成功被explorer.exe加載

如果想要卸載可調用函數UnSetHook,執行完成后再觀察explorer.exe是否加載了windowsHookDll.dll。

遠線程注入

遠線程注入是指一個進程在另一個進程中創建線程的技術。主要是利用LoadLibrary在所有進程空間中的地址是一樣,進程在另一個進程中創建線程時傳入LoadLibrary的地址和我們要注入的DLL的路徑,這樣在另一個進程中就能通過LoadLibray加載DLL到進程空間中。

說起來簡單,但是實現起來卻有幾大難點需要注意的。

  • 如何將DLL路徑傳給另一個進程,因為進程之間是相互隔離的,所以我們要在我們要注入的進程中申請內存。
  • 需要對打開的進程進行提權,這就要求我們的注入程序要有管理員以上的權限。

函數介紹

HANDLE?OpenProcess(
??DWORD?dwDesiredAccess,?//?進程訪問權限
??BOOL??bInheritHandle,?//?子進程是否繼承此句柄
??DWORD?dwProcessId?//?要打開的進程id
);

//?分配指定進程的內存
LPVOID?VirtualAllocEx(
??HANDLE?hProcess,?//?進程句柄
??LPVOID?lpAddress,?//?要分配內存起始地址,為NULL則自動分配
??SIZE_T?dwSize,?//?要分配的內存大小
??DWORD??flAllocationType,//?內存分配類型
??DWORD??flProtect?//?內存保護(讀寫)
);

//?寫入內存數據
BOOL?WriteProcessMemory(
??HANDLE??hProcess,?//?進程句柄
??LPVOID??lpBaseAddress,?//?目標進程緩沖區地址
??LPCVOID?lpBuffer,?//?要寫入數據的地址
??SIZE_T??nSize,?//?數據大小
??SIZE_T??*lpNumberOfBytesWritten?//?寫入數據的返回大小,?為NULL則忽略此參數
);

//?在另一個進程中創建線程
HANDLE?CreateRemoteThread(
??HANDLE?????????????????hProcess,?//?進程句柄
??LPSECURITY_ATTRIBUTES??lpThreadAttributes,?//?線程安全描述符
??SIZE_T?????????????????dwStackSize,?//?堆棧的初始大小
??LPTHREAD_START_ROUTINE?lpStartAddress,?//?函數地址(存在于另一個進程中)
??LPVOID?????????????????lpParameter,?//?函數的參數
??DWORD??????????????????dwCreationFlags,?//?線程創建標志
??LPDWORD????????????????lpThreadId?//?線程標識符
);

//?詳細信息可參閱msdn

代碼實現


/*dwProcessId:?目標進程的pid
**pszDllFileName:?要注入DLL的路徑
*/
BOOL?CreateRemoteThreadInjectDll(DWORD?dwProcessId,?char?*pszDllFileName){
?HANDLE?hProcess?=?NULL;
?SIZE_T?dwSize?=?0;
?LPVOID?pDllAddr?=?NULL;
?FARPROC?pFuncProcAddr?=?NULL;

?//?打開注入進程,獲取進程句柄
?hProcess?=?::OpenProcess(PROCESS_ALL_ACCESS,?FALSE,?dwProcessId);
?if?(NULL?==?hProcess)
?{
??EP_ShowError("OpenProcess");
??return?FALSE;
?}
?//?在注入進程中申請內存
?dwSize?=?1?+?::lstrlenA(pszDllFileName);
?pDllAddr?=?::VirtualAllocEx(hProcess,?NULL,?dwSize,?MEM_COMMIT,?PAGE_READWRITE);
?if?(NULL?==?pDllAddr)
?{
??EP_ShowError("VirtualAllocEx");
??return?FALSE;
?}
?//?向申請的內存中寫入數據
?if?(FALSE?==?::WriteProcessMemory(hProcess,?pDllAddr,?pszDllFileName,?dwSize,?NULL))
?{
??EP_ShowError("WriteProcessMemory");
??return?FALSE;
?}
?//?獲取LoadLibraryA函數地址
?pFuncProcAddr?=?::GetProcAddress(::GetModuleHandleA("kernel32.dll"),?"LoadLibraryA");
?if?(NULL?==?pFuncProcAddr)
?{
??EP_ShowError("GetProcAddress_LoadLibraryA");
??return?FALSE;
?}
?//?使用?CreateRemoteThread?創建遠線程,?實現?DLL?注入
?HANDLE?hRemoteThread?=?::CreateRemoteThread(hProcess,?NULL,?0,?(LPTHREAD_START_ROUTINE)pFuncProcAddr,?pDllAddr,?0,?NULL);
?if?(NULL?==?hRemoteThread)
?{
??EP_ShowError("CreateRemoteThread");
??return?FALSE;
?}
?//?關閉句柄
?::CloseHandle(hProcess);

?return?TRUE;
}

試驗結果

注入成功后效果圖在explorer.exe中RemoteThreadDll.dll被正確加載

遠線程注冊進階 突破SESSION 0隔離

在系統普通進程中可以使用遠線程注入DLL,但如果要注入系統服務則不行,因為有SESSION 0隔離。想要突破隔離需要使用ZwCreateThreadEx函數。這也是和遠線程注入的區別。

ZwCreateThreadEx 是未公開的函數,在ntdll.dll中,它的函數聲明如下:

#ifdef?_WIN64
?typedef?DWORD(WINAPI?*typedef_ZwCreateThreadEx)(
??PHANDLE?ThreadHandle,
??ACCESS_MASK?DesiredAccess,
??LPVOID?ObjectAttributes,
??HANDLE?ProcessHandle,
??LPTHREAD_START_ROUTINE?lpStartAddress,
??LPVOID?lpParameter,
??ULONG?CreateThreadFlags,
??SIZE_T?ZeroBits,
??SIZE_T?StackSize,
??SIZE_T?MaximumStackSize,
??LPVOID?pUnkown);
#else
?typedef?DWORD(WINAPI?*typedef_ZwCreateThreadEx)(
??PHANDLE?ThreadHandle,
??ACCESS_MASK?DesiredAccess,
??LPVOID?ObjectAttributes,
??HANDLE?ProcessHandle,
??LPTHREAD_START_ROUTINE?lpStartAddress,
??LPVOID?lpParameter,
??BOOL?CreateSuspended,
??DWORD?dwStackSize,
??DWORD?dw1,
??DWORD?dw2,
??LPVOID?pUnkown);
#endif

具體實現代碼:

//?使用?ZwCreateThreadEx?實現遠線程注入
BOOL?ZwCreateThreadExInjectDll(DWORD?dwProcessId,?char?*pszDllFileName){
?HANDLE?hProcess?=?NULL;
?SIZE_T?dwSize?=?0;
?LPVOID?pDllAddr?=?NULL;
?FARPROC?pFuncProcAddr?=?NULL;
?HANDLE?hRemoteThread?=?NULL;
?DWORD?dwStatus?=?0;

?//?打開注入進程,獲取進程句柄
?hProcess?=?::OpenProcess(PROCESS_ALL_ACCESS,?FALSE,?dwProcessId);
?if?(NULL?==?hProcess)
?{
??EP_ShowError("OpenProcess");
??return?FALSE;
?}
?//?在注入進程中申請內存
?dwSize?=?1?+?::lstrlenA(pszDllFileName);
?pDllAddr?=?::VirtualAllocEx(hProcess,?NULL,?dwSize,?MEM_COMMIT,?PAGE_READWRITE);
?if?(NULL?==?pDllAddr)
?{
??EP_ShowError("VirtualAllocEx");
??return?FALSE;
?}
?//?向申請的內存中寫入數據
?if?(FALSE?==?::WriteProcessMemory(hProcess,?pDllAddr,?pszDllFileName,?dwSize,?NULL))
?{
??EP_ShowError("WriteProcessMemory");
??return?FALSE;
?}
?//?加載?ntdll.dll
?HMODULE?hNtdllDll?=?::LoadLibraryA("ntdll.dll");
?if?(NULL?==?hNtdllDll)
?{
??EP_ShowError("LoadLirbary");
??return?FALSE;
?}
?//?獲取LoadLibraryA函數地址
?pFuncProcAddr?=?::GetProcAddress(::GetModuleHandleA("Kernel32.dll"),?"LoadLibraryA");
?if?(NULL?==?pFuncProcAddr)
?{
??EP_ShowError("GetProcAddress_LoadLibraryA");
??return?FALSE;
?}
?//?獲取ZwCreateThread函數地址
#ifdef?_WIN64
?typedef?DWORD(WINAPI?*typedef_ZwCreateThreadEx)(
??PHANDLE?ThreadHandle,
??ACCESS_MASK?DesiredAccess,
??LPVOID?ObjectAttributes,
??HANDLE?ProcessHandle,
??LPTHREAD_START_ROUTINE?lpStartAddress,
??LPVOID?lpParameter,
??ULONG?CreateThreadFlags,
??SIZE_T?ZeroBits,
??SIZE_T?StackSize,
??SIZE_T?MaximumStackSize,
??LPVOID?pUnkown);
#else
?typedef?DWORD(WINAPI?*typedef_ZwCreateThreadEx)(
??PHANDLE?ThreadHandle,
??ACCESS_MASK?DesiredAccess,
??LPVOID?ObjectAttributes,
??HANDLE?ProcessHandle,
??LPTHREAD_START_ROUTINE?lpStartAddress,
??LPVOID?lpParameter,
??BOOL?CreateSuspended,
??DWORD?dwStackSize,
??DWORD?dw1,
??DWORD?dw2,
??LPVOID?pUnkown);
#endif
?typedef_ZwCreateThreadEx?ZwCreateThreadEx?=?(typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll,?"ZwCreateThreadEx");
?if?(NULL?==?ZwCreateThreadEx)
?{
??EP_ShowError("GetProcAddress_ZwCreateThread");
??return?FALSE;
?}
?//?使用?ZwCreateThreadEx?創建遠線程,?實現?DLL?注入
?dwStatus?=?ZwCreateThreadEx(&hRemoteThread,?PROCESS_ALL_ACCESS,?NULL,?hProcess,?(LPTHREAD_START_ROUTINE)pFuncProcAddr,?pDllAddr,?0,?0,?0,?0,?NULL);
?if?(NULL?==?hRemoteThread)
?{
??EP_ShowError("ZwCreateThreadEx");
??return?FALSE;
?}
?//?關閉句柄
?::CloseHandle(hProcess);
?::FreeLibrary(hNtdllDll);

?return?TRUE;
}

試驗結果

同遠線程注入一致,只是在服務程序中不能彈窗。

APC注入

APC(Asynchronous Procedure Call)為異步過程調用,APC注入是指利用線程本身的APC隊列進行DLL注入。

函數介紹

//?將異步調用函數添加到指定線程的APC隊列中
DWORD?QueueUserAPC(
??PAPCFUNC??pfnAPC,?//?函數指針
??HANDLE????hThread,?//?線程句柄
??ULONG_PTR?dwData?//?函數參數
);

//?詳細信息可參閱msdn

實現原理

APC隊列中的函數需要等待線程掛起時才會被執行,所以要保證我們注入的程序能被執行需要將我們的函數插入到進程的所有線程中。具體代碼實現如下:

//?apc.h
#include?
#include?


//?根據進程名稱獲取PID
DWORD?GetProcessIdByProcessName(char?*pszProcessName);

//?根據PID獲取所有的相應線程ID
BOOL?GetAllThreadIdByProcessId(DWORD?dwProcessId,?DWORD?**ppThreadId,?DWORD?*dwThreadIdLength);

//?APC注入
BOOL?ApcInjectDll(char?*pszProcessName,?char?*pszDllName);


//apc.cpp
#include?"APC.h"


void?ShowError(char?*pszText){
?char?szErr[MAX_PATH]?=?{?0?};
?::wsprintf(szErr,?"%s?Error[%d]\n",?pszText);
?::MessageBox(NULL,?szErr,?"ERROR",?MB_OK?|?MB_ICONERROR);
}


//?根據進程名稱獲取PID
DWORD?GetProcessIdByProcessName(char?*pszProcessName){
?DWORD?dwProcessId?=?0;
?PROCESSENTRY32?pe32?=?{?0?};
?HANDLE?hSnapshot?=?NULL;
?BOOL?bRet?=?FALSE;
?::RtlZeroMemory(&pe32,?sizeof(pe32));
?pe32.dwSize?=?sizeof(pe32);

?//?獲取進程快照
?hSnapshot?=?::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,?0);
?if?(NULL?==?hSnapshot)
?{
??ShowError("CreateToolhelp32Snapshot");
??return?dwProcessId;
?}

?//?獲取第一條進程快照信息
?bRet?=?::Process32First(hSnapshot,?&pe32);
?while?(bRet)
?{
??//?獲取快照信息
??if?(0?==?::lstrcmpi(pe32.szExeFile,?pszProcessName))
??{
???dwProcessId?=?pe32.th32ProcessID;
???break;
??}

??//?遍歷下一個進程快照信息
??bRet?=?::Process32Next(hSnapshot,?&pe32);
?}

?return?dwProcessId;
}


//?根據PID獲取所有的相應線程ID
BOOL?GetAllThreadIdByProcessId(DWORD?dwProcessId,?DWORD?**ppThreadId,?DWORD?*pdwThreadIdLength){
?DWORD?*pThreadId?=?NULL;
?DWORD?dwThreadIdLength?=?0;
?DWORD?dwBufferLength?=?1000;
?THREADENTRY32?te32?=?{?0?};
?HANDLE?hSnapshot?=?NULL;
?BOOL?bRet?=?TRUE;

?do
?{
??//?申請內存
??pThreadId?=?new?DWORD[dwBufferLength];
??if?(NULL?==?pThreadId)
??{
???ShowError("new");
???bRet?=?FALSE;
???break;
??}
??::RtlZeroMemory(pThreadId,?(dwBufferLength?*?sizeof(DWORD)));

??//?獲取線程快照
??::RtlZeroMemory(&te32,?sizeof(te32));
??te32.dwSize?=?sizeof(te32);
??hSnapshot?=?::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,?0);
??if?(NULL?==?hSnapshot)
??{
???ShowError("CreateToolhelp32Snapshot");
???bRet?=?FALSE;
???break;
??}

??//?獲取第一條線程快照信息
??bRet?=?::Thread32First(hSnapshot,?&te32);
??while?(bRet)
??{
???//?獲取進程對應的線程ID
???if?(te32.th32OwnerProcessID?==?dwProcessId)
???{
????pThreadId[dwThreadIdLength]?=?te32.th32ThreadID;
????dwThreadIdLength++;
???}

???//?遍歷下一個線程快照信息
???bRet?=?::Thread32Next(hSnapshot,?&te32);
??}

??//?返回
??*ppThreadId?=?pThreadId;
??*pdwThreadIdLength?=?dwThreadIdLength;
??bRet?=?TRUE;

?}?while?(FALSE);

?if?(FALSE?==?bRet)
?{
??if?(pThreadId)
??{
???delete[]pThreadId;
???pThreadId?=?NULL;
??}
?}

?return?bRet;
}


//?APC注入
BOOL?ApcInjectDll(char?*pszProcessName,?char?*pszDllName){
?BOOL?bRet?=?FALSE;
?DWORD?dwProcessId?=?0;
?DWORD?*pThreadId?=?NULL;
?DWORD?dwThreadIdLength?=?0;
?HANDLE?hProcess?=?NULL,?hThread?=?NULL;
?PVOID?pBaseAddress?=?NULL;
?PVOID?pLoadLibraryAFunc?=?NULL;
?SIZE_T?dwRet?=?0,?dwDllPathLen?=?1?+?::lstrlen(pszDllName);
?DWORD?i?=?0;

?do
?{
??//?根據進程名稱獲取PID
??dwProcessId?=?GetProcessIdByProcessName(pszProcessName);
??if?(0?>=?dwProcessId)
??{
???bRet?=?FALSE;
???break;
??}

??//?根據PID獲取所有的相應線程ID
??bRet?=?GetAllThreadIdByProcessId(dwProcessId,?&pThreadId,?&dwThreadIdLength);
??if?(FALSE?==?bRet)
??{
???bRet?=?FALSE;
???break;
??}

??//?打開注入進程
??hProcess?=?::OpenProcess(PROCESS_ALL_ACCESS,?FALSE,?dwProcessId);
??if?(NULL?==?hProcess)
??{
???ShowError("OpenProcess");
???bRet?=?FALSE;
???break;
??}

??//?在注入進程空間申請內存
??pBaseAddress?=?::VirtualAllocEx(hProcess,?NULL,?dwDllPathLen,?MEM_COMMIT?|?MEM_RESERVE,?PAGE_EXECUTE_READWRITE);
??if?(NULL?==?pBaseAddress)
??{
???ShowError("VirtualAllocEx");
???bRet?=?FALSE;
???break;
??}
??//?向申請的空間中寫入DLL路徑數據?
??::WriteProcessMemory(hProcess,?pBaseAddress,?pszDllName,?dwDllPathLen,?&dwRet);
??if?(dwRet?!=?dwDllPathLen)
??{
???ShowError("WriteProcessMemory");
???bRet?=?FALSE;
???break;
??}

??//?獲取?LoadLibrary?地址
??pLoadLibraryAFunc?=?::GetProcAddress(::GetModuleHandle("kernel32.dll"),?"LoadLibraryA");
??if?(NULL?==?pLoadLibraryAFunc)
??{
???ShowError("GetProcessAddress");
???bRet?=?FALSE;
???break;
??}

??//?遍歷線程,?插入APC
??i?=?dwThreadIdLength;
??for?(;?i?>?0;?--i)
??{
???//?打開線程
???hThread?=?::OpenThread(THREAD_ALL_ACCESS,?FALSE,?pThreadId[i]);
???if?(hThread)
???{
????//?插入APC
????::QueueUserAPC((PAPCFUNC)pLoadLibraryAFunc,?hThread,?(ULONG_PTR)pBaseAddress);
????//?關閉線程句柄
????::CloseHandle(hThread);
????hThread?=?NULL;
???}
??}

??bRet?=?TRUE;

?}?while?(FALSE);

?//?釋放內存
?if?(hProcess)
?{
??::CloseHandle(hProcess);
??hProcess?=?NULL;
?}
?if?(pThreadId)
?{
??delete[]pThreadId;
??pThreadId?=?NULL;
?}

?return?bRet;
}

總結

Windows注入技術可以方便我們對目標進程作修改,但是也可能使目標進程崩潰,在使用的時候需要小心謹慎。

長按圖片自動識別~~~關注我哦~~~~- END -

總結

以上是生活随笔為你收集整理的redistemplate注入为null_Windows DLL 注入技术的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。