大神论坛

找回密码
快速注册
查看: 561 | 回复: 0

[原创] 以远线程注入与卸载为例,展示一种优雅的写法

主题

帖子

25

积分

初入江湖

UID
16
积分
25
精华
威望
50 点
违规
大神币
68 枚
注册时间
2021-02-19 10:10
发表于 2021-03-03 22:52
本帖最后由 ttgogo 于 2021-03-03 22:52 编辑

#include <windows.h>
#include <Tlhelp32.h>
#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")

/************************************************************************
函数名称:RemoteInjectDll
函数功能:向目标进程中注入一个指定 Dll
参 数:pDllPath dll的存放路径
返 回 值:成功返回PID/失败返回NULL
************************************************************************/
DWORD GetProcessIDFromName(const TCHAR *pProcName)
{
HANDLE hSnapshot = NULL;
BOOL bStatus = FALSE;
DWORD dwProcessId = 0;
PROCESSENTRY32 pi = { 0 };
pi.dwSize = sizeof(pi);

hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == NULL)
{
return NULL;
}

bStatus = ::Process32First(hSnapshot, &pi);
while (bStatus)
{
if (memcmp(pProcName, pi.szExeFile, ::_tcslen(pProcName)) == 0)
{
dwProcessId = pi.th32ProcessID;
break;
}
bStatus = ::Process32Next(hSnapshot, &pi);
}

if (hSnapshot != NULL)
{
::CloseHandle(hSnapshot);
}
return dwProcessId;
}

/************************************************************************
函数名称:RemoteInjectDll
函数功能:向目标进程中注入一个指定 Dll
参 数1:pProcName 进程名
参 数2:pDllPath dll的存放路径
返 回 值:注入成功返回TRUE/注入失败返回FALSE
************************************************************************/
BOOL RemoteInjectDll(const TCHAR* pProcName, const TCHAR* pDllPath)
{
HANDLE hProcess = NULL, hThread = NULL;
DWORD dwSize = 0, dwProcessId = 0;
BOOL bRet = FALSE;
TCHAR* pRemoteBuf = NULL;
LPTHREAD_START_ROUTINE lpThreadFun = NULL;



// 参数无效
if (pProcName == NULL || ::_tcslen(pProcName) == 0
|| pDllPath == NULL || ::_tcslen(pDllPath) == 0)
{
return FALSE;
}

// 指定 Dll 文件不存在
if (_taccess(pDllPath, 0) == -1)
{
return false;
}

do
{
//获取进程ID
dwProcessId = GetProcessIDFromName(pProcName);
if (dwProcessId == 0)
{
break;
}

// 获取目标进程句柄
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (hProcess == NULL)
{
break;
}

// 在目标进程中分配内存空间
dwSize = (DWORD)::_tcslen(pDllPath) + 1;
pRemoteBuf = (TCHAR*)::VirtualAllocEx(hProcess, NULL, dwSize * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);
if (pRemoteBuf == NULL)
{
break;
}

// 在目标进程的内存空间中写入所需参数(模块名)
if (FALSE == ::WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)pDllPath, dwSize * sizeof(TCHAR), NULL))
{
break;
}

// 获取 LoadLibrary 地址
#ifdef _UNICODE
lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
#else
lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryA");
#endif
if (lpThreadFun == NULL)
{
break;
}

// 创建远程线程调用 LoadLibrary
hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpThreadFun, pRemoteBuf, 0, NULL);
if (hThread == NULL)
{
break;
}
// 等待远程线程结束
::WaitForSingleObject(hThread, INFINITE);
bRet = TRUE;

} while (0);


if (hThread != NULL)
{
::CloseHandle(hThread);
}
if (pRemoteBuf != NULL)
{
::VirtualFreeEx(hProcess, pRemoteBuf, dwSize, MEM_DECOMMIT);
}
if (hProcess != NULL)
{
::CloseHandle(hProcess);
}
return bRet;
}


/************************************************************************
函数名称:UnRemoteInjectDll
函数功能:从目标进程中卸载一个指定 Dll
参 数1:pProcName 进程名
参 数2:pDllPath dll的存放路径
返 回 值:卸载成功返回TRUE/卸载失败返回FALSE
备 注:采用远程线程注入技术实现
************************************************************************/
BOOL UnRemoteInjectDll(const TCHAR* pProcName, const TCHAR* pDllPath)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE, hProcess = NULL, hThread = NULL;
TCHAR *pModuleName = PathFindFileName(pDllPath);
BOOL bRet = FALSE, bFound = FALSE;
DWORD dwProcessId = 0;
MODULEENTRY32 me32 = { 0 };;
me32.dwSize = sizeof(me32);

// 参数无效
if (pProcName == NULL || ::_tcslen(pProcName) == 0
|| pDllPath == NULL || ::_tcslen(pDllPath) == 0)
{
return FALSE;
}

do
{
//获取进程ID
dwProcessId = GetProcessIDFromName(pProcName);
if (dwProcessId == 0)
{
break;
}

// 获取模块快照
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (hModuleSnap == INVALID_HANDLE_VALUE)
{
break;
}

if (::Module32First(hModuleSnap, &me32) == FALSE)
{
break;
}

do
{
bFound = (::_tcsicmp(me32.szModule, pModuleName) == 0
|| ::_tcsicmp(me32.szExePath, pDllPath) == 0);
// 找到指定模块
if (bFound)
{
break;
}
} while (::Module32Next(hModuleSnap, &me32) == TRUE);

if (false == bFound)
{
break;
}

// 获取目标进程句柄
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (hProcess == NULL)
{
break;
}

// 获取 FreeLibrary 地址
LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(
::GetModuleHandle(_T("Kernel32")), "FreeLibrary");
if (lpThreadFun == NULL)
{
break;
}

// 创建远程线程调用 FreeLibrary
hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun,
me32.modBaseAddr, 0, NULL);
if (hThread == NULL)
{
break;
}
// 等待远程线程结束
::WaitForSingleObject(hThread, INFINITE);
bRet = TRUE;
} while (0);

if (hThread != NULL)
{
::CloseHandle(hThread);
}
if (hProcess != NULL)
{
::CloseHandle(hProcess);
}
if (hModuleSnap != INVALID_HANDLE_VALUE)
{
::CloseHandle(hModuleSnap);
}
return bRet;[hide]
}



int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szDllPath[MAX_PATH] = { 0 };
GetCurrentDirectory(MAX_PATH, szDllPath);
wcscat_s(szDllPath, TEXT("\\JmpOEP.dll"));

if (RemoteInjectDll(TEXT("EmEditor.exe"), szDllPath) == FALSE)
{
MessageBox(NULL, TEXT("RemoteInjectDll Error"), NULL, NULL);
return 0;
}

if (UnRemoteInjectDll(TEXT("EmEditor.exe"), szDllPath) == FALSE)
{
MessageBox(NULL, TEXT("UnRemoteInjectDll Error"), NULL, NULL);
return 0;
}
return 0;
}



返回顶部