Skip to content

Latest commit

 

History

History
58 lines (43 loc) · 3.22 KB

C7.md

File metadata and controls

58 lines (43 loc) · 3.22 KB

C7: gofuscated

Link: https://squarectf.com/2018/gofuscated.html

This problem involved understanding and reverse engineering a golang program to output a flag. As with most other challenges, this involved providing an argument to the program which would cause it to execute and complete successfully.

Solution

First off, running the program immediately exits if your input doesn't match the regex defined in panicIfInvalid(). This means, that any valid input to the file will have to be exactly 26 characters long. Given thats the length of the alphabet, we have a good starting point:

go run gofuscated.go abcdefghijklmnopqrstuvwxyz

Running the program with this shows a juggler, presumably waiting for some long computation to finish, and untimately ends with an "invalid input!" string. Without anything further to go on, I dove into the functions within the source code.

  • main() - mostly this just calls each of the other functions. This go program uses several different pipes to pass data between functions. This causes them to execute simultaneously which makes debugging difficult, but overall is not a huge issue.
  • compute1() - this function simply creates the juggling animation until the done flag is set. I ended up commenting out the fmt.Printf() call in this function to turn it off and then ignored the function entirely.
  • compute2() - This function takes the input string, uses it to create a very long series of swaps on a 100000 long array. This function is the main bottleneck for computation (and will take several minutes to execute to completion), but since there is no obvious hint here, I moved on.
  • compute3() - This function is largly useless. As far as I can tell, it just destroys one channel and sets up another
  • compute4() - Finally, a helpful function! This seeds rand with a fixed value, creates a new lookup (or permutation) array for each lowercase character, and then applies that to the input value. This will come in useful in later on.
  • another_helper() - This function performs a final check that the input array is increasing order and if not valid the program exits.

Using all of this analysis, it seems clear that the only important functions for determining the correct input are compute4() and another_helper(). To have these functions run first, I re-ordered a couple lines in the source code and re-ran the program:

	input = compute4(input)
	flag := <-h
	if !another_helper(input) {
		panic("invalid input!")
	}
	panicIfInvalid(input)

into this:

	input = compute4(input)
	if !another_helper(input) {
		panic("invalid input!")
	}
	flag := <-h
	panicIfInvalid(input)

Finally, using the lookup table created by the compute4() function, I inverted the lookup so that the output would be the strictly increasing string abcdefghijklmnopqrstuvwxyz. With the inverted string computed, all that needs to be done is to run the program, wait a couple minutes for compute2() to complete, and grab the flag.

$ go run gofuscated.go nxelvzqaifsyhojudrbcwgptmk
                 
                oo
               O) 
             o/|  
               |
              / \
Congrats! 🚩  = flag-705787f208e6eff63768ae166482125b