前言

这里说的DLL注入 是将我们指定的DLL注入到指定的进程中,DLL卸载也就是将指定进程中的DLL卸载下来。在Windows提供的API中有 CreateRemoteThread函数 见名知意 创建远程线程函数,这的远程指定的垮进程,让远程进程执行我们指定的线程回调函数。这就提供操作其他进程的契机。
CreateRemoteThread 函数原型

// 函数是不是和CreateThread非常像,实际上内部调用的该函数
HANDLE WINAPI CreateRemoteThread(// 指定创建线程的进程句柄_In_  HANDLE                 hProcess,_In_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,_In_  SIZE_T                 dwStackSize,// 线程回调函数地址_In_  LPTHREAD_START_ROUTINE lpStartAddress,// 线程回调函数的参数_In_  LPVOID                 lpParameter,_In_  DWORD                  dwCreationFlags,_Out_ LPDWORD                lpThreadId
);

实现思路

注入DLL

我们现在思考下面3个问题
第一个问题:如何加载DLL文件?DLL的调用方式,可以以参考 C/C++:Windows编程—调用DLL程序的2种方法。将一个DLL文件注入到目标进程 使用的是LoadLibrary函数。该函数的形式和ThreadProc形式一样,即可将LoadLibrary函数地址作为线程回调函数,这样目标进程会执行该函数将我们指定的DLL文件加载到目的进程中。

//加载一个DLL文件到进程的地址空间
HMODULE LoadLibraryA(LPCSTR lpLibFileName   //dll文件的路径
);

第二个问题:DLL的路径参数呢?需要将DLL文件的路径,同样写到目标进程中。这里需要借助WriteProcessMemory函数,

BOOL WINAPI WriteProcessMemory(// 进程句柄_In_  HANDLE  hProcess,// 指定写入目标进程内存的起始地址_In_  LPVOID  lpBaseAddress,// 写入的内容的缓冲区起始地址_In_  LPCVOID lpBuffer,// lpBuffer长度_In_  SIZE_T  nSize,// 接受实际写入内容的长度  _Out_ SIZE_T  *lpNumberOfBytesWritten
);

该函数非常强大,比如在破解方面,可以实现一个内存补丁,在开发方面,该函数可以用于修改目标进程中指定的值。

这样目标进程用LoadLibrary函数加载指定的DLL文件了。回到第二个问题 写入目标进程的起始地址应该是多少?目标进程中的内存块允许将DLL文件的路径写进去吗?这就引出了第3个问题

第三个问题:如何确定应该将DLL文件的完整路径写入目标进程的哪块地址呢?对于目标进程来说,不会事先准备一块地址让用户进行写入,用户做的是自己在目标进程中申请一块内存,然后把DLL文件的路径进程写入。在目标进程中申请内存的函数是VirtualAllocEx().

// suc,返回值是在目标进程申请到的内存起始地址
// err,NULL
LPVOID WINAPI VirtualAllocEx(// 指定进程句柄_In_     HANDLE hProcess,// 在目标进程中申请内存的起始地址_In_opt_ LPVOID lpAddress,// 申请内存的长度_In_     SIZE_T dwSize,// 申请内存的状态类型,如MEM_COMMIT _In_     DWORD  flAllocationType,// 申请内存的属性,如PAGE_READWRITE _In_     DWORD  flProtect
);
// 获取指定模块的模块句柄
HMODULE WINAPI GetModuleHandle(_In_opt_ LPCTSTR lpModuleName
);

那么注入DLL的思路,就是是上面3个问题的思路。

  1. 先在目标进程 申请 注入DLL的路径长度的 内存空间(也是LoadLibrary参数的),使用VirtualAllocEx
  2. 将DLL路径 写入的目标进程,使用WriteProcessMemory
  3. 获取LoadLibraryA函数的地址,通过GetProcAddress,LoadLibraryA函数在kernel32.dll中使用GetModuleHandle
  4. 创建线程并执行,使用CreateRemoteThread在目标进程中执行LoadLibrary。至就完成了将DLL注入到指定的进程中了。

卸载DLL

卸载DLL库的API函数
https://docs.microsoft.com/zh-cn/windows/desktop/api/libloaderapi/nf-libloaderapi-freelibrary

BOOL FreeLibrary(HMODULE hLibModule
);

思路还是和注入的一样,因为我们在目标进程使用LoadLibraryA将线程注入了,那么卸载DLL同样要在目标进程中执行!步骤同注入一样。由于FreeLibrary参数为HMODULE 实际上就是一个指针值。这个句柄已经加载就已经存在。所以并不需要项目标进程申请空间和写入数据。为什么LoadLibraryA需要在内存中申请参数空间呢因为字符串 有空间,事先并没有,必须自己开辟空间,然后将字符串指针值传入

