Last active
December 23, 2015 18:29
-
-
Save tprynn/6676217 to your computer and use it in GitHub Desktop.
CSAW CTF 2013 - Misc 300 Life Solution in Golang -- WildcatSec
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
// 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