xenocidewiki's blog

Ramblings of a bored university student on the topics of reverse engineering, CTFs, and other technical wizardry

IceCTF 2020 | Hydrogen Bomb Writeup

Posted at — Jan 4, 2021

Intro

We are given a binary called bomb which is a billion functions taking input, where the goal is to find a sequence of inputs that gets us to a function called defuse which prints the flag.

We will embark on a journey that fried my brain and left me with two(!) out of the three braincells I already had remaining.

In order to get to defuse, we need to pass the following check:

Collectibles

In order to do that, we have to visit a few specific functions that perform an OR operation on the global variable (which is initially 0), after which collectibles becomes 1023 and is able to pass the check:

Collectibles Xrefs

How to solve it

My first idea was to see if I can manually get to defuse through the required functions by clicking a sequence of functions in IDA, unfortunately due to the 1600+ functions available this was not really a possibility.

Second idea was to use the integrated graph functionality IDA has, but instead of anything nice coming out of it we got a sick ass star destroyer:

Star Destroyer Call Flow

As much as I love the Empire, this was very unhelpful :(

Well, how about a big brain strat then, we run pathfinding algorithms, that should work! Right…?

IDA has an integrated pathfinding function, you can get there by doing a similar sequence of operations to the following:

Right Click->Proximity Browser->Right Click->Add Node(s)->Right Click->Find Path

MFW IDA dies again because of too many functions.

As a result, I engaged 300iq mode and ran the following command:

 .\idat64.exe "-Ohexx64:-new:kurwa.c:ALL" -A "{PATH_TO_BOMB}\bomb"

What does it do you ask? Well, that uses the amazing IDA CLI to decompile all functions for us and put it into a file we called kurwa.c.

My smort teammate wrote up a quick pathfinding algorithm in Haxe™ in order to find which functions connected to which, and used that to find a path that would lead to defuse with the required checkpoints. (Note: this was after 400 failed attempts and not realizing that some functions were dead ends, fortunately the decompiler noticed this, our initial approach which used ASM only didn’t :c)

WOOOOOSH, okay we got the PATH (the addresses are taken from IDA):

  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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  # wiring -> EERYGRINGO
  0x48D46A, # wiring
  0x4080F3, # FULFILSIMILE
  0x408229, # USEABLECHUMP
  0x408354, # HUSKYMULLAHS
  0x4084FC, # SERVESTILT
  0x408632, # MATTEJOYED
  0x40E4BE, # SHOESITAR
  0x40F521, # ATONALHOAGIE
  0x4153CA, # WOBBLEFORLORN
  0x416268, # NUPTIALAZALEA
  0x41BEAE, # MATCHWINDBAG
  0x41CDE0, # POTABLEHAGGARD
  0x422AB7, # BOOZERPOISON
  0x423A49, # SKYJACKARTISTE
  0x42391B, # GENETICPOACHER
  0x42379B, # USHEREDPREMIUM
  0x429B7D, # MUCOUSEPISODE
  0x42A54D, # SERIALSOYA
  0x430767, # PARTIALTROPHY
  0x4311EA, # SNIPPYNAVE
  0x4374C5, # FREEZERROBS
  0x437DE7, # GENTNEBULA
  0x43E1E2, # NASTYCHEWY
  0x43EC02, # THIRDBLINTZ
  0x43EAD7, # DURABLERUNNIER
  0x43E96D, # MOCKBLENT
  0x445376, # BURPEDLUBED
  0x445761, # ODOROUSJEWELER
  0x44C195, # SUCHFORESEE
  0x44C57B, # EVASIVEDUET
  0x452DA4, # RIGIDTRADUCE
  0x453179, # LAWFULOFFBEAT
  0x459BD8, # POETICARTLESS
  0x459FFD, # CHOPPYSLIDER
  0x45A133, # CONICALMESAS
  0x45A2B0, # BAGBARREL
  0x46073A, # RADIUMUNIQUER
  0x4610D3, # ANNEALMOURN
  0x461250, # ALIVECURTEST
  0x4613D0, # FECALSWOLLEN
  0x4604D0, # CAUSTICNYMPHS
  0x45A516, # SERUMPONTOON
  0x4595DF, # AGAPETHEATER
  0x45373A, # RICKSHAVERTIGO
  0x452834, # KINETICJADING
  0x44CB22, # CALICOSPUSSY
  0x44C9A2, # TONECOMPETE
  0x44C822, # GOODROVER
  0x44BEFB, # YOGISFAIREST
  0x445A3A, # IMMORALRAREFY
  0x445BE2, # PLYWOODSHANK
  0x445D18, # LUCKYHOMONYM
  0x445EC0, # HEAVENHAZEL
  0x446068, # LOUTISHTHEREIN
  0x444A5E, # RIFESHORTEN
  0x43F20C, # EMPTYTYMPANA
  0x43DCB9, # ELEGIACDELUXE
  0x438315, # FIBBERFALCON
  0x438495, # LINGUALGLAD
  0x438612, # SHRINKSPAR
  0x436D37, # FICTIONRETRACT
  0x431992, # COSIEREXECS
  0x431AFC, # POLISHCACTI
  0x431C27, # PERIWIGMARINER
  0x42FBCA, # UNJUSTPACIFIC
  0x42AFF1, # PARDONREEKS
  0x4290D5, # BRAYEDBASIL
  0x4242B5, # BAUBLEVILLAIN
  0x42441F, # BENCHCHORUS
  0x4245C7, # GROSSPATE
  0x421F21, # ABLERCAM
  0x41D84E, # FINALPERTEST
  0x41B404, # METRICCONTAIN
  0x416DD6, # NOURISHLEG
  0x416C59, # VIOLENTCRULLER
  0x416ADC, # NITERJEWEL
  0x414B39, # ADDUCEDREAD
  0x40FC98, # LARCENYCASTOR
  0x40FB6D, # RACEMESUBSUME
  0x40FA37, # GIBLETHOB
  0x40F907, # PUTTENURE
  0x40F787, # HUFFEDAUREOLA
  0x4150E8, # LYNXFORFEIT
  0x416540, # EERYGRINGO
  # EERYGRINGO -> GOUTIERSHILL
  0x416668, # collectible in EERYGRINGO
  0x4150E8, # LYNXFORFEIT
  0x40F787, # HUFFEDAUREOLA
  0x40F907, # PUTTENURE
  0x40FA37, # GIBLETHOB
  0x40FB6D, # RACEMESUBSUME
  0x40FC98, # LARCENYCASTOR
  0x40FE40, # WINDIERHIND
  0x40FFE8, # RASCALCHARM
  0x40D990, # COCCISWALLOP
  0x40919F, # BILIOUSRETOOL
  0x409309, # AGATEWOOFS
  0x409473, # PRIZEBANGING
  0x4095A1, # TRIKEFINESSE
  0x40970B, # HAPPYSHADOWY
  0x4098B3, # MUFFLECOLLEGE
  0x409A1D, # FELLEREASEL
  0x409B46, # CLOBBERPINCER
  0x409C71, # GOUTIERSHILL
  # GOUTIERSHILL -> MAJORKNIT
  0x409D61, # collectible in GOUTIERSHILL
  0x409DFE, # STICKYLUSTIER
  0x409FA6, # JAWINGPOOREST
  0x40A0D4, # COSTLYBANI
  0x40A20A, # DEPOTNICHE
  0x40A335, # FULLLOUSY
  0x40A460, # UNLUCKYLAUGH
  0x40A608, # BRUISERRAINIER
  0x40A7B0, # SEPALTRIPOS
  0x40C299, # MIMEINVEIGH
  0x411795, # COPILOTLAUGH
  0x413191, # SHAMBLEPALE
  0x418421, # DUBIOUSMADCAP
  0x418557, # SEPTICNOVELTY
  0x418685, # OAFISHINSOLE
  0x41882D, # CURRENTRESIDE
  0x418966, # TAPIOCATICKET
  0x418A9C, # WUSSDEPLANE
  0x418BCA, # LABIALOUTWEAR
  0x419552, # HENCAMBER
  0x41F559, # STABLETANAGER
  0x420011, # UNPAIDCAPTIVE
  0x42647F, # HAPPYPARKING
  0x426315, # ARCHIVERHEA
  0x4261D8, # MAJORKNIT
  # MAJORKNIT -> UPTOWNROBBED
  0x4262A6, # collectible in MAJORKNIT
  0x426315, # ARCHIVERHEA
  0x42647F, # HAPPYPARKING
  0x420011, # UNPAIDCAPTIVE
  0x41F559, # STABLETANAGER
  0x419552, # HENCAMBER
  0x418BCA, # LABIALOUTWEAR
  0x418A9C, # WUSSDEPLANE
  0x418966, # TAPIOCATICKET
  0x41882D, # CURRENTRESIDE
  0x418685, # OAFISHINSOLE
  0x418557, # SEPTICNOVELTY
  0x418421, # DUBIOUSMADCAP
  0x419DB1, # WIDEHOKEY
  0x41EDF0, # OMINOUSPALL
  0x4208A2, # WORNUNTRUER
  0x425CA1, # FAIRSLEUTH
  0x425E0B, # EQUABLEBROODER
  0x425F3B, # CROUCHPASTA
  0x4274B5, # FUMBLERGRAVEST
  0x42CB03, # SECRETLEFTIE
  0x42CC2E, # OVERALLBEAUTY
  0x42CDAB, # LAMBDALECTERN
  0x42CF2B, # DURABLEMUKLUKS
  0x42D095, # YUPPYMATZOS
  0x42D1FF, # RARESTHUBBY
  0x42D37C, # ANGRYHIKE
  0x426B87, # TALENTDISBAR
  0x426732, # ACETICACCESS
  0x4268AF, # GLOBALROOM
  0x403AD1, # WEEKENDBUSSING
  0x403929, # BRASSTUMBLER
  0x403781, # FORMALSAG
  0x403617, # PELICANSUNLIT
  0x4034E1, # MODESTRECITAL
  0x403364, # TROUGHBLANCH
  0x4031BC, # UNMORALRHYTHM
  0x403052, # JIGGEDLEMUR
  0x402F1C, # UNREADUNCUT
  0x402DB2, # TINYPAPA
  0x402BF3, # UPTOWNROBBED
  # UPTOWNROBBED -> TUMORPEG
  0x402D1E, # collectible in UPTOWNROBBED
  0x402DB2, # TINYPAPA
  0x402F1C, # UNREADUNCUT
  0x403052, # JIGGEDLEMUR
  0x4031BC, # UNMORALRHYTHM
  0x403364, # TROUGHBLANCH
  0x4034E1, # MODESTRECITAL
  0x403617, # PELICANSUNLIT
  0x403781, # FORMALSAG
  0x403929, # BRASSTUMBLER
  0x403AD1, # WEEKENDBUSSING
  0x4268AF, # GLOBALROOM
  0x426732, # ACETICACCESS
  0x426B87, # TALENTDISBAR
  0x42D37C, # ANGRYHIKE
  0x42D1FF, # RARESTHUBBY
  0x42D095, # YUPPYMATZOS
  0x42CF2B, # DURABLEMUKLUKS
  0x42CDAB, # LAMBDALECTERN
  0x42CC2E, # OVERALLBEAUTY
  0x42CB03, # SECRETLEFTIE
  0x42E00C, # AORTAEACHE
  0x4337D0, # AIMLESSTALK
  0x434D79, # ODIOUSBLOCK
  0x43A56B, # ANGEREDDWARF
  0x43A3EB, # REAPBLIMP
  0x43A2B1, # REFRAINWEDDER
  0x43BD18, # FERTILEHURTLE
  0x44113B, # CONDUCTCRISIS
  0x442BC5, # FURNISHFAIR
  0x447E9E, # MAINMANIKIN
  0x447CF6, # ANTIQUEIVY
  0x447BC0, # GENERALPROSODY
  0x447A40, # CONICALPISS
  0x447898, # VIRTUALBULKIER
  0x449F01, # SKEPTICBEGS
  0x44E6C1, # PREPPYCLUNG
  0x44E7EC, # PUBLISHSOLOED
  0x44E956, # GARAGETAXIS
  0x4509EC, # MOVABLESHUNT
  0x45563C, # CURIOUSMUSCLE
  0x4557BC, # VESTTYPESET
  0x455964, # HAPPYTUCKER
  0x455B0C, # COMBOSEPTET
  0x455C76, # SLIMYUSER
  0x4503EE, # UNSOLDPEEL
  0x44EEB2, # COMMONSTYLIST
  0x449776, # SEWERLUMMOX
  0x448159, # TUMORPEG
  # TUMORPEG -> PURISTBENDER
  0x448281, # collectible in TUMORPEG
  0x449776, # SEWERLUMMOX
  0x44EEB2, # COMMONSTYLIST
  0x4503EE, # UNSOLDPEEL
  0x455C76, # SLIMYUSER
  0x455B0C, # COMBOSEPTET
  0x455964, # HAPPYTUCKER
  0x4557BC, # VESTTYPESET
  0x45563C, # CURIOUSMUSCLE
  0x4509EC, # MOVABLESHUNT
  0x44E956, # GARAGETAXIS
  0x44E7EC, # PUBLISHSOLOED
  0x44E6C1, # PREPPYCLUNG
  0x450C62, # SHINWALLEYE
  0x45538F, # THOUSHEATER
  0x457AF1, # SLOPPYCOUPLE
  0x45C0B4, # DYNAMICREAR
  0x45E6BF, # AROSENOSTRUM
  0x463064, # CLUSTERDOZE
  0x4631E1, # SEISMICWOOZY
  0x46330C, # AMOROUSQUIZ
  0x4652ED, # BURROAPT
  0x46A215, # GRATISRIBALD
  0x46A06D, # FESTIVEUNCORK
  0x469F03, # ADJUDGEDELVE
  0x469DCD, # UNAIDEDMIDWAY
  0x469C63, # TRUMPETLID
  0x469AE3, # MUCHOBJECT
  0x4699B8, # CIVILGLUEY
  0x46988D, # BUBBLEABACK
  0x469723, # SCUMMYTUNIC
  0x46CD40, # FONDUEINVOKE
  0x470293, # ELUSIVESWEAR
  0x4737D8, # FINALSHEET
  0x476DE4, # ZOMBIMINIVAN
  0x476CB9, # ALIVEDIORAMA
  0x476B81, # SENSUALPOLEMIC
  0x47A67B, # PURISTBENDER
  # PURISTBENDER -> AMOUNTRAKISH
  0x47A73F, # collectible in PURISTBENDER
  0x47D765, # SEMINALPIQUE
  0x48132A, # GENERALBUNKING
  0x4845CC, # UNSOLDFEST
  0x48844B, # WARBLESERMON
  0x48B5A5, # UNDIDSILKY
  0x48B47A, # BEATERBODE
  0x48B34F, # ADJUSTRANKEST
  0x48B219, # DRAFTEEBRIDGE
  0x48B09C, # OPTICALCORNET
  0x48AEF4, # OVARYTRUNDLE
  0x48AD8A, # HACKSAWFRAT
  0x48AC20, # CIVETPARFAIT
  0x48AAE6, # SHINGLEKNIFE
  0x48A97C, # UNITYCLEANSE
  0x48A7FC, # VOILEFIRMEST
  0x48A643, # AMOUNTRAKISH
  # AMOUNTRAKISH -> LAYOVERCLINK
  0x48A76B, # collectible in AMOUNTRAKISH
  0x48A7FC, # VOILEFIRMEST
  0x48A97C, # UNITYCLEANSE
  0x48AAE6, # SHINGLEKNIFE
  0x48AC20, # CIVETPARFAIT
  0x48AD8A, # HACKSAWFRAT
  0x48AEF4, # OVARYTRUNDLE
  0x48B09C, # OPTICALCORNET
  0x48B219, # DRAFTEEBRIDGE
  0x48B34F, # ADJUSTRANKEST
  0x48B47A, # BEATERBODE
  0x48B5A5, # UNDIDSILKY
  0x48B6DB, # RETRYJAB
  0x48B806, # RITZIERCOARSER
  0x48B970, # NEEDFULWALLOW
  0x48BAED, # VITAMINGRIPE
  0x48BC23, # WRYROPED
  0x48BDA3, # FAMOUSSEGUE
  0x48BECC, # THROELEAKIER
  0x48BFF7, # VIABLEGOOIEST
  0x48C177, # BADEDISPEL
  0x48C31F, # DECENTPRIEST
  0x48C49C, # DETESTRETORT
  0x48C644, # EARMARKDANDY
  0x4872F3, # VICIOUSBRAZIER
  0x48579B, # AERIALEMPANEL
  0x485631, # PANGLEMUR
  0x4854C7, # STAREHACKNEY
  0x48530E, # LAYOVERCLINK
  # LAYOVERCLINK -> UPPERTOPSIDE
  0x485436, # collectible in LAYOVERCLINK
  0x4854C7, # STAREHACKNEY
  0x485631, # PANGLEMUR
  0x48579B, # AERIALEMPANEL
  0x4872F3, # VICIOUSBRAZIER
  0x48C644, # EARMARKDANDY
  0x48C7AE, # HUMERIUPPITY
  0x48C8E4, # UPPERTOPSIDE
  # UPPERTOPSIDE -> ESTUARYAJAR
  0x48C9D4, # collectible in UPPERTOPSIDE
  0x48CA71, # SHIELDOXFORD
  0x48CBF1, # SCABBEDDAWN
  0x486CCB, # REGULARPUDGIER
  0x485D67, # SPACIALCOHABIT
  0x485BF3, # ESTUARYAJAR
  # ESTUARYAJAR -> MINUTEMISFIRE
  0x485CF6, # collectible in ESTUARYAJAR
  0x485D67, # SPACIALCOHABIT
  0x486CCB, # REGULARPUDGIER
  0x48CBF1, # SCABBEDDAWN
  0x48CD6E, # FONDUECRASS
  0x48CEEB, # GRUMBLEFAUNAE
  0x48D06B, # HILLTOPBEEFIER
  0x48D196, # ALLOYJAW
  0x48D300, # OWNRAVINE
  0x40109A, # MINUTEMISFIRE
  0x40119D # FINAL!

Cool! This should be EASY MODE now!

.
.
.
.
.
.
.

24 hours later

Vegetative State

I have reached the ultimate vegetative state after trying to learn angr.

Because the application is relatively complex, the idea is to take two neighboring functions at a time by using their addresses. Let’s call these address A and B. We find the input required to pass from addres A to addres B, and we continue to find the input to progress from B to C, C to D etc.

Because the path is long, I figured I would use angr in order to do this, because it would automatically solve for the required inputs.

However, I ran into a lot of issues (mostly because it was my first time using angr!). Nonetheless, after hours of banging my head against my keyboard I wrote up a script that finds the required inputs one by one and prints them out in a ridiculously shitty format.

Therefore, because I am so incredibly smart (like who wants to do it all in one script????), I wrote a parser to parse the output of my first script into something we can send to the binary and solve it :D

The first script which calculates the inputs can be found here

The tl;dr is that we hook scanf and strlen and let angr solve constraints.

However, a few things to explain:

You can run the script as follows:

python hydrogen-bomb-solve.py > outputname.txt

The script to parse the output of the above (given you remove all the spaces on each line), can be found here.

It effectively parses everything and sends it off to the server.

When that finishes running, we get our sweeeeeet flag:

IceCTF{aut0mat1on_w1ll_e4t_4ll_0ur_j0bs}