实现效果

事先准备了一个DLLMsgBox.dll,在DLL加载和卸载的时候 会有个弹框效果。这里我们注入到KuGou.exe进程中。


我们用上次写的进程管理器 查看KuGou.exe进程中的DLL

滑到最下面

已经被注入到进程中了。
我们进行卸载DLL

卸载完毕,再次查看DLL列表

已经被成功卸载了。

核心代码

相关基础知识已经有了,下面我们来看核心代码

注入DLL

// 注入DLL
void WorkerThread::injectDLL()
{/*注入DLL的思路步骤:1. 在目标进程中申请一块内存空间(使用VirtualAllocEx函数) 存放DLL的路径,方便后续执行LoadLibraryA2. 将DLL路线写入到目标进程(使用WriteProcessMemory函数)3. 获取LoadLibraryA函数地址(使用GetProcAddress),将其做为线程的回调函数4. 在目标进程 创建线程并执行(使用CreateRemoteThread)*/HANDLE targetProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,m_pId);if( targetProc == NULL ){qDebug() << "OpenProcess error";return;}QString dllPath = m_dllPath;const char* pChar = dllPath.toStdString().c_str();int dllLen = dllPath.length();// 1.目标进程申请空间LPVOID pDLLPath = VirtualAllocEx(targetProc,NULL,dllLen,MEM_COMMIT,PAGE_READWRITE );if( pDLLPath == NULL ){qDebug() << "VirtualAllocEx error";return;}SIZE_T wLen = 0;// 2.将DLL路径写进目标进程内存空间int ret = WriteProcessMemory(targetProc,pDLLPath,pChar,dllLen,&wLen);if( ret == 0 ){qDebug() << "WriteProcessMemory error";return;}// 3.获取LoadLibraryA函数地址FARPROC myLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"),"LoadLibraryA");if( myLoadLibrary == NULL ){qDebug() << "GetProcAddress error";return;}// 4.在目标进程执行LoadLibrary 注入指定的线程HANDLE tHandle = CreateRemoteThread(targetProc,NULL,NULL,(LPTHREAD_START_ROUTINE)myLoadLibrary,pDLLPath,NULL,NULL);if(tHandle == NULL){qDebug() << "CreateRemoteThread error";return ;}qDebug() << "注入,wait ..." ;WaitForSingleObject(tHandle,INFINITY);CloseHandle(tHandle);CloseHandle(targetProc);qDebug() << "注入,finish ...";emit doInjectFinish();
}

卸载DLL

// 卸载DLL
void WorkerThread::uninstallDLL()
{/*卸载步骤和注入DLL步骤实质差不多.注入DLL是 在目标进程中执行LoadLibraryA卸载DLL是 在目标进程中执行FreeLibrary函数,不同的是卸载不需要再目标进程中申请空间,因为FreeLibrary参数为HMODULE 实际上就是一个指针值。这个句柄已经加载就已经存在。*/HANDLE targetProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,m_pId);if( targetProc == NULL ){qDebug() << "OpenProcess error";return;}QString dllPath = m_dllPath;// 1. 获取卸载dll的模块句柄HANDLE snapHandele = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE ,m_pId);if( INVALID_HANDLE_VALUE == snapHandele){qDebug() << "CreateToolhelp32Snapshot error" ;return;}MODULEENTRY32 entry = {0};entry.dwSize = sizeof(entry);// 长度必须赋值BOOL ret = Module32First(snapHandele,&entry);HMODULE dllHandle = NULL;while (ret) {QString dllName = QString::fromWCharArray(entry.szModule);if(dllPath.endsWith(dllName)){dllHandle = entry.hModule;qDebug() << dllName;break;}ret = Module32Next(snapHandele,&entry);}CloseHandle(snapHandele);if( dllHandle == NULL ){qDebug() << "dll 并未被加载";return;}// 2.获取FreeLibrary函数地址FARPROC myLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"),"FreeLibrary");if( myLoadLibrary == NULL ){qDebug() << "GetProcAddress error";return;}// 3.在目标进程执行FreeLibrary 卸载指定的线程HANDLE tHandle = CreateRemoteThread(targetProc,NULL,NULL,(LPTHREAD_START_ROUTINE)myLoadLibrary,dllHandle,NULL,NULL);if(tHandle == NULL){qDebug() << "CreateRemoteThread error";return ;}qDebug() << "卸载,wait ..." ;WaitForSingleObject(tHandle,INFINITY);CloseHandle(tHandle);CloseHandle(targetProc);qDebug() << "卸载,finish ...";emit doUninstallFinish();
}

完整工程

