详细解读:远程线程注入DLL到PC版微信

一、远程线程注入的原理

  1、其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以将DLL文件加载到自身进程中。

  2、这样,就可以用 CreateRemoteThread() 函数创建一个远程线程,让目标进程调用LoadLibrary() 来加载我们自己写的DLL 。CreateRemoteThread() 有这几个参数比较关键:A:想要注入的进程的句柄,这里可以通过OpenProcess()得到; B:想要运行的函数,本例中当然是 LoadLibrary() 啦; C: 所运行函数的参数,本例中是自己写的DLL的存放路径。

  3、那么,怎么让 LoadLibrary() 找到自己写的DLL的存放路径呢?这就需要在内存中开辟一块空间,把路径写入进去。这要先用 VirtualAllocEx()开辟一块空间,然后用WriteProcessMemory() 函数把DLL路径写进去。

  4、小结:总的来说,就是:先在目标进程的内存空间里开辟一块新地方,往新地方里面写入DLL的路径,再创建远程线程找到LoadLibrary() 函数,并在刚才开辟的新地方中读取DLL路径,进而加载我们自己写的DLL。

二、代码实现(含详细注释)

  1 #include <iostream>
2 #include "stdlib.h"
3 #include <tchar.h>
4 #include <Windows.h>
5
6 bool Inject(DWORD dwId, WCHAR* szPath)//参数1:目标进程PID 参数2:DLL路径
7 {
8 //一、在目标进程中申请一个空间
9
10
11 /*
12 【1.1 获取目标进程句柄】
13 参数1:想要拥有的进程权限(本例为所有能获得的权限)
14 参数2:表示所得到的进程句柄是否可以被继承
15 参数3:被打开进程的PID
16 返回值:指定进程的句柄
17 */
18 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
19
20
21 /*
22 【1.2 在目标进程的内存里开辟空间】
23 参数1:目标进程句柄
24 参数2:保留页面的内存地址,一般用NULL自动分配
25 参数3:欲分配的内存大小,字节单位
26 参数4:MEM_COMMIT:为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
27 参数5:PAGE_READWRITE 区域可被应用程序读写
28 返回值:执行成功就返回分配内存的首地址,不成功就是NULL
29 */
30 LPVOID pRemoteAddress = VirtualAllocEx(
31 hProcess,
32 NULL,
33 1,
34 MEM_COMMIT,
35 PAGE_READWRITE
36 );
37
38 //二、 把dll的路径写入到目标进程的内存空间中
39
40 DWORD dwWriteSize = 0;
41 /*
42 【写一段数据到刚才给指定进程所开辟的内存空间里】
43 参数1:OpenProcess返回的进程句柄
44 参数2:准备写入的内存首地址
45 参数3:指向要写的数据的指针(准备写入的东西)
46 参数4:要写入的字节数(东西的长度+0/)
47 参数5: 返回值。返回实际写入的字节
48 */
49 WriteProcessMemory(hProcess,pRemoteAddress, szPath, wcslen(szPath) * 2 + 2, &dwWriteSize);
50
51
52 //三、 创建一个远程线程,让目标进程调用LoadLibrary
53
54 /*
55 参数1:该远程线程所属进程的进程句柄
56 参数2:一个指向 SECURITY_ATTRIBUTES 结构的指针, 该结构指定了线程的安全属性
57 参数3:线程栈初始大小,以字节为单位,如果该值设为0,那么使用系统默认大小
58 参数4:在远程进程的地址空间中,该线程的线程函数的起始地址(也就是这个线程具体要干的活儿)
59 参数5:传给线程函数的参数(刚才在内存里开辟的空间里面写入的东西)
60 参数6:控制线程创建的标志。0(NULL)表示该线程在创建后立即运行
61 参数7:指向接收线程标识符的变量的指针。如果此参数为NULL,则不返回线程标识符
62 返回值:如果函数成功,则返回值是新线程的句柄。如果函数失败,则返回值为NULL
63 */
64 HANDLE hThread = CreateRemoteThread(
65 hProcess,
66 NULL,
67 0,
68 (LPTHREAD_START_ROUTINE)LoadLibrary,
69 pRemoteAddress,
70 NULL,
71 NULL
72 );
73 WaitForSingleObject(hThread, -1); //当句柄所指的线程有信号的时候,才会返回
74
75 /*
76 四、 【释放申请的虚拟内存空间】
77 参数1:目标进程的句柄。该句柄必须拥有 PROCESS_VM_OPERATION 权限
78 参数2:指向要释放的虚拟内存空间首地址的指针
79 参数3:虚拟内存空间的字节数
80 参数4:MEM_DECOMMIT仅标示内存空间不可用,内存页还将存在。
81 MEM_RELEASE这种方式很彻底,完全回收。
82 */
83 VirtualFreeEx(hProcess, pRemoteAddress, 1, MEM_DECOMMIT);
84 return 0;
85 }
86
87
88 int _tmain(int argc, _TCHAR * argv[])
89 {
90 wchar_t wStr[] = L"E:\\inject.dll";
91 DWORD dwId = 0;
92
93 //参数1:(NULL
94 //参数2:目标窗口的标题
95 //返回值:目标窗口的句柄
96 HWND hCalc = FindWindow(NULL, L"微信");
97 printf("目标窗口的句柄为:%d\n", hCalc);
98
99 DWORD dwPid = 0;
100
101 //参数1:目标进程的窗口句柄
102 //参数2:把目标进程的PID存放进去
103 DWORD dwRub = GetWindowThreadProcessId(hCalc, &dwPid);
104 printf("目标窗口的进程PID为:%d\n", dwPid);
105
106 //参数1:目标进程的PID
107 //参数2:想要注入DLL的路径
108 Inject(dwPid, wStr);
109
110 return 0;
111 }

