Airgapp CTF
On the 2nd of May 2020 Thugcrowd ran AIRGAPP, and along side this conference they hosted a CTF. I worked with the CTF_Circle team and we finished 1st overall!
Discord (Captured, 10pts)
Test your ability to read a Discord message.
This flag was quite simple, the first message in the official discord channel for the CTF was
thug{its_free_real_estate}
this was the flag.
Elliot (Captured, 10pts)
This flag was also relatively quick, not sure where to start for these recon flags I ran
wget -m ctf.airgapp.in
and then following the hint to search airgapp website I ran a search across the entire site
grep -s "thug{" * .*
which returned
robots.txt:thug{HeLlO_mR_rObOt}
While I did expect these flags to be more obfuscated than that, the other recon flags proved trickier, and their 10pt value should have been a hint to not waste so much time on them.
Kappa (Captured, 10pts)
There's a flag hiding somewhere on Twitch.
This was a twitch recon flag which lead us, initially to look at clips and video descriptions from previous broadcasts, all to no avail. We then figured we'd try chat for commands for a bot that may give a flag, I sent the chat
!flag
and got
!flag
in reply from a twitch user by the name of "definitelynotaflag" who has a stream description of
thug{streaming_video_platform}
This flag was interesting in that the definitelynotaflag did not seem to always respond to people for the flag, and was often not watching the stream.
Not Elliot (Not Captured, 10pts)
Knowing now that Elliot was a reference to Mr. Robot we then looked for references to non robot things (hoping to take a hint from the title of this flag), we looked for a
/notrobots.txt
but did not check the location
/humans.txt
where the flag actually resided.
ayy lmao (Not Captured, 10pts)
Snoop around the THUGCROWD and AIRGAP websites until you find some flags.
Much like Not Elliot, we had some suspicions about what this might relate to. We figured it would be a reference to the ayy lmao alien meme, but did not think to check
/aliens.txt
paramz (Captured, 200pts.)
parameters are easy!
This challenge provided a WASM file and an html file with some horrifically obfuscated JS. After setting up FireFox to allow WASM debugging, you can work through the parameters without spending time digging at the JS.
(module
(type $type0 (func (param i32) (result i32)))
(type $type1 (func))
(global $global0 i32 (i32.const 0))
(export "__wasm_apply_relocs" (func $func0))
(export "_acb" (func $func1))
(export "_bcb" (func $func2))
(export "_ccb" (func $func3))
(export "_dcb" (func $func4))
(export "_ecb" (func $func5))
(export "_fcb" (func $func6))
(export "_gcb" (func $func7))
(export "_hcb" (func $func6))
(export "_icb" (func $func5))
(export "_jcb" (func $func8))
(export "_kcb" (func $func9))
(export "_lcb" (func $func10))
(export "_mcb" (func $func11))
(export "_ncb" (func $func6))
(export "_ocb" (func $func5))
(export "_pcb" (func $func12))
(export "_qcb" (func $func13))
(export "_rcb" (func $func6))
(export "_scb" (func $func1))
(export "_tcb" (func $func3))
(export "_ucb" (func $func14))
(export "_vcb" (func $func15))
(export "_wcb" (func $func4))
(export "_xcb" (func $func9))
(export "__dso_handle" (global $global0))
(export "__post_instantiate" (func $func0))
(func $func0
nop
)
(func $func1 (param $var0 i32) (result i32)
get_local $var0
i32.const 100
i32.ne
)
(func $func2 (param $var0 i32) (result i32)
get_local $var0
i32.const 71
i32.ne
)
(func $func3 (param $var0 i32) (result i32)
get_local $var0
i32.const 104
i32.ne
)
(func $func4 (param $var0 i32) (result i32)
get_local $var0
i32.const 49
i32.ne
)
(func $func5 (param $var0 i32) (result i32)
get_local $var0
i32.const 90
i32.ne
)
(func $func6 (param $var0 i32) (result i32)
get_local $var0
i32.const 51
i32.ne
)
(func $func7 (param $var0 i32) (result i32)
get_local $var0
i32.const 116
i32.ne
)
(func $func8 (param $var0 i32) (result i32)
get_local $var0
i32.const 86
i32.ne
)
(func $func9 (param $var0 i32) (result i32)
get_local $var0
i32.const 57
i32.ne
)
(func $func10 (param $var0 i32) (result i32)
get_local $var0
i32.const 115
i32.ne
)
(func $func11 (param $var0 i32) (result i32)
get_local $var0
i32.const 98
i32.ne
)
(func $func12 (param $var0 i32) (result i32)
get_local $var0
i32.const 108
i32.ne
)
(func $func13 (param $var0 i32) (result i32)
get_local $var0
i32.const 88
i32.ne
)
(func $func14 (param $var0 i32) (result i32)
get_local $var0
i32.const 99
i32.ne
)
(func $func15 (param $var0 i32) (result i32)
get_local $var0
i32.const 50
i32.ne
)
)
these are in order up to number 7 and with a little bit of scrolling and copying and pasting it can be simplified down to
(export "_acb" (func 100))
(export "_bcb" (func 71))
(export "_ccb" (func 104))
(export "_dcb" (func 49))
(export "_ecb" (func 90))
(export "_fcb" (func 51))
(export "_gcb" (func 116))
(export "_hcb" (func 51))
(export "_icb" (func 90))
(export "_jcb" (func 86))
(export "_kcb" (func 57))
(export "_lcb" (func 115))
(export "_mcb" (func 98))
(export "_ncb" (func 51))
(export "_ocb" (func 90))
(export "_pcb" (func 108))
(export "_qcb" (func 88))
(export "_rcb" (func 51))
(export "_scb" (func 100))
(export "_tcb" (func 104))
(export "_ucb" (func 99))
(export "_vcb" (func 50))
(export "_wcb" (func 49))
(export "_xcb" (func 57))
I then threw these lines into excel: [imgleft]https://blog.q3w3e3.dev/assets/img/screenshots/params.png[/imgleft]
and split them at the _ and )) and eventually generating a list of parameters
?a=100&b=71&c=104&d=49&e=90&f=51&g=116&h=51&i=90&j=86&k=57&l=115
&m=98&n=51&o=90&p=108&q=88&r=51&s=100&t=104&u=99&v=50&w=49&x=57
when these params are checked on the main site an alert is then shown with the flag
thug{we_love_wasm}
Gerkinz (Captured, 200pts)
host: ctf.airgapp.in port: 5000
See the amazing writeup by T Van Doren over here
tecmu (Captured, 300pts)
See the lovely writeup by Sen over here or over gopher.
Spilling Messtake (Captured, 200pts)
Since the world is falling apart, you decide to pick up your old Gameboy to play some Pokemon Red. Immediately after entering your name, you realize you accidentally misspelled WUTANG as VUTANG. Damn. Create a Gameshark code to fix this problem for you. Then submit the flag as thug{CODE_HERE}
A teammate completed this flag, I may update this with their writeup.
Compy385 (Not Captured, 150pts)
do you like techno music?
A teammate nearly completed this flag, I may update this with their writeup.
We were unable to complete the flag because we were defeated by newline characters.
The Thugcrowd and Friends Happy Fun Time Crossword (Not Captured, 100pts)
Each clue is the Twitter handle of one of our friends. Fit them all into the puzzle and the highlighted letters will spell out the flag.
For this we went through twitter users with links to thugcrowd, and as many people as we could find that had been guests on the podcast, resulting in [this spreadsheet. As you can tell, I love working in spreadsheets, if something can be reasonably improved by a spreadsheet, I make one!
Takeaways and Lessons Learned
- Stop assuming that hex with x86 like entropy is x86, try something else... this probably lost us flags.
- Crypto hard, practice moar.
- Communication is important, documentation more so... Partially completed flags should be in a state where team members can pick up your work.
- I should do more of these, I love doing this stuff.
- Working in teams is a great way to learn (see #4).
- Sometimes it's important to prioritize targets based on their value, the time I spent digging for 10pt flags was not worth as much as that spent on the higher point flags.
And lastly, I know a number of my teammates were close with other challenges and would have loved to have worked with them a little longer to complete them all. I want to congratulate them all on the work, and thank them for letting me work with them during this CTF.