Running the program shows a progress bar and gives a core dump:
1 2 3 |
|
Let’s look at the output from strace (other lines are omitted):
1 2 3 4 5 6 7 8 |
|
Segmentation fault happens right after the second open(), so something might be wrong while reading the file. From the output above we can see that the program sends GET request to 134.79.129.105 to fetch a file, and the response (starting with ‘<!DOCTYPE HTML PUBLIC’) is probably written to /tmp/.tera. Let’s open /tmp/.tera:
1 2 3 4 5 6 7 8 9 |
|
As we can see, the response is indeed written to /tmp.tera, and we also know the domain of the ip address. But why is it 404 Not found? Using gdb to set a break point before the function curl_easy_setopt() to examine its arguments, from which we can know the full URL of the file:
1
|
|
Alright, let’s go to “http://darksky.slac.stanford.edu/simulations/ds14_a/”:
There is indeed a file called ds14_a_1.0000 (we got response 404 because there are two ending non-ascii characters. We can change \252 to \0 to make the program work), and its size is 31T. Downloading the whole file doesn’t seem to be realistic, so let’s open IDA to see what the program does after downloading. Reading towards the end of sub_400F19 routine, we can see the following code:
1 2 3 4 5 6 7 8 9 |
|
n is defined earlier in the same routine, and it is 34359739943392 (this also explains the seg fault earlier, since the file containing “404 Not found” is much smaller than this). It looks like the program wants to load the whole file into memory, and uses xor between some bytes (depends on array v35) of the file and bytes in array v18. Again, loading 31T into memory is not realistic, so we should use other ways to access the file without downloading it. After looking around at the website, I found that they have a bitbucket repo and a tutorial for accessing the data:
1 2 3 |
|
After installing python package thingking, we can access arbitrary bytes of the file without downloading it :) Then the only thing left is to reverse the two arrays (v35 and v18 above). Luckily, they are constructed directly from the values in memory location: 4199552 and 4200064. In gdb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
After having the values of those 2 arrays, we can do xor operations to get the flag. There is a piece of python code for this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
running the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
then we get the flag: ASIS{3149ad5d3629581b17279cc889222b93}
This is my first writeup. Any comments are welcome :)