执行之后,DLL就注入到了PC版的微信进程。且该DLL中含有一个弹窗代码,也出现在了PC版微信的界面之上。

附:测试用的DLL代码

 1 #include <windows.h>
2
3
4 DWORD WINAPI runBot(LPVOID lpParam) {
5 // 此处可以写具体的bot代码
6 return 1;
7 }
8
9
10 BOOL APIENTRY DllMain( HMODULE hModule,
11 DWORD ul_reason_for_call,
12 LPVOID lpReserved
13 )
14 {
15 switch (ul_reason_for_call)
16 {
17 case DLL_PROCESS_ATTACH:
18 MessageBoxA(NULL, "DLL Attached!\n", "Game Hacking", MB_OK | MB_TOPMOST);
19 CreateThread(NULL, 0, &runBot, NULL, 0, NULL);
20 break;
21 }
22 return TRUE;
23 }

(以上例程均在 Windows 10 系统,VisualStudio 2019 环境中编译通过)

kernel32.dll 这个系统模块的更多相关文章

  1. advapi32.dll kernel32.dll 中的两套注册表API

    日前遇到一件事:WebBrowser中的网页会用到一个“大众”ActiveX控件,为了保证兼容性以及和其它程序互不干扰,我们采用这样一种方案: 1. 我们的软件会自带该控件: 2. 如果系统中已注册有 ...

  2. kernel32.dll出错解决方案

    kernel32.dll 一.什么是kernel32内核文件 kernel32.dll是Windows 9x/Me中非常重要的32位动态链接库文件,属于内核级文件.它控制着系统的内存管理.数据的输入输 ...

  3. [DllImport("kernel32.dll")]是什么意思??

    转载自:http://blog.csdn.net/sp6645597/article/details/8683737 1.简单说明 这叫引入kernel32.dll这个动态连接库(顾名思义就是一个链接 ...

  4. 旧书重温:0day2【2】 实验:三种获取kernel32.dll基址的方法

    0x01 找kernel32基地址的方法一般有三种: 暴力搜索法.异常处理链表搜索法.PEB法. 0x02 基本原理 暴力搜索法是最早的动态查找kernel32基地址的方法.它的原理是几乎所有的win ...

  5. 无法定位程序输入点GetTickCount64 在动态链接库kernel32.dll上

    winxp系统,在使用boost中的thread中的sleep的时候出现“无法定位程序输入点GetTickCount64 在动态链接库kernel32.dll上”的错误, 1.在引用boost库之前( ...

  6. VS2010 + winxp 无法定位程序输入点GetTickCount64 在动态链接库kernel32.dll上 错误

    winxp系统,使用VS2010, 在使用boost中的thread中的sleep的时候出现 “无法定位程序输入点GetTickCount64 在动态链接库kernel32.dll上”的错误, 在网上 ...

  7. python系统模块

    Python中大多数系统接口都集中在两个模块:sys和os.这么说有点过于简单化 还有一些其他的表转模块也属于这个领域他们包括: glob 用于文件名的扩展 socket 用于网络连接和进程间通信(I ...

  8. 安装postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题

    安装postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题 解决办法: 1.安装系统更新补丁KB2533623,下 ...

  9. [DllImport("kernel32.dll")]

    这叫引入kernel32.dll这个动态连接库. 这个动态连接库里面包含了很多WindowsAPI函数,如果你想使用这面的函数,就需要这么引入.举个例子: [DllImport("kerne ...

随机推荐

  1. $ python manage.py makemigrations You are trying to add a non-nullable field 'name' to course without a default; we can't do that (the database needs something to populate existing rows). Please selec

    问题: $ python manage.py makemigrationsYou are trying to add a non-nullable field 'name' to course wit ...

  2. gzip/bzip/xz/tar

    说明 归档和压缩并不是一回事,压缩是按照压缩算法将文件进行压缩,一般是直接压缩文件,不同的压缩工具的压缩比率是不一样的,同时还支持在压缩工具中指定压缩比,gz < bz2 <xz 压缩增大 ...

  3. 【luoguP5550】Chino的数列

    题目背景 没有背景 我写不出来了qwq 题目描述 Chino给定了nn个数a_1...a_na1​...an​,给定常数s,m,她会轮流对这nn个数做k组操作,每组操作包含以下几步: 1.swap(a ...

  4. 【CUDA 基础】6.2 并发内核执行

    title: [CUDA 基础]6.2 并发内核执行 categories: - CUDA - Freshman tags: - 流 - 事件 - 深度优先 - 广度优先 - 硬件工作队列 - 默认流 ...

  5. 记一次 用 ssh 反向代理解决的远程操作效率问题

    公司在异地有一个项目,项目在内网有一个linux 集群开发人员通过 xshell 进行操作,但是开发过程中还需要公司开发人员进行远程操作,原来采用的方案是向日葵,需求能实现但是限于网络环境向日葵实在是 ...

  6. Hdu 5248

    hdu5248-序列变换 题意: 给你一个序列A,要求改变序列A中的某些元素的顺序,形成一个新的数列B,并保证数列B严格单调递增,求出最小代价. 代价计算公式 $ cost(a,b)=max(|A_i ...

  7. Linux 上的Tomcat配置输入域名直接访问项目

    申请的域名备案通过了,域名是在阿里云上面的买的,一块钱,当初买服务器是买着来玩玩的. 既然申请的域名已经备案通过了,也配置了域名解析 ,服务器上也装了Tomcat,部署了web项目,下面来配置下通过域 ...

  8. 【Eureka】 作为服务注册中心,Eureka比Zookeeper好在哪里

    著名的 CAP 理论指出,一个分布式系统不可能同时满足 C(一致性) A(可用性) 和 P(分区容错性).由于分区容错性 P 是在分布式系统中必须保证的,因此我们只能在 A 和 C 之间进行权衡. Z ...

  9. Flutter移动电商实战 --(7)dio基础_POST请求的使用

    这节学习一下POST请求的使用,其实POST和Get请求都是在工作中最重要的两种请求.比如我们要传递一组表单数据过去,这时候用Get请求就是不太合适的,使用POST比较好. SingleChildSc ...

  10. 记录学习Linux过程

    第一步fdisk-l 出错 Permission denied? ubuntu@VM-0-6-ubuntu:~$ fdisk -l fdisk: cannot open /dev/vda: Permi ...