整个qt工程请在这里下载(含DLLMsgBox.dll)。

Qt:Windows编程—DLL注入与卸载相关推荐

  1. Qt:Windows编程—代码注入

    前言 ​ 这里所说的代码注入和上篇的DLL注入有类似之处.DLL文件的注入与卸载在上篇中都完成了,整个注入与卸载的过程其实就是让远程线程执行一次LoadLibrary函数或者FreeLibrary函数 ...

  2. C/C++:Windows编程—Hook IE浏览器实现URL拦截及更改(上)

    Hook IE浏览器实现URL拦截及更改(上) 前言+思路 笔者这里有个需求,针对IE浏览器 用户访问URL 做一个判断,是否为 限制访问的url,如果是 在另一个软件上给与警告提示.笔者在拿到这个需 ...

  3. 【Windows编程】Dll的注入与调用

    Dll注入与调用 Add.dll One.exe HookDll.dll Hook.exe 去年的时候想做个脚本,开始是用python,但是有些实现想用Hook,然而自己本来python就是半桶水,而 ...

  4. Windows核心编程_远线程方式实现Dll注入

    之前有介绍过HOOK的方式注入,这次介绍以其它方式注入,而无须HOOK,要知道在Windows这个浩荡的海洋里,API就是宝藏,找到足够多的宝藏那么你就是海贼王~! 实现思路如下: 首先打开一个进程的 ...

  5. 2020-11-23(Windows系统的dll注入 )

    一.什么是dll注入 在Windows操作系统中,运行的每一个进程都生活在自己的程序空间中(保护模式),每一个进程都认为自己拥有整个机器的控制权,每个进程都认为自己拥有计算机的整个内存空间,这些假象都 ...

  6. Qt:Windows编程—Qt实现进程管理

    前言 继续学window编程,学呀学呀 学无止境,学到Windows进程相关API了.利用相关的API使用Qt写界面实现了一个简单的进程管理.主要用到 进程的创建.进程的枚举.线程的枚举.DLL的枚举 ...

  7. Windows 钩子,基本的dll注入

    Windows操作系统是基于钩子完成的消息传递与用户交互,它以事件驱动的方式运行.每一个窗口都拥有自己的消息队列,当外部设备触发消息时,消息被发送到系统消息队列,再有操作系统安排将消息发送到特定进程上 ...

  8. Windows Dll注入与API HOOK

    DLL注入: 1.  使用注册表注入dll HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit ...

  9. Python并发编程——paramiko远程控制的模块、病毒攻击原理、dll注入、

    文章目录 paramiko模块 作业 攻击原理解析 一.什么是dll 二.为何要有dll 什么是dll注入: 什么时候需要dll注入 dll注入的方法 使用SetWindowsHookEx函数对应用程 ...

最新文章

  1. cmd指令卸载java_.net 服务 安装 卸载 命令行 bat cmd
  2. permission denied for window type 2003
  3. 系统中编译安装ZLMediaKit的步骤
  4. MyBatis--连接池模块
  5. 植树节快乐|用小学数学到高数的知识思考种树,你能种到哪一步?
  6. 【实施工程师】Linux查看日志后100行
  7. ssh汉字乱码怎么办_[转]SSH Secure Shell Client中文乱码的解决办法
  8. Git初学札记(八)————版本回退
  9. 批处理实现—循环Ping指定网段(检测网络时使用)
  10. thinkPHP5项目上传到centOS服务器后不显示验证码图片
  11. day01--课后练习
  12. zencart 对首页静态化处理
  13. Android http proxy server 设置
  14. java怎么销毁session_Java中session的销毁
  15. 华为eNSP三层架构网络配置
  16. 深度学习和浅层学习的区别
  17. Flink实战(八十五):flink-sql使用(十二)Flink 与 hive 结合使用(四)Hive Read Write
  18. 【好书推荐】物理、数学和发明的经典科普书籍
  19. php将一维数组转换成二维数组
  20. 新知实验室 腾讯云实时音视频产品体验

热门文章

  1. matlab repmat函数_Matlab向量化编程在二级劝退学科中的一个应用例子
  2. HbuilderX、Hbuilder编辑器如何使用手机调试app
  3. Linux编译安装nginx1.4.7版本
  4. js写随机输出7位数代码教程
  5. Forbidden You don't have permission to access / on this server.解决方法
  6. Python笔记-CAPM(资本资产定价模型)例子
  7. Web前端笔记-element ui中table中某列添加a便签进行跳转
  8. Spring Boot中防表单重复提交以及拦截器登录检测
  9. windows中mysql添加环境变量_windows 下添加mysql到系统环境变量
  10. boot lvm 分区_LVM磁盘逻辑卷管理