学习c++ (五) dll注入和卸载

摘要:
tchar.h>tkp.Privileges[0].Attributes=SE_ PRIVILEGE_已启用;错误的NULL)){CloseHandle(hToken);

在学习第一篇时,就直接折腾代码,这是我学习的方法,基础的只是简单过一遍就好了,因为根本记得不够深刻,还是用了之后,才知道真正的含义。

然后在第一篇的基础上,把卸载加进来了,同时重整理了注入的代码,更重要的是这次的消息接收,抛弃了MFC,直接用的C++写的,感觉真好

另外,在这个注入和进程的通讯上,还遇到两个问题:

第一点,对于OpenProcess 时使用的权限最好还是PROCESS_ALL_ACCESS,反正我换了台电脑,就会造成CreateRemoteThread失败

第二点,在进程的通讯上,也存在权限问题,也就是说接收方如果不做处理 ,可能收不到,在WM_INITDIALOG中使用了ChangeWindowMessageFilter(WM_COPYDATA, 1)来处理一下

还是直接贴代码,也懒得上工程,有些变量啥的可能看不全,刚入门的同学们对不住了,你们还是慢慢看

#include "stdafx.h"
#include "Inject.h"


//#include <iostream>;
//using namespace std;
//#include <windows.h>;
//#include <tlhelp32.h>;
//#include <tchar.h>;




// 提升进程访问权限
bool enableDebugPriv()
{
    HANDLE hToken;
    LUID sedebugnameValue;
    TOKEN_PRIVILEGES tkp;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)
        )
    {
        return false;
    }
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
    {
        CloseHandle(hToken);
        return false;
    }
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = sedebugnameValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
    {
        CloseHandle(hToken);
        return false;
    }
    return true;
}
// 根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的ID
DWORD processNameToId(LPCTSTR lpszProcessName)
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hSnapshot, &pe))
    {
        MessageBox(NULL,
            L"The frist entry of the process list has not been copyied to the buffer",
            L"Notice",
            MB_ICONINFORMATION | MB_OK
        );
        return 0;
    }
    while (Process32Next(hSnapshot, &pe))
    {
        if (!wcscmp(lpszProcessName, pe.szExeFile))
        {
            return pe.th32ProcessID;
        }
    }
    return 0;
}




bool InjectDll()
{
    enableDebugPriv();
    DWORD dwProcessId = processNameToId(INJECT_PROCESS_NAME);
    if (dwProcessId == 0)
    {
        MessageBox(NULL,
            L"The target process have not been found !",
            L"Notice",
            MB_ICONINFORMATION | MB_OK
        );
        return FALSE;
    }

    return InjectDll(INJECT_DLL_NAME, dwProcessId);
}

bool InjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId)
{
    // 参数无效   
    if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))
    {
        return false;
    }
    // 指定 Dll 文件不存在   
    if (-1 == _taccess(ptszDllFile, 0))
    {
        return false;
    }
    HANDLE hProcess = NULL;
    HANDLE hThread = NULL;
    DWORD dwSize = 0;
    TCHAR* ptszRemoteBuf = NULL;
    LPTHREAD_START_ROUTINE lpThreadFun = NULL;
    // 获取目标进程句柄   
    hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (NULL == hProcess)
    {
        return false;
    }
    // 在目标进程中分配内存空间   
    dwSize = (DWORD)::_tcslen(ptszDllFile) + 1;
    ptszRemoteBuf = (TCHAR*)::VirtualAllocEx(hProcess, NULL, dwSize * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);
    if (NULL == ptszRemoteBuf)
    {
        ::CloseHandle(hProcess);
        return false;
    }
    // 在目标进程的内存空间中写入所需参数(模块名)   
    if (FALSE == ::WriteProcessMemory(hProcess, ptszRemoteBuf, (LPVOID)ptszDllFile, dwSize * sizeof(TCHAR), NULL))
    {
        ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);
        ::CloseHandle(hProcess);
        return false;
    }
    // 从 Kernel32.dll 中获取 LoadLibrary 函数地址   
#ifdef _UNICODE   
    lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
#else   
    lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryA");
#endif   
    //LPVOID pFunc = LoadLibraryA;
 
    if (NULL == lpThreadFun)
    {
        ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);
        ::CloseHandle(hProcess);
        return false;
    }
    // 创建远程线程调用 LoadLibrary   
    hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, ptszRemoteBuf, 0, NULL);
    if (NULL == hThread)
    {
        DWORD error = GetLastError();
        ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);
        ::CloseHandle(hProcess);
        return false;
    }
    // 等待远程线程结束   
    ::WaitForSingleObject(hThread, INFINITE);
    // 清理   
    ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);
    ::CloseHandle(hThread);
    ::CloseHandle(hProcess);
    return true;
}


bool UnInjectDll()
{
    enableDebugPriv();
    DWORD dwProcessId = processNameToId(INJECT_PROCESS_NAME);
    if (dwProcessId == 0)
    {
        MessageBox(NULL,
            L"The target process have not been found !",
            L"Notice",
            MB_ICONINFORMATION | MB_OK
        );
        return FALSE;
    }

    return UnInjectDll(INJECT_DLL_NAME, dwProcessId);
}

