DLL 动态注入—ImgWalk动态库,这个DLL用来检测被注入的进程中当前载入的各个模块名称—exe程序
DLL 动态注入—ImgWalk动态库,这个DLL用来检测被注入的进程中当前载入的各个模块名称—exe程序
/*------------------------------------------------------------------------
22-InjLib.cpp
ImgWalk动态库,这个DLL用来检测被注入的进程中当前载入的各个模块名称---exe程序
-----------------------------------------------------------------------*/
#include "CmnHdr.h"
#include "Resource.h"
#include <malloc.h>
#include <strsafe.h>
#include <TlHelp32.h>
#include <windowsx.h>
#include <tchar.h>
/
#ifdef UNICODE
#define InjectLib InjectLibW
#define EjectLib EjectLibW
#else
#define InjectLib InjectLibA
#define EjectLib EjectLibA
#endif
/
BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile);//创建远程线程并注入DLL
BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile);
BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile);//将DLL从进程地址空间中撤销
BOOL WINAPI EjectLibA(DWORD dwProcessId, PCSTR pszLibFile);
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotity);
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//
int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE,PTSTR pszCmdLine,int)
{
DialogBox(hInstance,MAKEINTRESOURCE(IDD_INJLIB),NULL,Dlg_Proc);
return 0;
}
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
chHANDLE_DLGMSG(hWnd,WM_INITDIALOG,Dlg_OnInitDialog);
chHANDLE_DLGMSG(hWnd,WM_COMMAND,Dlg_OnCommand);
}
return FALSE;
}
/
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
chSETDLGICONS(hwnd,IDI_INJLIB);
return TRUE;
}
/
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotity)
{
switch (id)
{
case IDCANCEL:
EndDialog(hwnd, id);
break;
case IDC_INJECT:
DWORD dwProcessId = GetDlgItemInt(hwnd, IDC_PROCESSID, NULL, FALSE);
if (dwProcessId == 0)
{
//如果为0,表示注入本进程
dwProcessId = GetCurrentProcessId();
}
TCHAR szLibFile[MAX_PATH];
GetModuleFileName(NULL,szLibFile,_countof(szLibFile));//获得当前进程的完整路径
PTSTR pFileName = _tcsrchr(szLibFile, TEXT('\\')) + 1;
_tcscpy_s(pFileName,_countof(szLibFile) - (pFileName - szLibFile),TEXT("22-ImgWalk.DLL"));
if (InjectLib(dwProcessId, szLibFile))
{
chVERIFY(EjectLib(dwProcessId,szLibFile));
chMB("DLL注入/撤消成功!");
}
else
chMB("DLL注入/撤消失败!");
break;
}
}
/
//创建远程线程注入DLL
//参数:dwProcessID --进程ID
// pszLibFile ---要注入的DLL路径(含名称)
BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile)
{
BOOL bOk = FALSE;//假设注入失败
HANDLE hProcess = NULL,hThread = NULL;
PWSTR pszLibFileRemote = NULL;
__try {
//获得目标进程句柄
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | //需要检索有关进程的某些信息,例如其令牌、退出代码和优先级类
PROCESS_CREATE_THREAD | //For CreateRemoteThread
PROCESS_VM_OPERATION| //For VirtualAllocEx/VirtualFreeEx
PROCESS_VM_WRITE, //For WriteProcessMemory
FALSE,dwProcessId);
if (hProcess == NULL) __leave;
//计算存储DLL路径所需字节数
int cch = 1 + lstrlenW(pszLibFile);//字符个数,因strlen不含结尾\0,所以加1
int cb = cch * sizeof(wchar_t);
//为远程进程分配内存空间
pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
if (pszLibFileRemote == NULL) __leave;
//复制DLL路径到远程进程的内存中
if (!WriteProcessMemory(hProcess, pszLibFileRemote,
(PVOID)pszLibFile, cb, NULL)) __leave;
//获取LoadLibraryW在Kernel32.dll中的地址
//LPTHREAD_START_ROUTINE 函数指针,该函数通知宿主某个线程已开始执行。
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)//指向一个函数,该函数通知宿主某个线程已开始执行
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
if (pfnThreadRtn == NULL) __leave;
//创建远程线程调用LoadLibraryW
hThread = CreateRemoteThread(hProcess, NULL, 0,
pfnThreadRtn, //LoadLibraryW(远程进程地址空间中)
pszLibFileRemote, //Dll路径名(远程进程地址空间中)
0, NULL);//立即执行
if (hThread == NULL) __leave;
//等待远程线程结束
WaitForSingleObject(hThread,INFINITE);
bOk = TRUE; //注入成功
}
__finally {
//释放用于保存Dll路径名称的内存
if (pszLibFileRemote != NULL)
VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (hThread != NULL)
CloseHandle(hThread);
if (hProcess != NULL)
CloseHandle(hProcess);
}
return (bOk);
}
BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile)
{
//分配一个栈内存(无需手动释放),用于存储Unicode版本的路径名
SIZE_T cchSize = lstrlenA(pszLibFile) + 1;//字符个数,含'\0'
PWSTR pszLibFileW = (PWSTR)_alloca(cchSize * sizeof(wchar_t));
//将ANSI路径转换为等价的UNICODE
StringCchPrintfW(pszLibFileW, cchSize, L"%s", pszLibFile);
return InjectLibW(dwProcessId, pszLibFileW);
}
///
//将DLL从进程地址空间中撤销
//先根据DLL文件名,在进程加载的模块中查找是否该DLL己被加载
//如果被加载,记下这个DLL的句柄。然后创建远程线程去调用FreeLibrary卸载
BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile)
{
BOOL bOk = FALSE;//假定撤销失败
HANDLE hthSnapshot = NULL;
HANDLE hProcess = NULL, hThread = NULL;
__try
{
//抓取进程快照
hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,//指定进程中加载的所有模块
dwProcessId);
if (hthSnapshot == INVALID_HANDLE_VALUE) __leave;
//获得Unicode版本的目标DLL库句柄
MODULEENTRY32W me = {sizeof(me)};
BOOL bFound = FALSE;
BOOL bMoreMods = Module32FirstW(hthSnapshot, &me);//Unicode版本
for (;bMoreMods;bMoreMods = Module32NextW(hthSnapshot,&me))
{
bFound = (_wcsicmp(me.szModule,pszLibFile) == 0) ||
(_wcsicmp(me.szExePath,pszLibFile) == 0);
if(bFound)
break;
}
if (!bFound) __leave;
//获得目标进程的句柄
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION ,
FALSE, dwProcessId);
if (hProcess == NULL) __leave;
//获取FreeLibraray在Kernel32.dll中的地址
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
if(pfnThreadRtn == NULL) __leave;
//创建远程线程
hThread = CreateRemoteThread(hProcess,
NULL, 0,
pfnThreadRtn,
me.modBaseAddr,
0, NULL);
if (hThread == NULL) __leave;
//等待远程线程结束
WaitForSingleObject(hThread, INFINITE);
bOk = TRUE; //撤销成功
}
__finally
{
if (hthSnapshot != NULL)
CloseHandle(hthSnapshot);
if (hThread != NULL)
CloseHandle(hThread);
if (hProcess != NULL)
CloseHandle(hProcess);
}
return bOk;
}
BOOL WINAPI EjectLibA(DWORD dwProcessId, PCSTR pszLibFile)
{
//分配一个栈内存(无需手动释放),用于存储Unicode版本的路径名
SIZE_T cchSize = lstrlenA(pszLibFile) + 1;//字符个数,含'\0'
PWSTR pszLibFileW = (PWSTR)_alloca(cchSize * sizeof(wchar_t));
//将ANSI路径转换为等价的UNICODE
StringCchPrintfW(pszLibFileW, cchSize, L"%s", pszLibFile);
return EjectLibW(dwProcessId, pszLibFileW);
}