Created
March 15, 2020 05:37
-
-
Save moycat/de6a73dea8e34c94f3bb82b62e5b1f4f to your computer and use it in GitHub Desktop.
Spoof ICMP package from any source IP.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"golang.org/x/net/ipv4" | |
"log" | |
"net" | |
"os" | |
"strconv" | |
"strings" | |
"syscall" | |
) | |
var ( | |
sourceIP [4]byte | |
targetIP [4]byte | |
) | |
func init() { | |
if len(os.Args) < 3 { | |
log.Panicf("Usage: %s <Source IP> <Target IP>", os.Args[0]) | |
} | |
sourceIP = parseIP(os.Args[1]) | |
targetIP = parseIP(os.Args[2]) | |
} | |
func main() { | |
var err error | |
fd, _ := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW) | |
addr := syscall.SockaddrInet4{ | |
Port: 0, | |
Addr: sourceIP, | |
} | |
p := pack() | |
err = syscall.Sendto(fd, p, 0, &addr) | |
if err != nil { | |
log.Fatal("Sendto:", err) | |
} | |
} | |
func pack() []byte { | |
h := ipv4.Header{ | |
Version: 4, | |
Len: 20, | |
TotalLen: 20 + 10, // 20 bytes for IP, 10 for ICMP | |
TTL: 64, | |
Protocol: 1, // ICMP | |
Src: net.IPv4(sourceIP[0], sourceIP[1], sourceIP[2], sourceIP[3]), | |
Dst: net.IPv4(targetIP[0], targetIP[1], targetIP[2], targetIP[3]), | |
// ID and Checksum will be set for us by the kernel | |
} | |
icmp := []byte{ | |
8, // type: echo request | |
0, // code: not used by echo request | |
0, // checksum (16 bit), we fill in below | |
0, | |
0, // identifier (16 bit). zero allowed. | |
0, | |
0, // sequence number (16 bit). zero allowed. | |
0, | |
0xC0, // Optional data. ping puts time packet sent here | |
0xDE, | |
} | |
cs := calcChecksum(icmp) | |
icmp[2] = byte(cs) | |
icmp[3] = byte(cs >> 8) | |
out, err := h.Marshal() | |
if err != nil { | |
log.Fatal(err) | |
} | |
return append(out, icmp...) | |
} | |
func calcChecksum(b []byte) uint16 { | |
var s uint32 | |
for i := 0; i < len(b); i += 2 { | |
s += uint32(b[i+1])<<8 | uint32(b[i]) | |
} | |
// add back the carry | |
s = s>>16 + s&0xffff | |
s = s + s>>16 | |
return uint16(^s) | |
} | |
func parseIP(addr string) [4]byte { | |
parts := strings.Split(addr, ".") | |
b0, err := strconv.Atoi(parts[0]) | |
if err != nil { | |
log.Fatalf("parseIP: %s (program works with IPv4 addresses only, but not IPv6!)\n", err) | |
} | |
b1, _ := strconv.Atoi(parts[1]) | |
b2, _ := strconv.Atoi(parts[2]) | |
b3, _ := strconv.Atoi(parts[3]) | |
return [4]byte{byte(b0), byte(b1), byte(b2), byte(b3)} | |
} | |
// Some code is from https://github.com/grahamking/latency. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment