Rating:
> I think this is my last story for this competition. (Didn't I only tell, like, three?) This one's a sing-along. Let's see how long we can keep it up!
> Author: micpap25
We're given the last ELF in the series: `story3`. When run it appears to just print the following over and over:
> I know a song that gets on everybody's nerves,
Everybody's nerves, yes, on everybody's nerves,
I know a song that gets on everybody's nerves,
And this is how it goes.
There's a bunch of other functions which are not directly called. I got a chuckle out of some, one will print the beginning of the Bee Movie script (a callback to [Flare-On 6 challenge 10](https://www.fireeye.com/content/dam/fireeye-www/blog/pdfs/flareon7-challenge10-solution.pdf)), another prints an excerpt from https://mrt4ntr4.github.io/BCACTF-LargeData-Writeup/ which I found hilarious.
> I usually try to stay polite towards organizers because I know that making a CTF is hard. But there are some issues that need to be fixed. Most importantly, every single challenge is trivially easy. I don’t think that’s inherently terrible, although it makes the CTF less enjoyable. I think having a CTF where the goal is maxing quickly is defendable. But that means you can’t release problems midway through the competition, especially if they are just as easy. Doing that completely nullifying every previous challenge. You also need to check that your challenges work. Both three-step-program and bca-store, the challenges released today, were initially broken. By the time you fix your mistake, many people have solved the challenge. So you now reduce the entire competition to seeing how fast people can refresh and submit their solution to a fixed challenge. I think the best course of action is to get rid of the newly released challenges and to release many more future challenges.
Note: I didn't do the CTF last year so I don't know what it was like, but I really enjoyed this one.
One of the functions wasn't just printing junk, so it stood out to me. It was labelled `FUN_2302136` (I think the author set the names for the troll functions). The meat of it was this:
```c++
timer = time(0LL);
time_obj = localtime(&timer;;
tm_min = time_obj->tm_min;
for ( i = 0; i <= 33; ++i )
flag[i] = (to_decrypt[i] >> tm_min) - tm_min * i + 21;
return puts(flag);
```
It takes many numbers as input, unjumbles their ordering, and then does a simple calculation based on the current time (minutes past the hour). One of the other functions gave the clue "the second minute" which turned out to not-be a troll.
```c++
return puts("74 68 65 20 73 65 63 6f 6e 64 20 6d 69 6e 75 74 65")
// can be decoded in python with: ''.join([chr(int(x, 16)) for x in "74 68 65 20 73 65 63 6f 6e 64 20 6d 69 6e 75 74 65".split(' ')])
```
This was my python script to perform the decoding.
```python
a = [467, 520, 390, 452, 459, 426, 179, 517, 257, 351, 265, 447, 389, 538, 231, 575, 365, 682, 210, 440, 330, 389, 337, 510, 554, 322, 309, 415, 401, 323, 574, 298, 511, 397]
m= {} # the `-1` thing turned out to be the easiest way to convert the IDA output
m[21] = a[1 - 1]
m[28] = a[2 - 1]
m[7] = a[3 - 1]
m[12] = a[4 - 1]
(...)
m[23] = a[32 - 1]
m[24] = a[33 - 1]
m[10] = a[34 - 1]
"""
for ( i = 0; i <= 33; ++i )
flag[i] = (m[i] >> tm_min) - tm_min * i + 21;
"""
minute = 2
res = [-1 for _ in range(len(m))]
for k,v in m.items():
res[k] = (v >> minute) - minute * k + 21
print(''.join(chr(c) for c in res))
```
Flag: `bcactf{h1dd3n_c0d3_1s_h1dd3n_2c8d}`