//-----------------------------------------------------------------------------------------------------------   
// 函数: UnInjectDll   
// 功能: 从目标进程中卸载一个指定 Dll 模块文件.   
// 参数: [in] const TCHAR* ptszDllFile - Dll 文件名及路径   
//       [in] DWORD dwProcessId - 目标进程 ID   
// 返回: bool - 卸载成功返回 true, 卸载失败则返回 false.   
// 说明: 采用远程线程注入技术实现   
//-----------------------------------------------------------------------------------------------------------   
bool UnInjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId)
{
    // 参数无效   
    if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))
    {
        return false;
    }
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    HANDLE hProcess = NULL;
    HANDLE hThread = NULL;
    // 获取模块快照   
    hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
    if (INVALID_HANDLE_VALUE == hModuleSnap)
    {
        return false;
    }
    MODULEENTRY32 me32;
    memset(&me32, 0, sizeof(MODULEENTRY32));
    me32.dwSize = sizeof(MODULEENTRY32);
    // 开始遍历   
    if (FALSE == ::Module32First(hModuleSnap, &me32))
    {
        ::CloseHandle(hModuleSnap);
        return false;
    }
    // 遍历查找指定模块   
    bool isFound = false;
    do
    {
        isFound = (0 == ::_tcsicmp(me32.szModule, ptszDllFile) || 0 == ::_tcsicmp(me32.szExePath, ptszDllFile));
        if (isFound) // 找到指定模块   
        {
            break;
        }
    } while (TRUE == ::Module32Next(hModuleSnap, &me32));
    ::CloseHandle(hModuleSnap);
    if (false == isFound)
    {
        return false;
    }
    // 获取目标进程句柄   
    hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (NULL == hProcess)
    {
        return false;
    }
    // 从 Kernel32.dll 中获取 FreeLibrary 函数地址   
    LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary");
    if (NULL == lpThreadFun)
    {
        ::CloseHandle(hProcess);
        return false;
    }
    // 创建远程线程调用 FreeLibrary   
    hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, me32.modBaseAddr /* 模块地址 */, 0, NULL);
    if (NULL == hThread)
    {
        ::CloseHandle(hProcess);
        return false;
    }
    // 等待远程线程结束   
    ::WaitForSingleObject(hThread, INFINITE);
    // 清理   
    ::CloseHandle(hThread);
    ::CloseHandle(hProcess);
    return true;
}

免责声明:文章转载自《学习c++ (五) dll注入和卸载》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C# winform 动态添加控件 以及 事件MySQL连接池下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

pcntl_fork()函数说明

pcntl_fork()函数复制了当前进程的PCB,并向父进程返回了派生子进程的pid,父子进程并行,打印语句的先后完全看系统的调度算法,打印的内容控制则靠pid变量来控制。因为我们知道pcntl_fork()向父进程返回了派生子进程的pid,是个正整数;而派生子进程的pid变量并没有被改变,这一区别使得我们看到了他们的不同输出。 1. 派生子进程的进程,...

.net core Identity学习(三) 第三方认证接入

简介 .net core在nuget中提供了微软、google、Facebook和twitter的Identity接入包,这里主要以MS作为例子。 微软官方文档可以参见这个链接,但是.net core的文档个人认为作为教学并不是特别好,利用了很多VS中的功能隐藏掉了很多细节,当当当点几下,就可以认证了,对于需要自定义一些流程的情况,可能会不方便,而且也不太...

帆软常用JS

1.鼠标移动图片放大 $("td[id^=A] img").mouseover(function(e){var col=Number($(this).attr("col"))+1; //获取鼠标当前所在单元格的col var row=$(this).attr("row"); //获取鼠标当前所在单元格的row var img=this.src; //获取到...

mssql 发布库 Invalid object name 'syspublications'

前段时间在删除分发的时候  Invalid object name 'syspublications' 导致整个server 都不能重做replication 解决如下 EXEC sp_removedbreplication dbname 发现还是不行  sp_replicationdboption 'Problem Database','Publish...

Row size too large. The maximum row size for the used table type 解决

原因:不要建太多字段,或者字段类型设置太长了,像这样设置了字段长度会导致最后超出表长度,新增不了新字段 ,或者建表本身就报错。 [IMP] Import start[IMP] Import type - CSV file[IMP] Import from - C:UsersWQBinDesktopxxx_user.csv[ERR] Cannot creat...

Linux 内存监控

centos6 init进程是系统中的第一个进程,PID永远为1 查看系统在中静态进程的统计信息 命令: ps 格式: ps [可选项] ax: 显示所有的进程信息 -u: 使用以用户为主的格式输出进程信息 -e: select all processes 显示系统内的进程信息 -l: 使用长格式显示进程信息 -f: full 使用完整的格式显示进程信息...