Created
July 29, 2022 13:02
-
-
Save rlewkowicz/d11040ec66018b1eb612426486116d7e to your computer and use it in GitHub Desktop.
I'm in your global protect, hacking your routes
This file contains hidden or 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 | |
// The concept of this was borrowed from https://github.com/kayrus/tuncfg.git | |
// This is a crappy dumbed down rewrite so you can add some hacky routes. | |
// This is a useful reference for understanding the syscalls. You can add routes that don't | |
// show as static etc. It's useful for combating global protect. | |
// https://www.freebsd.org/cgi/man.cgi?query=rtentry | |
// https://www.freebsd.org/cgi/man.cgi?query=route | |
import ( | |
"flag" | |
"fmt" | |
"syscall" | |
"github.com/IBM/netaddr" | |
"golang.org/x/net/route" | |
"golang.org/x/sys/unix" | |
) | |
func main() { | |
var msg route.RouteMessage | |
var addrs []route.Addr | |
// This feels gross, but I don't know what parens are in golang. You're building this like syscall object, | |
// But idk what this construct is. In python, it's a tuple, but I don't think that exists here. | |
var flags = (syscall.RTF_UP | syscall.RTF_GATEWAY | syscall.RTF_PINNED | syscall.RTF_STATIC) | |
// onetwo is misnomer. Really this is just RTM messages (see reference). 1 is add, 2 is del, 3 is change. | |
// I think change has to have matching flags? | |
onetwo := flag.Int("onetwo", 1, "1/2") | |
ip := flag.String("ip", "", "1.2.3.4") | |
mask := flag.String("mask", "", "255.255.255.255") | |
// mac := flag.String("mac", "", "3c:22:fb:27:26:38") | |
// iface := flag.String("iface", "en0", "en0") | |
gateway := flag.String("gateway", "", "192.168.1.1") | |
linkIndex := flag.Int("index", 1000, "Link index is the index of the interface. I think its array indexed starting at 1 of ifconfig") | |
UC := flag.String("uc", "false", "its uc, of course you know what that is") | |
watch := flag.String("watch", "false", "watch for new routes. Useful for vms coming online") | |
host := flag.String("host", "false", "create a host route") | |
broadcast := flag.String("broadcast", "false", "create a broadcast route") | |
bridge := flag.String("bridge", "false", "create a bridge route") | |
flag.Parse() | |
a := [4]byte{} | |
m := [4]byte{} | |
g := [4]byte{} | |
// g := []byte{} | |
copy(a[:], netaddr.ParseIP(*ip)) | |
copy(m[:], netaddr.ParseIP(*mask)) | |
copy(g[:], netaddr.ParseIP(*gateway)) | |
// s := strings.Split(*gateway, ".") | |
// w, _ := strconv.Atoi(s[0]) | |
// x, _ := strconv.Atoi(s[1]) | |
// y, _ := strconv.Atoi(s[2]) | |
// z, _ := strconv.Atoi(s[3]) | |
// h, _ := net.ParseMAC("7c:10:c9:69:5e:30") | |
hop := &route.LinkAddr{ | |
Index: *linkIndex, | |
// Name: "", | |
// Addr: g, | |
} | |
// fmt.Printf("", *iface) | |
socket, _ := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | |
// If index is 1k no one set, lets use the ip | |
if *linkIndex == 1000 { | |
addrs = []route.Addr{ | |
&route.Inet4Addr{a}, | |
&route.Inet4Addr{g}, | |
&route.Inet4Addr{m}, | |
} | |
} else { // If it's not set, lets use the link number | |
addrs = []route.Addr{ | |
&route.Inet4Addr{a}, | |
hop, | |
&route.Inet4Addr{m}, | |
} | |
} | |
// 1 RTF_PROTO1 Protocol specific routing flag #1 | |
// 2 RTF_PROTO2 Protocol specific routing flag #2 | |
// 3 RTF_PROTO3 Protocol specific routing flag #3 | |
// B RTF_BLACKHOLE Just discard packets (during updates) | |
// b RTF_BROADCAST The route represents a broadcast address | |
// C RTF_CLONING Generate new routes on use | |
// c RTF_PRCLONING Protocol-specified generate new routes on use | |
// D RTF_DYNAMIC Created dynamically (by redirect) | |
// G RTF_GATEWAY Destination requires forwarding by intermediary | |
// H RTF_HOST Host entry (net otherwise) | |
// I RTF_IFSCOPE Route is associated with an interface scope | |
// i RTF_IFREF Route is holding a reference to the interface | |
// L RTF_LLINFO Valid protocol to link address translation | |
// M RTF_MODIFIED Modified dynamically (by redirect) | |
// m RTF_MULTICAST The route represents a multicast address | |
// R RTF_REJECT Host or net unreachable | |
// r RTF_ROUTER Host is a default router | |
// S RTF_STATIC Manually added | |
// U RTF_UP Route usable | |
// W RTF_WASCLONED Route was generated as a result of cloning | |
// X RTF_XRESOLVE External daemon translates proto to link address | |
// Y RTF_PROXY Proxying; cloned routes will not be scoped | |
// g RTF_GLOBAL Route to a destination of the global internet (policy hint) | |
if *host != "false" { | |
flags = (syscall.RTF_UP | syscall.RTF_GATEWAY | syscall.RTF_PINNED | syscall.RTF_HOST) | |
} | |
if *UC != "false" { | |
flags = (syscall.RTF_UP | syscall.RTF_CLONING) | |
} | |
if *broadcast != "false" { | |
flags = (syscall.RTF_UP | syscall.RTF_HOST | syscall.RTF_LLINFO | syscall.RTF_WASCLONED | syscall.RTF_BROADCAST | syscall.RTF_IFSCOPE) | |
} | |
if *bridge != "false" { | |
flags = (syscall.RTF_UP | syscall.RTF_HOST | syscall.RTF_LLINFO | syscall.RTF_WASCLONED | syscall.RTF_IFSCOPE) | |
} | |
msg = route.RouteMessage{ | |
Version: syscall.RTM_VERSION, | |
Type: *onetwo, | |
Index: 0, | |
ID: 0, | |
// So I tried host flags to get around GP first, the host flag is interesting on subnets. | |
// Seems to work, but it looks kinda weird in the routing table | |
// Flags: (syscall.RTF_UP | syscall.RTF_GATEWAY | syscall.RTF_PINNED | syscall.RTF_HOST), | |
Flags: flags, | |
Addrs: addrs, | |
} | |
bin, _ := msg.Marshal() | |
COUNT := 0 | |
if *watch != "false" { | |
for { | |
_, err := unix.Write(socket, bin[:]) | |
fmt.Println(err) | |
} | |
} else { | |
for { | |
_, err := unix.Write(socket, bin[:]) | |
COUNT = COUNT + 1 | |
fmt.Println(err) | |
if COUNT > 0 { | |
break | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment