Commit 20e9abe

bryfry <bryon@fryer.io>
2025-04-06 14:36:25
2025-04-06
1 parent 318a5e5
Changed files (2)
2025-04-05_pctf
2025-04-05_pctf/sundown_vault/create.go
@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"net/http"
+	"time"
 
 	"github.com/google/uuid"
 )
@@ -63,28 +64,39 @@ func loginUser(client *http.Client, username string) (*http.Cookie, error) {
 	return nil, fmt.Errorf("session cookie not found")
 }
 
-func createSecret(client *http.Client, cookie *http.Cookie, revealAt string) (string, error) {
+func createSecret(client *http.Client, cookie *http.Cookie, revealAt time.Time) (string, time.Time, error) {
+	now := time.Now()
+	revealFmt := revealAt.UTC().Format(time.RFC3339Nano)
+	type secret struct {
+		Id        string `json:"id,omitempty"`
+		Name      string `json:"name,omitempty"`
+		RevealAt  string `json:"revealAt,omitempty"`
+		CreatedAt string `json:"createdAt,omitempty"`
+	}
+	type my struct {
+		Secrets []secret
+	}
 
 	name := uuid.New().String()
 	payload, err := json.Marshal(map[string]string{
 		"name":     name,
 		"secret":   name,
-		"revealAt": revealAt,
+		"revealAt": revealFmt,
 	})
 	if err != nil {
-		return "", err
+		return "", now, err
 	}
 
 	req, err := http.NewRequest("POST", httpURL+"/api/secrets/create", bytes.NewBuffer(payload))
 	if err != nil {
-		return "", err
+		return "", now, err
 	}
 	req.Header.Set("Content-Type", "application/json")
 	req.AddCookie(cookie)
 
 	resp, err := client.Do(req)
 	if err != nil {
-		return "", err
+		return "", now, err
 	}
 	defer resp.Body.Close()
 
@@ -93,37 +105,38 @@ func createSecret(client *http.Client, cookie *http.Cookie, revealAt string) (st
 	}
 	err = json.NewDecoder(resp.Body).Decode(&result)
 	if err != nil {
-		return "", err
+		return "", now, err
 	}
-	return result.ID, nil
-}
 
-func postJSON(client *http.Client, path string, payload interface{}, cookie *http.Cookie, out interface{}) (*http.Response, error) {
-	data, _ := json.Marshal(payload)
-	req, err := http.NewRequest("POST", httpURL+path, bytes.NewBuffer(data))
+	req, err = http.NewRequest("GET", httpURL+"/api/secrets/my", nil)
 	if err != nil {
-		return nil, err
+		return "", now, err
 	}
 	req.Header.Set("Content-Type", "application/json")
-	if cookie != nil {
-		req.AddCookie(cookie)
-	}
+	req.AddCookie(cookie)
 
-	resp, err := client.Do(req)
+	resp, err = client.Do(req)
 	if err != nil {
-		return nil, err
+		return "", now, err
 	}
 	defer resp.Body.Close()
 
-	if out != nil {
-		if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
-			return resp, fmt.Errorf("failed to parse response: %w", err)
-		}
+	var mySecrets my
+	err = json.NewDecoder(resp.Body).Decode(&mySecrets)
+	if err != nil {
+		return "", now, err
 	}
 
-	if resp.StatusCode >= 400 {
-		return resp, fmt.Errorf("API error: %s", resp.Status)
+	for _, s := range mySecrets.Secrets {
+		if s.Id == result.ID {
+			r, err := time.Parse(time.RFC3339Nano, s.RevealAt)
+			if err != nil {
+				return "", now, err
+			}
+			return result.ID, r, nil
+		}
 	}
 
-	return resp, nil
+	return result.ID, now, nil
+
 }
2025-04-05_pctf/sundown_vault/main.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"log"
 	"net/http"
+	"sync"
 	"time"
 
 	"github.com/gorilla/websocket"
@@ -45,79 +46,102 @@ func main() {
 		log.Fatalf("failed login: %v", err)
 	}
 
-	secretDuration := 500 * time.Millisecond
-	for {
-		revealAt := time.Now().Add(secretDuration)
-		revealFmt := revealAt.UTC().Format(time.RFC3339)
+	var wg sync.WaitGroup
+	//secretDuration := 16050 * time.Microsecond
+	secretDuration := 2 * time.Second
+	revealAt := time.Now().Add(secretDuration)
+	myID, revealAt, err := createSecret(client, cookie, revealAt)
+	if err != nil {
+		log.Fatalf("failed to create secret: %v", err)
+	}
+	//fmt.Printf("[%s]\t💾 Created: %s\n", time.Since(revealAt), myID)
 
-		myID, err := createSecret(client, cookie, revealFmt)
-		if err != nil {
-			log.Fatalf("failed to create secret: %v", err)
-		}
-		fmt.Printf("[%s]\t💾 Created: %s\n", time.Since(revealAt), myID)
+	for paces := range time.Duration(25) {
+		wg.Add(1)
+		go draw(&wg, myID, revealAt, paces*time.Millisecond)
+	}
+	wg.Wait()
+}
 
-		conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
-		if err != nil {
-			log.Fatalf("failed ws connect: %v\n", err)
-		}
-		defer conn.Close()
+func draw(
+	wg *sync.WaitGroup,
+	id string,
+	revealAt time.Time,
+	paces time.Duration,
+) {
+	conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
+	if err != nil {
+		log.Fatalf("failed ws connect: %v\n", err)
+	}
 
-		//flag := Message{Command: "open", ID: flagID}
-		myFlag := Message{Command: "open", ID: myID}
+	time.Sleep(time.Until(revealAt) - (100 * time.Millisecond))
+	myFlag := Message{Command: "open", ID: id}
+	if err := conn.WriteJSON(myFlag); err != nil {
+		log.Fatalf("Failed to send message: %v\n", err)
+	}
 
-		if err := conn.WriteJSON(myFlag); err != nil {
-			log.Fatalf("Failed to send message: %v\n", err)
+	//var drawWG sync.WaitGroup
+	//drawWG.Add(1)
+	//go func() {
+	//	flag := Message{Command: "open", ID: flagID}
+	//	time.Sleep(time.Until(revealAt) - 10*time.Millisecond)
+	//	if err := conn.WriteJSON(flag); err != nil {
+	//		log.Fatalf("Failed to send message: %v\n", err)
+	//	}
+	//	drawWG.Done()
+	//}()
+	//fmt.Printf("[%s]\t🔫 DRAW!\n", time.Now())
+
+	first := true
+	updateCount := 0
+	update := false
+	for {
+		_, data, err := conn.ReadMessage()
+		if err != nil {
+			log.Printf("Read error: %v\n", err)
+			return
 		}
-		//go func() {
-		//	fmt.Printf("[%s]\t⏱️ loading: %s\n", time.Since(revealAt), offset.String())
-		//	time.Sleep(secretDuration + offset*2)
-		//	//if err := conn.WriteJSON(flag); err != nil {
-		//	//	log.Fatalf("Failed to send message: %v\n", err)
-		//	//}
-		//	fmt.Printf("[%s]\t🔫 DRAW:\n", time.Since(revealAt))
-		//}()
-
-		first := true
-		updateCount := 0
-		for {
-			_, data, err := conn.ReadMessage()
-			if err != nil {
-				log.Printf("Read error: %v\n", err)
-				return
-			}
-			var parsed Message
-			if err := json.Unmarshal(data, &parsed); err != nil {
-				log.Printf("Failed to parse: %v\n", err)
+		var parsed Message
+		if err := json.Unmarshal(data, &parsed); err != nil {
+			log.Printf("Failed to parse: %v\n", err)
+			continue
+		}
+		fmt.Printf("[%s]\t📩 Raw: %s\n", time.Now(), string(data))
+
+		if parsed.Kind == "Watch" {
+			if first {
+				first = false
 				continue
 			}
-			//fmt.Printf("[%s]\t📩 Raw: %s\n", time.Since(revealAt), string(data))
-
-			if parsed.Kind == "Watch" {
-				if first {
-					first = false
-					continue
-				}
-				fmt.Printf("[%s]\t☠️  DEAD:\n", time.Since(revealAt))
-				break
-			}
-			if parsed.Kind == "Update" {
-				fmt.Printf("[%s]\t📩 Raw: %s\n", time.Since(revealAt), string(data))
-				updateCount = updateCount + 1
+			fmt.Printf("[%s]\t☠️  DEAD! \n", time.Now())
+			break
+		}
+		if parsed.Kind == "Update" {
+			//fmt.Printf("[%s]\t📩 Raw: %s\n", time.Now(), string(data))
+			flag := Message{Command: "open", ID: flagID}
+			time.Sleep(paces)
+			if err := conn.WriteJSON(flag); err != nil {
+				log.Fatalf("Failed to send message: %v\n", err)
 			}
-			if parsed.Kind == "Reveal" {
-				if parsed.Name == "Flag" {
-					fmt.Printf("🎉 SECRET REVEALED: %s\n", parsed.Secret)
-					return
-				}
-				if updateCount > 1 {
-					secretDuration = secretDuration - time.Millisecond*5*time.Duration(updateCount)
-				}
-				if updateCount < 1 {
-					secretDuration = secretDuration + time.Millisecond*5
-				}
-				fmt.Printf("[%s]\t⏱️ calibrated: %s\n", time.Since(revealAt), secretDuration.String())
+			fmt.Printf("[%s]\t📩 SENT\n", time.Now())
+			updateCount = updateCount + 1
+			update = true
+		}
+		if parsed.Kind == "Reveal" {
+			if !update {
+				fmt.Print("DSF")
 				break
 			}
+			//fmt.Printf("[%s]\t📩 Raw: %s\n", time.Now(), string(data))
+			if parsed.Name == "Flag" {
+				fmt.Printf("🎉 SECRET REVEALED: %s\n", parsed.Secret)
+				return
+			}
+			//fmt.Printf("💨 MISS! d:%s\n", paces)
+			continue
 		}
 	}
+	//drawWG.Wait()
+	conn.Close()
+	wg.Done()
 }