]> git.somenet.org - pub/jan/ctf-seminar.git/blob - writeups/b3rn1/OTW_Advent19.md
Add writeup for Over the wire Advent Bonanza
[pub/jan/ctf-seminar.git] / writeups / b3rn1 / OTW_Advent19.md
1 # Retrospective
2 I find the concept of CTF challenges as an advent calendar quite nice. However, I think the challeges should get easier since we have less time to solve the later challenges and that was in my opinion not really the case. Unfortunately, I didn't have much success with the challenges I played so I got a little frustrated after some time.  
3
4 # Challenges
5 ## Northpole Airwaves [Unsolved]
6 ### Description
7 During our latest expedition to the north pole, one of our scientists tuned her radio to 88Mhz and captured a slice of 1MHz (samplerate = 1M/s) to a GNURadio file sink. Surprisingly, there was more than just silence. We need your help to figure out what's going on. 
8
9 ### Analysis
10 We were provided with a GNU radio file sink that functioned as the file source for a GNU radio flow chart. The first gnuradio flowchart that stiefel40k posted sounded like there was morse code in the otherwise random noise. Astra then got some audio tracks from the file with a FM Demod block in the gnuradio companion. I also played around a little with the blocks but couldn't reveal more than Astra already had. 
11
12 ### Approaches
13 First approach by stiefel40k was to try if it was really morse code, he couldn't find anything meaningful. I also tried it myself but the track is really long so I didn't know where to look for the part for the flag. The beginning of the morse code is 414F54577B5468 which does not really look like a flag (or an hint where to find it), so I stopped there. Moreover, the audio tracks found by Astra looked (or sounded) more promising. So I also looked for the right track that is played there. stiefel40k found "Jesu, Joy of Man's Desiring" from Johann Sebastian Bach, which sounds quite similar but I think it is slightly different, however, that might just be because it is a different version. The name of the song wouldn't really help us as it was not the flag nor "Johann Sebastian Bach" or things alike. I thought maybe we need to find a radio station that plays classic, is far in the north and sends on 88 MHz but all I could find was a radio station in Alaska that sends on 88.1 (https://en.wikipedia.org/wiki/KBRW_(AM)). I tried their name and their call signs as the flag, which obviously didn't work. 
14 stiefel40k had the idea that the flag was encoded in RDS (the data radio stations send out so the listener knows which radio station he is listening to and sometimes the song title). I therefore tried to decode the RDS with fm-rds which didn't work because there were blocks missing and I didn't know how to get them. Moreover, I tried gr-rds as well. After lots of installing dependencies the execution of the flowchart always finished with "ModuleNotFoundError: No module named 'rds'". Unfortunately, I did not find out how to get that module. stiefel40k managed to try it with gr-rds but couldn't get anything out of it. 
15
16 ### Solution
17 The intended solution was a flag that was put together out of 3 parts. One was indeed RDS, one was indeed morse code and the third one used rc car based encoding.
18
19 ### Conclusion
20 I learned about gnuradio and how to use it in simple ways (probably too simple to find the flag). I think it would not be necessary to split the flag in 3 parts because it was already hard to find one of them. I spent about 12 hours on the challenge. 
21
22 ## Musical Stegano [Solved]
23 ### Description
24 I found a CD with some relaxing music on it, but one track just sounds completely off. The name of the track is 'BASS SEVEN TRIGRAPHS IN G MAJOR'. Hint: all the information you need to solve this challenge is audible. In other words, it's possible to solve with your ears only, though not everyone would be able to do that. An .ogg file is provided along with the .mid, for reference only, but is otherwise not useful. The .mid file is what you should use for the challenge. 
25
26 ### Analysis
27 We are provided with a midi file and an ogg-file to listen to the music file. 
28 Later they also published the music sheet as a pdf file and some hints: 
29
30 * If you don’t know music, it’s enough to know these concepts:
31     * Major scale: https://en.wikipedia.org/wiki/G_major
32     * How rhythm works, such as https://en.wikipedia.org/wiki/Eighth_note
33 * You do NOT need to know additional music theory such as chords.
34 * Both the treble and bass clefs are important.
35 * The challenge is tagged as a “stegano” but it’s actually very different from an image stegano - the point of an image stegano is to hide information in a way that does not affect the appearance of the image; this music stegano would sound different if the flag’s contents were changed.
36 * The flag format is AOTW{} and that wrapper part is embedded in the music as well.
37 * Consider it irrelevant whether a note is in the treble clef or the bass clef. For example, a middle C could be written on a treble clef (below the lines) or on a bass clef (above the lines) and they would sound exactly the same. When I said “don’t worry about chords”, I meant not to analyze the harmonic interactions between notes that play at the same time, not to ignore the bass clef (and treble clef can also have chords anyway).
38 * The way to encode notes in base 7 is: G = 0, A = 1, B = 2, ..., F# = 6. (If you don’t know what that # means, it does not matter; I’m just being technically accurate).
39 * The flag is spelled out chronologically, character by character, by special notes in the music, for some definition of “special”, but this definition can be described in just a few words. Non-special notes are irrelevant.
40
41 ### Approach
42 My first approach was to find the A of the AOTW part. Since we knew from the hint that the flag is base 7 encoded and the ASCII code for A is 65. 65 in base 7 is 122 and that is encoded in notes ABB. So I tried to find chords where these these 3 notes are played at the same time. However, I could not find it and the hint that chords don't really matter speaks against that as well. I then searched for ABB directly 
43
44 I also experimented a little with the python midi module but gained nothing useful from it.
45
46 ### Solution
47 The challenge was solved by ToasteR who found out that you have to take every second sixteenth note (no matter if in treble or in bass). The flag is AOTW{Mus1Cal_fUN}.
48
49 ### Conclusion
50 I learned a lot about musical steganography and a little bit about the midi python module. I find the concept of hiding a message in an musical piece highly interesting. I play the Flugelhorn in our local brass band but never have I thought of encoding messages in the music. I have spent around 3h on the challenge.
51
52 ## Naughty list
53 ### Description
54 Santa has been abusing his power and is union busting us elves. Any elves caught participating in union related activities have been put on a naughty list, if you can get me off the list I will give you a flag.
55
56 ### Analysis
57 When entering the webpage we are provided with the following text:
58 ```
59 Naughty List
60  
61 You've been a naughty elf
62
63 If you are here you have been a bad, bad elf. This holiday season, Santa has implemented a NO UNION policy in order to stay competitive with the likes of Amazon and AliExpress. We cannot afford to lose our competitive advantage due to your collective bargaining.
64
65 Since you were caught attempting to participate in union related activities, you have been placed on a list for bad elves. Once on this list your Christmas related privileges have been revoked with immediate effect and you are now under a period of probation.
66
67 In order to get off of this list, you will have to accumulate enough credits to show you are willing to participate in Christmas with the proper amount of Christmas spirit. Credits can be purchased with your hard earned gingerbread tokens in order to speed up your probation otherwise you will get a reduced wage of 1 gingerbread token per Christmas season (held in escrow). Once you have 5000 tokens, you can resume normal activities.
68
69 Failure to meet these minimum demands will result in your entry to a re-education camp.
70 ```
71 We can now either navigate to the contact form, where we can submit a message or go to the login page, where we first have to register on the register page. After that we can now login with the credentials. 
72
73 Now a new tab appears where the username is shown and the credits (1/50000) and "next credit: expired". Below that there are 3 buttons to buy credits but all just have a JS as href where an alert pops up saying: "no privs".
74
75 Below that there is an area to transfer credits to other elfs and a code. If we use the code given there we send the credit to santa. The code gets renewed every time we reload the page. The code is 59 characters long. We don't know our own code.
76
77 If you click multiple times on "Account" or any other link apart from "Home" the value of the get parameter "page" always changes. The value has 54 characters and looks as if it is base64 encoded but can not be decoded. If you add anything to the parameter and hit enter a file not found error page is shown with the page parameter set to 404 and the from_page set to another base64 looking string but with length 139.
78
79 Unfortunately, I was completely stuck there and didn't know what to do further.
80
81 ### Solution
82 First important thing that the others found out is, that you can use the from_page to encode data. To get to an the code of user "a" one had to use the page parameter as follows: ?page=anything:a. Then they created multiple users and made use of a race condition that occurred, and sent the credits back and forth until one user had more than 5000 credits. The flag was then AOTW{S4n7A_c4nT_hAv3_3lF-cOnTroL_wi7H0uT_eLf-d1sCipl1N3}.
83
84 ### Conclusion
85 The main challenge of this challenge was to guess the right way of adding the username to the page parameter to get the right token, which is not that appealing because its just guessing (and you couldn't even be sure, that it was about the page parameter). I spent around 3h on the challenge.
86
87 ## Snowflake Idle [Solved]
88 ### Description
89 It's not just leprechauns that hide their gold at the end of the rainbow, elves hide their candy there too.
90
91 ### Analysis
92 First we are provided with an input field where we should enter our name and then click on the button "Start Adventure!". After that a cookie "id" is stored in the browser and we are on a board where we can see how many snowflakes we already have. Moreover one can collect snowflakes, melt snowflakes or buy a higher collection speed with snowflakes. Moreover if we have a vigintillion of snowflakes (10^63) we can buy the flag. One could also show the growth chart and erase the progress and start over new. When collecting a snowflake the board freezes for 1 second and we have to wait, that the snowflake is connected.
93
94 After opening the network analysis of the browser we can see that there are the following endpoints are used:
95
96 For each request the PHP session ID and the id cookies are sent in the header.
97
98 /control POST-request with parameter "action": "new" and "name": "test" is used to register the new user "test"
99
100 /client POST-request is used for more things. First of all with parameter "action": "collect" and "amount": 1 collects 1 snowflake for the current user, with parameter "action": "melt" 1 snowflake is melted and we can also retrieve the current state with the parameter "action": "state" that returns an object like
101 {"collect_speed":1,"elf_name":"test","snowflakes":0.0,"speed_upgrade_cost":11.0}
102
103 /history/client GET-request returns the history of the commands on the server 
104 like [[1577378430227,{"action":"state"}],[1577378599241,{"action":"state"}],[1577379556474,{"action":"state"}],[1577379567446,{"action":"state"}],[1577379604610,{"action":"state"}],[1577379616488,{"action":"collect","amount":1}],[1577379617921,{"action":"state"}],[1577380056401,{"action":"melt"}],[1577380057835,{"action":"state"}]] and it is used to draw the growth chart. 
105
106 ### Approaches
107 First thing I tried was to set the amount directly with the parameter "amount". Unfortunately, the amount is ignored and the snowflakes are only increased by that amount that is currently legal for the user. Later we found out that the amount is used when drawing the snowflake growth chart. However even if you set the amount to 10^63 we are not provided with the flag, when drawing the graph. Here we also realised that any action is stored into the history, but we couldn't make any use of that.
108
109 Another thing I tried, was to upgrade even if I'm not yet allowed to do so, but that didn't work as well, as that is also checked on the server. 
110
111 Because of the hint with the rainbow I thought that we maybe need to draw an rainbow on the chart and I tried it, but it is hard to draw a perfect rainbow and we would not now in which height to draw, so that would be way to ambigous. 
112
113 Therefore, we thought that the rainbow might suggest to look something up in a rainbow table. I tried the id and the PHP session id but without success. 
114
115 I also tried to manually collect the snowflakes, since the sleeping time is only done on the client (setTimeOut with 1000 milli seconds). However if you do that you get the error message "Throttled at one request per second. Please note that this challenge does NOT require brute forcing, and does NOT require sending an excessive number of requests."
116
117 ### Solution 
118 The others found out that there is another endpoint /history/control by fuzzing (since /history/asdf didn't give a 404 Not Found they searched for an endpoint beneath history). The data that is returned looks like this [[1577378430227,{"action":"load"}],[1577378430227,{"action":"save","data":"6iq2Zm9wyq5DwLUQWXJ1whS6E031KuEpMDmTrheB6FtLZHXCE68FXLN1"}],[1577378599241,{"action":"load"}],[1577378599241,{"action":"save","data":"6iq2Zm9wyq5DwLUQWXJ1whS6E031KuEpMDmTrheB6FtLZHXCE68FXLN1"}], and the saved values change only sligthly. Therefore they concluded that this is the snowflake amount part. They changed it at the same byte and posted to /control with parameter "save" and could then buy the flag AOTW{leaKinG_3ndp0int5}.
119
120 ### Conclusion 
121 I liked that challenge, because it was just one thing you had to find out not 3 like in day 3. However, I didn't like that you had to guess for the other endpoint (however, we could have thought about it, since we have got client, history/client and control, that there is also a hitory/control). I spent around 10 hours with the challenge.
122
123 ## Gr8 Escape [Unsolved]
124 ### Description
125 The description was an imgur link to an image that shows a dialogue between a sun and his mom, where he asks if the elves also make the video games and she answers "sure" and than we see an elve struggling with C++ while reading a book "C++ for Dummies". 
126
127 ### Analysis
128 When netcatting to the server we are provided with a colorful header "THE GR8 ESCAPE" and a prompt "game:" waiting for input. The server executable was also provided. I downloaded it and tried to decompile it. Therefore I tried to install Boomerang and Snowman, but that didn't work on my Ubuntu. Therefore I used the Snowman binary for Windows and decompiled it on Windows. The result was a C/C++ file with about 270 000 lines of code. In that file I searched for the string "game: " and found it once. From there I tried to understand along the code what can or should be done next but unfortunately I could not follow.
129 Code snippet:  
130 ```
131     if (v9) {
132         fun_4117a0("game: ", rsi, rdx, rcx, r8, r9);
133         rax10 = fun_44bf60(0, v9, 0xe00, rcx, r8);
134         v11 = *reinterpret_cast<int32_t*>(&rax10);
135 ```
136
137 ```
138 void** fun_4117a0(void** rdi, void** rsi, void** rdx, void** rcx, void** r8, void** r9, ...) {
139     void** rsp7;
140     signed char al8;
141     void** rax9;
142     void** rdi10;
143     void** eax11;
144     uint64_t rcx12;
145     void** rax13;
146     void** rsp14;
147     void** rax15;
148     uint64_t rcx16;
149     void** rax17;
150     void** rsp18;
151     void** rax19;
152     void** r8_20;
153     void** rbx21;
154     void** rdx22;
155     void** eax23;
156     void* rsp24;
157     void** rsi25;
158     void** rdx26;
159     int1_t zf27;
160     int1_t zf28;
161     int1_t zf29;
162     int1_t zf30;
163     uint64_t rcx31;
164     void** rax32;
165     void* rsp33;
166     void** rsi34;
167     int1_t zf35;
168     void** rsp36;
169     void** r12_37;
170     void** r13_38;
171     void** rdi39;
172     void* rsp40;
173     void** rax41;
174     void* rsp42;
175     void** rax43;
176     void** r14_44;
177     void** rbx45;
178     uint32_t eax46;
179     void* rsp47;
180     void** rcx48;
181     void* rsp49;
182     int64_t* rsp50;
183     void** rax51;
184     void*** rsp52;
185     void** rax53;
186     void** rcx54;
187     void** rax55;
188     void* rsp56;
189     void** rcx57;
190     void*** rsp58;
191     void** rax59;
192     void*** rsp60;
193     void** rbx61;
194     void** rsp62;
195     void** rax63;
196     void** rdx64;
197     void** rdi65;
198     void** rsp66;
199     void** eax67;
200     void** rsp68;
201     void** rsi69;
202     void** rdx70;
203     int1_t zf71;
204     int1_t zf72;
205     int1_t zf73;
206     int1_t zf74;
207     void** rcx75;
208     int64_t* rsp76;
209     void** rsp77;
210     void** rax78;
211     void** rsp79;
212     void** rsp80;
213     void** rbx81;
214     void** rsp82;
215     void** rax83;
216     void** rbp84;
217     void** rdi85;
218     void** rsp86;
219     void** eax87;
220     void** rsp88;
221     int1_t zf89;
222     void** rsi90;
223     void** rdx91;
224     int1_t zf92;
225     uint64_t rcx93;
226     int64_t* rsp94;
227     void** rsp95;
228     void** rsp96;
229     void** rsp97;
230     void** rsp98;
231     void** eax99;
232     void** rsp100;
233     uint32_t edx101;
234     void** rsp102;
235     void** rdx103;
236     void** r8_104;
237     int1_t zf105;
238     int1_t zf106;
239     void** tmp32_107;
240     int1_t zf108;
241     void** tmp32_109;
242     void** rdx110;
243     int1_t zf111;
244     int64_t* rsp112;
245     void** r12_113;
246     void** rsp114;
247     void** rsp115;
248     void** rsp116;
249     void** r12_117;
250     void** rsi118;
251     int1_t zf119;
252     int1_t zf120;
253     int32_t tmp32_121;
254     int1_t zf122;
255     int32_t tmp32_123;
256     void** rsp124;
257     void** rdi125;
258     void** rsp126;
259     void** rdi127;
260     void** rsp128;
261     int1_t zf129;
262     int1_t zf130;
263     int64_t* rsp131;
264     int1_t zf132;
265     int1_t zf133;
266     int1_t zf134;
267     int1_t zf135;
268     int64_t* rsp136;
269     int64_t* rsp137;
270     void** rdx138;
271     void** r8_139;
272     int1_t zf140;
273     int1_t zf141;
274     int1_t zf142;
275     int64_t* rsp143;
276     int64_t* rsp144;
277
278     rsp7 = reinterpret_cast<void**>(reinterpret_cast<int64_t>(__zero_stack_offset()) - 0xd8);
279     if (al8) {
280         __asm__("movaps [rsp+0x50], xmm0");
281         __asm__("movaps [rsp+0x60], xmm1");
282         __asm__("movaps [rsp+0x70], xmm2");
283         __asm__("movaps [rsp+0x80], xmm3");
284         __asm__("movaps [rsp+0x90], xmm4");
285         __asm__("movaps [rsp+0xa0], xmm5");
286         __asm__("movaps [rsp+0xb0], xmm6");
287         __asm__("movaps [rsp+0xc0], xmm7");
288     }
289 ```
290
291 litplus later found out, that when entering some lines of "AAAAA..."s that it prints out a big dashed rectangle that has something like a progress bar on the top left corner. However it does not do that always.
292
293 ### Conclusion
294 I found that challenge really hard and frustrating because I did not know where to start. I spent around 4h on it. 
295