Skip to content

Instantly share code, notes, and snippets.

@tprynn
Last active December 23, 2015 18:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tprynn/6676217 to your computer and use it in GitHub Desktop.
Save tprynn/6676217 to your computer and use it in GitHub Desktop.
CSAW CTF 2013 - Misc 300 Life Solution in Golang -- WildcatSec
// life.go
// This file solves CSAW CTF 2013 - Misc 300
// Challenge was to take an ASCII Game-of-Life, advance by n generations, and return the new game, then repeat
package main
import (
"fmt"
"net"
"regexp"
"strconv"
"strings"
)
func main() {
// Connect to the server
conn, err1 := net.Dial("tcp", "128.238.66.216:45678")
if err1 != nil {
fmt.Println(err1)
return
}
var read []byte
var err error
var matched bool
var connStatus error
// while connected
for connStatus == nil {
// scan for Generations header
matched = false
for !matched {
read = make([]byte, 4096)
_, connStatus = conn.Read(read)
matched, _ = regexp.Match(".*Generations.*", read)
if matched == false {
fmt.Print("Didn't match:\n", string(read))
return // Ugly code is the result of hacky solutions
}
}
re1 := regexp.MustCompile("[0-9]+ Gen") // Noncapturing groups don't work :(
re2 := regexp.MustCompile("[0-9]+")
generationsAsString := re2.FindString(re1.FindString(string(read)))
fmt.Println(generationsAsString)
generations, err := strconv.ParseInt(generationsAsString, 0, 32)
if err != nil {
fmt.Print(err)
return
}
fmt.Println("Generations: ", generations)
// Read the game board
read = make([]byte, 4096)
_, connStatus = conn.Read(read)
gameRows := strings.Split(string(read), "\n")
// Split the board into a 2D matrix
game := make([][]rune, len(gameRows)-1)
for i, row := range gameRows {
if i == len(gameRows)-1 {
break
}
game[i] = []rune(row)
fmt.Println(row)
}
for i := int64(0); i < generations; i++ {
game = step(game)
}
_, connStatus = conn.Write([]byte(toString(game)))
}
for err == nil {
read = make([]byte, 4096)
_, err = conn.Read(read)
fmt.Println(string(read))
}
}
func toString(game [][]rune) string {
var res string
for i := range game {
res += string(game[i]) + "\n"
}
return res
}
func step(game [][]rune) [][]rune {
newgame := make([][]rune, len(game))
for i, row := range game {
newgame[i] = make([]rune, len(row))
for j, cell := range row {
if cell == '#' {
newgame[i][j] = '#'
} else {
neighbors := 0
for x := i - 1; x <= i+1; x++ {
for y := j - 1; y <= j+1; y++ {
if x == i && y == j {
continue
}
if game[x][y] == '*' {
neighbors++
}
}
}
if cell == '*' && (neighbors == 2 || neighbors == 3) {
newgame[i][j] = '*'
} else if neighbors == 3 {
newgame[i][j] = '*'
} else {
newgame[i][j] = ' '
}
}
}
}
return newgame
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment