diff --git a/build.sh b/build.sh index f8325fc714e4a96388df9023bd56e68cfffe4dfb..5a24787a4204c8cf8192c41269429c53193c8aee 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,6 @@ #!/bin/sh + CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o darwin_arm64 -v . CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o darwin_amd64 -v . CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o linux_amd64 -v . diff --git a/main.go b/cmd/chat/main.go similarity index 73% rename from main.go rename to cmd/chat/main.go index 8e2db3a37dc96a71a2ff6a0dc81fc70354153fdd..7fe6f1572b40fd7a6a6a4844bd2543670e36d2f8 100644 --- a/main.go +++ b/cmd/chat/main.go @@ -1,6 +1,8 @@ package main -import "pp/web" +import ( + "pp/pkg/web" +) const key = "#hashcode69" diff --git a/cmd/grind/main.go b/cmd/grind/main.go new file mode 100644 index 0000000000000000000000000000000000000000..a17f846732d7f7ae273d4d7bce15797c5f5e20e3 --- /dev/null +++ b/cmd/grind/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "encoding/json" + "log" + "os" + "pp/pkg/comms" + "pp/pkg/grind" + "time" +) + +// // fos.Args[0] fd23::2:f083:f378:4f03 i + +// { "type": "discovered", "ips": [ "fd23::3:99d:951c:339b" ], "id": 69 } +// mit szólsz ehhez? { "type": "discovered", "ips": [...], "id": 69696}, aztán {"type": "ack", "id": 6969} és {"type": "submitted", "text": "a!", "id": 420} + +var host = "" + +func main() { + time.Sleep(time.Second) + + log.Println("Kakifantom is running") + host, _ = os.Hostname() + e := comms.Send("Kakifantom joined on " + host) + if e != nil { + panic(e) + } + + for msg := range comms.Recv() { + var m grind.Message + e := json.Unmarshal([]byte(msg), &m) + if e != nil { + continue + } + + switch m.Type { + case "discovered": + var d grind.Discovered + e = json.Unmarshal([]byte(msg), &d) + if e != nil { + log.Println(e) + continue + } + go func() { + e = grind.Discover(d) + if e != nil { + log.Println(e) + } + }() + case "submitted": + var s grind.Submitted + e = json.Unmarshal([]byte(msg), &s) + if e != nil { + log.Println(e) + continue + } + go func() { + e = grind.Submit(s) + if e != nil { + log.Println(e) + } + }() + case "ack": + log.Println("ack") + + } + } +} diff --git a/cmd/scrape/main.go b/cmd/scrape/main.go new file mode 100644 index 0000000000000000000000000000000000000000..95a9f0613146fd6d2d79ff8b03617826b2da0081 --- /dev/null +++ b/cmd/scrape/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "fmt" + "github.com/samber/lo" + "log" + "net" + "os" + "pp/pkg/comms" + "pp/pkg/tutter" + "regexp" + "strings" +) + +var socket = "ws://127.0.0.1:8080/ws" + +func init() { + _socket := os.Getenv("SOCKET") + if _socket != "" { + socket = _socket + } +} + +type Discovered struct { + Type string `json:"type"` + Id int `json:"id"` + IPs []string `json:"ips"` +} + +const cookiecutter = `#important #addr +New IPs just dropped! Get them while they're hot!` + +func main() { + for m := range tutter.LongPoll() { + if m.Author.Name == "ollescram" { + m.Text = string(lo.Reverse([]byte(m.Text))) + } + if strings.HasPrefix(m.Text, cookiecutter) { + continue + } + + ips := ExtractIPv6Addresses(m.Text) + if len(ips) > 0 { + fmt.Println() + fmt.Println(m.Text) + fmt.Println(ips) + e := comms.SendJSON(Discovered{ + Type: "discovered", + Id: 1, + IPs: ips, + }) + if e != nil { + log.Println(e) + } + } + } +} + +// ExtractIPv6Addresses extracts all possible IPv6 addresses from a string. +func ExtractIPv6Addresses(s string) []string { + // IPv6 addresses are typically represented in eight groups of four hexadecimal digits each, separated by colons. + // This regex will capture possible IPv6 addresses. + ipv6Regex := regexp.MustCompile(`([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}`) + + // Find all matches in the input string. + matches := ipv6Regex.FindAllString(s, -1) + + // Initialize an empty slice to hold the valid IPv6 addresses. + validIPv6Addresses := make([]string, 0) + + // Iterate over the matches. + for _, match := range matches { + // Use net.ParseIP to validate the IP address. + // If it's a valid IPv6 address, it will be returned in IPv6 format. + // If it's not a valid IP address, or if it's an IPv4 address, nil will be returned. + if ip := net.ParseIP(match); ip != nil && strings.Contains(match, ":") { + validIPv6Addresses = append(validIPv6Addresses, match) + } + } + + // Return the slice of valid IPv6 addresses. + return validIPv6Addresses +} diff --git a/last b/last deleted file mode 100644 index 3b9e69dc7623fb7e61eed41b592c457366d28b2a..0000000000000000000000000000000000000000 --- a/last +++ /dev/null @@ -1 +0,0 @@ -122076 \ No newline at end of file diff --git a/out/kakifantom b/out/kakifantom index 8eab54443a0a7ee2a4e5a76f5799260e5c83341b..12c3e390c5305c65538a2ce744707611bdae7fde 100755 Binary files a/out/kakifantom and b/out/kakifantom differ diff --git a/comms/key.go b/pkg/comms/key.go similarity index 100% rename from comms/key.go rename to pkg/comms/key.go diff --git a/comms/recv.go b/pkg/comms/recv.go similarity index 97% rename from comms/recv.go rename to pkg/comms/recv.go index 5d83b273630aa5fe81b060fbeedf3349e44d734d..b85a25c7618f057429b288da9a0bc91bd2850493 100644 --- a/comms/recv.go +++ b/pkg/comms/recv.go @@ -3,7 +3,7 @@ package comms import ( "encoding/json" "github.com/funny/crypto/aes256cbc" - "pp/tutter" + "pp/pkg/tutter" "strings" ) diff --git a/comms/send.go b/pkg/comms/send.go similarity index 96% rename from comms/send.go rename to pkg/comms/send.go index 9f96795ca1b9706e4b056326fbef81c0d94e1fa4..61862a4aaa3274e22b430967e3b76514b2a54f3d 100644 --- a/comms/send.go +++ b/pkg/comms/send.go @@ -5,7 +5,7 @@ import ( "github.com/funny/crypto/aes256cbc" "github.com/samber/lo" "math/rand" - "pp/tutter" + "pp/pkg/tutter" ) func Send(msg string) error { diff --git a/pkg/comms/sendJson.go b/pkg/comms/sendJson.go new file mode 100644 index 0000000000000000000000000000000000000000..74378f9759c68e254cf16afcdd4bdfe4ee8b364a --- /dev/null +++ b/pkg/comms/sendJson.go @@ -0,0 +1,12 @@ +package comms + +import "encoding/json" + +func SendJSON(thing any) error { + str, e := json.Marshal(thing) + if e != nil { + return e + } + + return Send(string(str)) +} diff --git a/comms/types.go b/pkg/comms/types.go similarity index 100% rename from comms/types.go rename to pkg/comms/types.go diff --git a/pkg/grind/discovered.go b/pkg/grind/discovered.go new file mode 100644 index 0000000000000000000000000000000000000000..31b4987a83b55ded40f89071a8153bbd3e37ec08 --- /dev/null +++ b/pkg/grind/discovered.go @@ -0,0 +1,82 @@ +package grind + +import ( + "encoding/json" + "fmt" + "log" + "math/rand" + "net/http" + "strings" + "time" +) + +type Details struct { + Score int `json:"score"` + MaxBodySizeBytes int `json:"max_body_size_bytes"` + Properties struct { + MinTokenLength int `json:"min_token_length"` + MaxTokenLength int `json:"max_token_length"` + TokenCharacterGroups struct { + AsciiLowercase bool `json:"ascii_lowercase"` + AsciiUppercase bool `json:"ascii_uppercase"` + Digits bool `json:"digits"` + Punctuation bool `json:"punctuation"` + } `json:"token_character_groups"` + SolvableUntilUnix int `json:"solvable_until_unix"` + InactivitySeconds int `json:"inactivity_seconds"` + MaxAttempts int `json:"max_attempts"` + } `json:"properties"` +} + +func Discover(d Discovered) error { + for _, ip := range d.IPs { + go func(ip string) { + log.Println("Discover", ip) + + resp, e := http.Get(fmt.Sprintf("http://[%s]:8080/describe", ip)) + if e != nil { + log.Println("host is ded", ip) + log.Println(e) + return + } + + var det Details + dec := json.NewDecoder(resp.Body) + e = dec.Decode(&det) + if e != nil { + log.Println(e) + return + } + + if det.Score < 0 { + log.Println("Shitty host detected") + return + } + + str := "" + if det.Properties.TokenCharacterGroups.AsciiLowercase { + str = strings.Repeat("z", det.Properties.MaxTokenLength) + } else if det.Properties.TokenCharacterGroups.AsciiUppercase { + str = strings.Repeat("Z", det.Properties.MaxTokenLength) + } else if det.Properties.TokenCharacterGroups.Punctuation { + str = strings.Repeat(".", det.Properties.MaxTokenLength) + } else if det.Properties.TokenCharacterGroups.Digits { + str = strings.Repeat("9", det.Properties.MaxTokenLength) + } + + _, e = submit(ip, str) + if e != nil { + log.Println(e) + return + } + + if !nosleep { + t := time.Duration(rand.Intn(10)) * time.Second + fmt.Println("Sleeping for", t) + time.Sleep(t) + } + }(ip) + time.Sleep(time.Second / 2) + } + return nil +} diff --git a/pkg/grind/globals.go b/pkg/grind/globals.go new file mode 100644 index 0000000000000000000000000000000000000000..1b2e8cc3b73933af0b0fadb1f5cc6434db520953 --- /dev/null +++ b/pkg/grind/globals.go @@ -0,0 +1,17 @@ +package grind + +import "os" + +var nosleep = false + +func init() { + if os.Getenv("NOSLEEP") == "true" { + nosleep = true + } +} + +var host = "" + +func init() { + host, _ = os.Hostname() +} diff --git a/pkg/grind/sendMeme.go b/pkg/grind/sendMeme.go new file mode 100644 index 0000000000000000000000000000000000000000..fe62f5cefa29a2cd35f0480475458c2fb7adc2fe --- /dev/null +++ b/pkg/grind/sendMeme.go @@ -0,0 +1,75 @@ +package grind + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "pp/pkg/comms" + "strings" + "sync" +) + +var mut sync.Mutex +var cache = make(map[string]bool) + +func submit(ip, pass string) ([]string, error) { + mut.Lock() + isCache := cache[ip] + mut.Unlock() + if isCache { + log.Println("Cache hit, deny to", ip) + return nil, nil + } + + log.Println("Attempting", ip) + resp, e := http.Post(fmt.Sprintf("http://[%s]:8080/attempt", ip), "text/plain", strings.NewReader(pass+"\n")) + if e != nil { + log.Println("host is ded", ip) + return nil, e + } + + switch resp.StatusCode { + case 400: + log.Println("Code wasn't accepted") + case 401: + log.Println("Oops, you haven't registered") + case 409: + log.Println("Race condition, we'll get 'em next time") + case 500: + log.Println("They fucked up") + case 204: + log.Printf("First submission to %s\n", ip) + mut.Lock() + cache[ip] = true + mut.Unlock() + e = comms.SendJSON(Submitted{ + Id: 0, + IP: ip, + Type: "submitted", + Text: pass, + Hostname: host, + }) + return nil, e + case 200: + var ips []string + dec := json.NewDecoder(resp.Body) + e = dec.Decode(&ips) + if e != nil { + return nil, e + } + + log.Printf("Succesful solve of %s\n", ip) + defer resp.Body.Close() + + e = comms.SendJSON(Discovered{ + Type: "discovered", + Id: 0, + IPs: ips, + Hostname: host, + }) + + return ips, e + } + return nil, nil +} diff --git a/pkg/grind/submitted.go b/pkg/grind/submitted.go new file mode 100644 index 0000000000000000000000000000000000000000..5e93a281c76b90b211537f4283efb737639f6459 --- /dev/null +++ b/pkg/grind/submitted.go @@ -0,0 +1,22 @@ +package grind + +import ( + "fmt" + "log" + "math/rand" + "time" +) + +func Submit(s Submitted) error { + if !nosleep { + t := time.Duration(rand.Intn(10)) * time.Second + fmt.Println("Sleeping for", t) + time.Sleep(t) + } + + log.Println("Submit", s.IP) + + _, e := submit(s.IP, s.Text) + + return e +} diff --git a/pkg/grind/type.go b/pkg/grind/type.go new file mode 100644 index 0000000000000000000000000000000000000000..dc931063f5c15036643e818237799b4f41fe603d --- /dev/null +++ b/pkg/grind/type.go @@ -0,0 +1,21 @@ +package grind + +type Message struct { + Type string `json:"type"` + Id int `json:"id"` +} + +type Discovered struct { + Type string `json:"type"` + Id int `json:"id"` + IPs []string `json:"ips"` + Hostname string `json:"hostname"` +} + +type Submitted struct { + Type string `json:"type"` + Id int `json:"id"` + IP string `json:"IP"` + Text string `json:"text"` + Hostname string `json:"hostname"` +} diff --git a/tutter/tutter.go b/pkg/tutter/tutter.go similarity index 73% rename from tutter/tutter.go rename to pkg/tutter/tutter.go index 2f38d3f1bcea0db8948fb145744c9ceea28eab47..26f88ae9727a7bff602c875cdaaf4c6faab9e05d 100644 --- a/tutter/tutter.go +++ b/pkg/tutter/tutter.go @@ -8,8 +8,6 @@ import ( "log" "net/http" "os" - "strconv" - "strings" "time" ) @@ -29,35 +27,21 @@ const url = "https://tutter.pproj.dev/api/poll" var last = 0 -func readLast() { - by, e := os.ReadFile("last") - if e != nil { - panic(e) - } - - _last, e := strconv.Atoi(strings.TrimSpace(string(by))) - if e != nil { - panic(e) - } - last = _last -} - -func init() { - readLast() -} - func LongPoll() <-chan Message { ch := make(chan Message) go func() { for { - murl := fmt.Sprintf("%s?last=%d", url, last) + murl := "https://tutter.pproj.dev/api/post?limit=25&order=desc" + if last != 0 { + murl = fmt.Sprintf("%s?last=%d", url, last) + } + resp, e := http.Get(murl) if e != nil { log.Println(e) continue } - var messages []Message js := json.NewDecoder(resp.Body) @@ -70,16 +54,6 @@ func LongPoll() <-chan Message { lo.ForEach(messages, func(msg Message, _ int) { ch <- msg }) - - ids := lo.Map(messages, func(item Message, _ int) int { - return item.Id - }) - - last = lo.Max(ids) - e = os.WriteFile("last", []byte(strconv.Itoa(last)), os.ModePerm) - if e != nil { - log.Println(e) - } } }() diff --git a/web/chat.html b/pkg/web/chat.html similarity index 100% rename from web/chat.html rename to pkg/web/chat.html diff --git a/web/web.go b/pkg/web/web.go similarity index 93% rename from web/web.go rename to pkg/web/web.go index 0f5339db57d24a233d53d50c3091b37be774f7c7..c0e6ad0d5714f386842a1b4ada6eea31bb31e35b 100644 --- a/web/web.go +++ b/pkg/web/web.go @@ -6,7 +6,7 @@ import ( "html/template" "net/http" "os" - "pp/comms" + comms2 "pp/pkg/comms" "strings" "time" ) @@ -46,7 +46,7 @@ func Start() { if msg == "" { return } - e := comms.Send(msg) + e := comms2.Send(msg) if e != nil { c.Error(e) return @@ -78,7 +78,7 @@ func reverse(sl []string) []string { func listenForMsg() { go func() { - for c := range comms.Recv() { + for c := range comms2.Recv() { messages = append(messages, c) SendMsg(c) } diff --git a/web/ws.go b/pkg/web/ws.go similarity index 97% rename from web/ws.go rename to pkg/web/ws.go index 2b5338a93359c553df4fc5f7246330143c16fe45..d2362da132bf782bc3285a9da5148bfbd6ecda6a 100644 --- a/web/ws.go +++ b/pkg/web/ws.go @@ -6,7 +6,7 @@ import ( "github.com/gorilla/websocket" "log" "net/http" - "pp/comms" + "pp/pkg/comms" ) var sockets = map[*websocket.Conn]bool{}