0xkasper

RiceTeaCatPanda CTF 2020 Write-Up

· ctf, crypto, rev, misc, web, forensics

Introduction

I finally decided to participate in a CTF and chose the first upcoming CTF on CTFTime. This was the RiceTeaCatPanda CTF and, both because of my lack of CTF experience and the name of this particular CTF, I had no idea what to expect exactly. The CTF started on Monday, January 20th, and would last for five consecutive days until Friday. There were no prizes but the RTCP team highly encouraged participating, even if you did not have any CTF experience, in order to gain more practical knowledge.

The five days of this CTF were a really great experience. It was amazing to see so many like-minded people come together in the RTCP Discord, encouraging and helping each other. I am indeed very happy to have become part of this community and I look forward to doing a lot more CTFs in the coming future. There were plenty of categories and challenges to be solved and most of them were quite interesting. This is why I wanted to take this opportunity and make my first article a write-up of the challenges I completed during the RiceTeaCatPanda CTF 2020.

Check out the RTCP Github repository for the challenges.


Cryptography


HOME RUN!

Points: 50

Description: AND JAKE IS ROUNDING THE BASES. HE PASSES BASE 32! HE ROUNDS BASE 64! WE’RE WITNESSING A MIRACLE! Just one more base to go ;D

Hints:

After Base32 and Base64 comes Base85, so let’s use this website to decode the string and reveal the flag.

Flag: rtcp{uH_JAk3_w3REn’t_y0u_4t_Th3_uWust0r4g3}


Points: 100

Description: It was just a typical day in the bakery for Delphine. She was preparing her famous chocolate cake, when all of a sudden a GIANt burst through the doors of her establishment and demanded a cookie. Being the strong-willed girl she was, Delphine refused and promptly threw her rolling pin at the GIANt. Doing what any sensible being would do when faced with projectiles, the GIANt let out a shriek and ran out of the shop. Delphine smiled to herself, it was another day well done. But oh? What’s this? It seems the GIANt dropped this behind while he was screaming and scrambling out of the shop. 69acad26c0b7fa29d2df023b4744bf07

The given strings looks like an MD5 hash, so let’s try to decrypt it using this website and obtain the flag.

Flag: rtcp{chocolate_mmm}


15

Points: 100

Description: -long cryptic text-

The description looks like gibberish, but it ends with tovm{v4T3Ehq_f1oK_3J1e_i4O4}, which looks like the flag. But obviously the letters are wrong. The tovm should be rtcp, so this hints at the text being encrypted using a substitution cypher. We can use this website to solve these kinds of texts. The resulting text is a news acticle about foot fungus and Burger King. And, of course, the flag as well.

Flag: rtcp{c4R3Ful_w1tH_3X1f_d4T4}


notice me senpai

Points: 100

Description: uwu…senpai placed this note on my desk before class but i cant wead what it says! can you hewp me? uwu tysm
tlyrc_o_0pnvhu}{137rmi__i_omwm

The message contains all the elements of a flag: rtcp{}. The message might therefore be an anagram, which can be solved using this anagram solver. It is important however, to remove the rtcp{} from the string and replace the numbers with their corresponding letters, according to leet. So 0 becomes o, 1 becomes i, 3 becomes e, and 7 becomes t, resulting in ly_o_onvhuietrmi__i_omwm. Solving it gives: im_in_love_with_your_mom, and putting the numbers back gives us the flag.

Flag: rtcp{im_1n_lov3_wi7h_y0ur_mom}


Wrong Way

Points: 150

Description: Did you know that you’ve been going the wrong way entire time?
E7Rq<G:Kǒ

This challenge is not that difficult, it just requires some guessing and trying things out.

t = 'E7Rq<G:Kǒ'
print(base64.b64encode(t.encode('utf-8')))

If we encode this string using Base64, we get RTcPUnEXPEcTEDpLAceS, which has to be converted to the standard flag format to get the flag.

Flag: rtcp{unexpected_places}


That’s Some Interesting Tea(rs)

Points: 175

Description: You know, the tears of one’s enemies works lovely in tea. Turns out, there’s tons of different bases for tea. In fact, I think I heard Delphine talk about this chef website she used for her tea base combinations. Oh! Speaking of which, GIANt wants Delphine to make him tea. All he has is the tea leaves and the cup though. Maybe you can help Delphine, since she’s really busy with cooking other things?
O53GG4CSJRHEWQT2GJ5HC4CGOM4VKY3SOZGECZ2YNJTXO6LROV3DIR3CK4ZEMWCDHFMTOWSXGRSHU23DLJVTS5BXOQZXMU3ONJSFKRCVO5BEGVSELJSGUNSYLI2XQ32UOI3FKWDYMJQWOMKQOJ4XIU2WN5KTKWT2INUW44SZONGUUN2BMFRTQQJYKM3WGSSUNVXGEU3THFIFUSDHIVWVEQ3LJVUXEMSXK5MXSZ3TG5JXORKTMZRFIVQ=

The given strings looks a lot like a Base encoding, because it ends with = and the characters that are used. But there are no lowercase letters and the numbers 1, 8 and 9 are not used, this means that it’s probably Base32 and not Base64. Decoding the string using Base32 indeed gives us a next similar-looking string. This next string is encoded with the next Base in line, Base58. This goes on for Base62, Base64 and finally Base85 and it reveals the flag. Use CyberChef to easily decode the string.

Flag: rtcp{th4t5_50m3_54lty_t34_1_bl4m3_4ll_th0s3_t34rs}


That’s a Lot of Stuff

Points: 275

Description: Do you want some numbers? Here, take these numbers. I don’t need them anyways. I have too many numbers at home, so go on, take them. Shoves numbers towards the computer screen
31 34 33 20 31 35 36 20 31 32 32 20 31 35 32 20 31 34 33 20 31 31 30 20 31 36 34 20 31 35 32 20 31 31 35 20 31 30 37 20 36 35 20 36 32 20 31 31 35 20 36 33 20 31 31 32 20 31 37 32 20 31 31 35 20 31 32 34 20 31 30 32 20 31 36 35 20 31 34 33 20 36 31 20 37 31 20 31 35 30 20 31 34 33 20 31 35 32 20 31 31 36 20 31 34 36 20 31 31 36 20 31 30 36 20 37 31 20 31 35 32 20 31 31 35 20 31 30 34 20 31 30 32 20 31 31 35 20 31 33 30 20 36 32 20 31 31 35 20 36 30 20 31 34 34 20 31 31 30 20 31 31 36 20 37 31

This challenges again requires you to chain different kinds of encodings and converting from different numeral systems. These number look a lot like hexadecimal and converting them from hexadecimal gives a smaller amount of three-digit numbers. These numbers look like octal and converting from octal gives a string of Base64-like characters. And therefore, decoding using Base64 reveals the flag.

Flag: rtcp{c0nv3rs10ns_ar3_4_c00L_c4ts}


Pandas Like Salads

Points: 350

Description: Did you know a new panda was added to the Washington DC zoo recently? Yep, apparently she really like salads. Interesting, yeah? Also, the panda keepers of the zoo said that the key to happiness in life is a little CUTENESS every day. You know, all the keepers who are on the panda’s rotation all said the same thing to me. Very interesting.

Attachments: pandas-like-salads.png

This looks a lot like Pigpen Cipher, so let’s use this website to decode it and obtain the next string: YSAY{HJKAHR_QQGDIA_UNR_KW_YRQ_PM_NNFB}. This next string is a Vigienere cipher, which needs a key. In the description it’s said that CUTENESS is the key (to happiness in life). You can use CyberChef for this step and the next one. This gives the next string: WYHU{UFSIFX_XMTZQI_STY_GJ_UZY_NS_UJSX}. In the description the word ‘rotation’ probably suggests a ROT encoding, such as ROT-13. But in this case you have to try multiple rotations and find that it’s ROT-21. Decoding the string and converting it to lowercase reveals the flag.

Flag: rtcp{pandas_should_not_be_put_in_pens}


FBI

Points: 375

Description: Happy MLK day! (January 20th for y’alls non-American folk).

Hints:

Attachments:

The MESSAGE.txt file contains the word ‘KING’ on the first line, followed by 55 triplets of numbers, one on every line. If we look at the hint, we can see that the challenge has something to do with the FBI and Martin Luther King Jr. This is probably a reference to the FBI-MLK suicide letter. The MESSAGE.txt starts with ‘KING’, just like the letter. Since the first value of every triplet doesn’t exceed the number of paragraphs of the letter, so I reckon that the triplets are coordinates for the letter. At first I tried to divide each paragraph up into sentences and then into words, where the second value would correspond to a sentence and the third one to a word. But that didn’t work. The right way is to divide each paragraph into lines, according to the actual picture of the original letter. The second value would then correspond to the line number and the third value to the letter in the line. Doing this for every triplet and stitching them together will give you the flag.

Flag: rtcp(happy-fiftieth-mlk-day-america-has-come-a-long-way)


Code On

Points: 500

Description: My houseplant and I were working on a biology assignment together. Yes, my houseplant. Don’t question it. Anyways, she ended up giving me a new cipher to use in my next project! So I’m giving it to my biology friends to see if they can solve it. They are, after all, studying DNA and mRNA right now.
AUGCAAGGUCUCUUGACCCAGUGGAUACUAAAUGCCUGGAAGGUAGCAUACUAG
Key: 6, 3, 4, 3, 1, 9, 8, 3, 3, 2, 7, 4, 1, 2, 4, 1

This challenge was very interesting to solve. The sequence is an mRNA sequence, because it uses U instead of T and starts with AUG. A codon is a triplet of A, U, C or G and mRNA sequences consist of multiple codons. Each codon combination corresponds to an amino acid. Except for the start and stop codon, there are 16 codons in the sequence and we have 16 keys. So we therefore have to construct the chain of amino acids for this particular sequence and use the key as letter-index for every amino acid. For example, CAA translates to Glutamine, and with key 6 that’s the letter m. Doing this for all keys and putting it together results in the flag.

Flag: rtcp{mycutehouseplant}


Hump’s Day

Points: 1050

Description: Happy Hump’s Day
Happy TGIF!
Happy Saturday
Happy Tuesday +1
Happy Thursday +1
Happy TGIF -2
Happy Monday!
Happy Hump’s day +5 3 times
Happy Saturday +3
Happy TGIF +1
Happy Tuesday +0
Happy Friday +3
Happy TGIF -1
Happy Wednesday
Happy TGIF
Happy Sunday
Happy Saturday -5

Hints:

This challenge was worth only 50 points in the beginning, but it wasn’t solved by anyone after 2 days, so it was increased to 1050 points and the 2 hints were added. In the end it wasn’t that difficult actually. Hump’s Day is the typical midpoint of a work week, or CTF week in this case, in other words it’s Wednesday. TGIF stands for Thank God It’s Friday, so that’s Friday. Every weekday stands for one digit according to the week order. For example Monday is 1, Hump’s Day is 3, TGIF -2 is 5-2 or 3 and Sunday is 0. The point is to put all digits together into one decimal number: 3563531888962843501. Converting that to hexadecimal gives: 3174355F6368336D and converting that to ASCII results in the flag.

Flag: rtcp{1t5_ch3m}


Reverse Engineering


What’s the Password: Revisited

Points: 300

Description: There’s a password somewhere…

Attachments:

First we’ll try to execute the binary and see what it does. It outputs ‘Whats the password?’ and then waits for user input. When trying a random wrong password, it will output ‘Hey, thats not right!’ and exit. Let’s load the binary into radare2 and try to decompile it.

$ r2 ./whats-the-password-revisited
$ aa
$ s main
$ pdd

This shows a decompilation of the binary and reveals some interesting information. It shows that it uses a stack protection, so using a buffer overflow probably won’t work. After copying the input string, it will start a while loop and does some checks, which is probably more interesting.

whats-the-password-revisited.png

As you can see, it copies the first 8 characters of the string ‘fL492_r_h4rd3r_th4n_th1s’, which is the decoy flag you obtain if you just search for strings in the binary. So the flag starts with ‘fL492_r_’ and then we enter a while loop where eax and ecx are compared. Rdx is the counter and we jump out of the loop when it reaches 0x14 or 20. Every iteration, rdx is multiplied by 5, left-shifted with 4 (which is the same as multiplying by 16) and the address of rsi is then added. The value at this address is then stored in ecx and later used for comparison. Eax contains the current character of the user input, which is XOR’d with 0x32, incremented and again XOR’d with 0x32. Eax and ecx have to be equal every iteration, or the program will exit. After 20 iterations, the flag is correctly built and printed. Trying to overwrite the comparison code won’t help, because the flag is the actual password that is needed to correctly loop the 20 iterations. You can either copy the data in esi and do the accesses yourself or check the value of ecx for every iteration, which is what I did. From there you only have to XOR each value with 0x32, decrement it and XOR it again. Put ‘fL492_r_’ in front of it and you’ve got yourself the flag.

Flag: rtcp{fL495_r_50m371m32_5Pr34D_0U7}


Miscellaneous


Come Eat Grandma

Points: 25

Description: Oh, my bad, this spreadsheet appears to be missing its commas.

Hints:

The Google Docs link leads to a spreadsheet were a bunch of people have edited stuff and the flag is nowhere to be found. Luckily, we can see the edit history of a document. Going back to January 20th reveals the flag.

Flag: rtcp{D0n’t_E^t_Gr4NDmA_734252}


Sticks and Stones

Points: 50

Description: may break my bones but words could never hurt me

Attachments:

The attachments contains a lot of different flags, all with random words, such as rtcp{swiftpicked} and rtcp{jointuressabductedmalaxed}. But all these flags do not adhere to the standard flag format, in other words they don’t have an underscore. Doing a quick find in the document for underscores instantly reveals the flag.

Flag: rtcp{w0Rd5_HuRt_,_d0n’T_Bu11y_,_k1Dz}


Types of Rice and Cookies, Because Those Definitely Go Together Well

Points: 100

Description: It’s important to know all the different kinds of rice. After all, what kind of cook would Delphine be if she couldn’t identify the different types? But GIANt needs to learn too. So Delphine is having him research different kinds of cookies. She wants him to find the cookie that help websites remember her information and settings when she visit them in the future. Creepy? Yes. Important? Also yes.

The cookies the description is referring to are persistent cookies.

Flag: rtcp{persistent_cookies}


ghost-in-the-system

Points: 1500

Description: I think my ls is being haunted… the colors are all weird!!! What’s that? It’s highlighting things?! Where!!?

Hints:

Attachments:

This challenge was pretty cool. It gives you a new ls binary that not only displays all the files in the directory, but also adds some color to them. If a filename is 100 characters long, like the hint said, it will display the name a bit differently and show how many characters are in the correct place.

ghost-in-the-system1.png

As you can see a flag with only w’s has 8 correct characters. You could easily bruteforce this, but I went in the other direction and tried to reverse engineer it. I used radare2 and decompiled using the pdd command.

ghost-in-the-system2.png

Here you can see a really long string of what seems like random characters. After that the index operator [] is used a 100 times, so it probably builds the correct flag and uses it to check against the filenames. If we collect all the index offsets, for example 0x1f0 and 0x192 in the screenshot, and use those to access the string we can build the flag ourselves. This is easily done using Python and will give you the flag.

Flag: rtcp{wh37h3r_1n4n1m473_f16ur35_0r_un4u7h0r1z3d_c0d3_7h3r35_4lw4y5_4_6h057_1n_7h3_5y573m_1056_726_00}


Web


Robots. Yeah, I know, pretty obvious.

Points: 25

Description: So, we know that Delphine is a cook. A wonderful one, at that. But did you know that GIANt used to make robots? Yeah, GIANt robots.

The mentioning of robots made me think of checking out /robots.txt. In /robots.txt there are only two paths disallowed: /flag and /robot-nurses. /flag is a rick-roll and /robot-nurses prompts you with the flag.

Flag: rtcp{r0b0t5_4r3_g01ng_t0_t4k3_0v3r_4nd_w3_4r3_s0_scr3w3d}


No Sleep

Points: 100

Description: Jess doesn’t get enough sleep, since he’s such a gamer so in this challenge, you’ll be staying up with him until 4:00 in the morning :D on a Monday! Let’s go, gamers!

Hints:

Going to the link reveals a countdown with, in my case, only 6000 years and a few hours left to go. I assume that the flag will be given once the time runs out. Using the Firefox debugger I looked at my cookies and one of them seems interesting. The cookie is called gamerfuel and has a value of Jan 27, 8020 04:20:00, which is exactly when the countdown would end. By changing the value of the cookie to right now, the countdown ends and the flag is revealed.

Flag: rtcp{w0w_d1d_u_st4y_up?}


Phishing for Flags

Points: 105

Description: I got a bunch of emails from people across the galaxy… some are more interesting than others.

Attachments:

Downloading and extracting the Emails.zip attachment gives you a few .eml files, each containing an email. The only thing you have to do is skim through each email, looking for something interesting. The GIVE ME BACK MY EYEHOLES.eml email contains a link to riceteacatpanda.wtf/phishingemail which immediately prompts you with the flag.

Flag: rtcp{r34d_b3f0rE_yOU_C1iCk}


Uwu?

Points: 125

Description: ᵘʷᵘ oh no ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ hecc sorry guys ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ sorry im dropping ᵘʷᵘ my uwus all over the ᵘʷᵘ place ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ oh no I lost one ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ᵘʷᵘ ah, Jake, you idiot

Hints:

Yeah. Alright then. Visiting the link reveals a page full of different kinds of UwU’s before quickly redirecting to a next page. This explains the second hint, since faster internet won’t give you any time to inspect every page. You can use BurpSuite or the network tab of the Firefox debugger to see the chain of redirects and the contents of every page. The chain goes from /uwu to /omgmeow to /pandaaaaaaa to /you-better-wash-your-rice to /footprint and finally to /uwustorage. I used the Python requests and BeautifulSoup library to write a simple script that retrieves the pages’ content and filters all the different UwU’s.

uwus = ['ᵘʷᵘ'. 'uwu', 'uWu', 'UWU', 'UʷU', 'ᵘWᵘ', 'Uwu', 'uwU']
urls = ['https://riceteacatpanda.wtf/uwu',
        'https://riceteacatpanda.wtf/omgmeow',
        'https://riceteacatpanda.wtf/pandaaaaaaa',
        'https://riceteacatpanda.wtf/you-better-wash-your-rice',
        'https://riceteacatpanda.wtf/footprint',
        'https://riceteacatpanda.wtf/uwustorage']
for url in urls:
    res = requests.get(url)
    soup = BeautifulSoup(res.text, features='html5lib')
    words = soup.find('div', attrs={'class':'container'}).findNext('p').getText().split(' ')
    for word in words:
        if not word in uwus:
            print(word + ' ', end='')

This reveals a story about a Rice Goddess and a person who didn’t wash their rice. Oh, and the flag as well.

Flag: rtcp{uwu_,_1_f0und_y0u}


What’s in The Box?!

Points: 200

Description: Button that executes some JavaScript code that spawns a moving cat gif on your screen.

After copying the JavaScript code of the button you’ll see that it’s quite unreadable. Just put it into a JavaScript beautifier and you can see the flag broken into multiple comments on multiple lines.

Flag: rtcp{k4w41I_kiT3nz_4_tH3_w1N!!_41232345}


Web Invaders

Points: 250

Description: iFrame to a Github.io page with a Space Invaders game.

Playing the game is rather difficult and winning is quite impossible, so we have to find another way to get the flag. The iFrame leads to jef1056.github.io/, so lets check out the repositories of jef1056 on Github. In the repository of this particular Github.io page, here, we find the WebInvaders game files. After downloading and inspecting all the files I find that game.ardc0 seems the most interesting, as it is a data file. We can use the strings command to read all human-readable strings from a file:

$ strings game.arcd0 > out

This writes the strings output to a file called out where we can then find the flag.

Flag: rtcp{web_h^ck3r_0004212}


growls at the chicken

Points: 1000

Description: grrrrrrR. big chicken, i hisS At you!!!

Hints:

Follow the Github link to the challenges in the introduction for the hint strings. In the description we can see that only the letter R, S and A are uppercase, plus the three hint strings are in Base64, so this screams RSA. RSA is an asymmetric public-key cryptosystem. It uses pairs of public and private keys, where the private key is usually a lot larger than the public (like in this case). The public and private key are chosen such that something encrypted using one of the keys, can only be decrypted using the other one. The generated private key is kept by one person, while that person then distributes the public key so other people can encrypt messages using this public key, and only the original person with the private key can decrypt and read these messages. In our case we already have an encrypted message, a public and a private key. We therefore only have to decrypt the message with the private key, the public key is not needed. There are websites that can do this decryption, but let’s write a small Python script to do it for us. This can easily be done using the rsa library.

with open('private_key', mode='rb') as f:
    private_key = rsa.PrivateKey.load_pkcs1(f.read())
with open('message', mode='rb') as f:
    message = base64.b64decode(f.read())
print(rsa.decrypt(message, private_key))

This script takes the message, reads the private_key file and creates an RSA private key, uses the base64 library to decode the string to a byte array and then decrypts and prints the message. The message is an address to unknown-123-246-470-726.herokuapp.com. Visiting this link shows a blank page and one single gif, but inspecting the page’s source reveals two hidden paragraph tags. One contains 9 20 30 15 16 5 14 19 30 27 29 8 20 13 12 28 and the other one "abcdefghijklmnopqrstuvwxyz[]. ". Using the numbers as index on the given characters reveals another message: it opens [.html]. This refers to the drawer in the gif and visiting the page /drawer.html leads to a page with the same gif but another hidden paragraph containing the flag.

Flag: rtcp{ch1ck3n_4nd_th3_3gg}


Forensics


BTS-Crazed

Points: 75

Description: My friend made this cool remix, and it’s pretty good, but everyone says there’s a deeper meaning in the music. To be honest, I can’t really tell - the second drop’s 808s are just too epic.

Attachments:

The flag is hidden in the file. All you have to do is run this command: strings Save\ Me.mp3 | grep rtcp, and it will give flag.

Flag: rtcp{j^cks0n_3ats_r1c3}


Allergic College Application

Points: 100

Description: I was writing my common app essay in Mandarin when my cat got on my lap and sneezed. Being allergic, I sneezed with him, and when I blew my nose into a tissue, the text for my essay turned really weird! Get out, Bad Kitty!

Attachments:

The attachment shows a text with strange characters and a lot of UTF-8 question marks, in other words they are not valid UTF-8. As the description said, the text is in Mandarin, so let’s reopen the file using a Chinese encoding like GB-2312. This results in the flag.

Flag: rtcp{我_只_修改_了_两_次}


cat-chat

Points: 125

Description: nyameowmeow nyameow nyanya meow purr nyameowmeow nyameow nyanya meow purr nyameowmeow nyanyanyanya nyameow meow purr meow nyanyanyanya nya purr nyanyanyanya nya meownyameownya meownyameow purr nyanya nyanyanya purr meowmeownya meowmeowmeow nyanya meownya meowmeownya purr meowmeowmeow meownya purr nyanyanyanya nya nyameownya nya!

Hints:

Another interesting challenge. In the #catchat channel there is a very long conversation between two bots, using this same cat language. As you can see it only uses three different words: nya, meow and purr. Purr is always alone, while nya and meow are usually combined. I thought that it was maybe binary, where nya and meow are 0 and 1 and purr is a stop token. But this wasn’t right. Another communication form that uses 2 signs is Morse code. In this case nya is a short signal or a dot, and meow is a long signal or a dash. The first word in the description therefore becomes .– which is Morse code for w. Translating the description doesn’t give you any information, but the messages in the Discord channel do. What you can do is translate rtcp to this cat language and do a search in the channel, this will give you the flag but you still have to translate it. Another way is to write a script and translate the entire chat, the flag will be in there somewhere.

Flag: rtcp{TH15_1Z_A_C4T_CH4T_N0T_A_M3M3_CH4T}


BASmati ricE 64

Points: 150

Description: There’s a flag in that bowl somewhere. Replace all zs with _ in your flag and wrap in rtcp{…}.

Attachments:

The attachment is just an image of a rice bowl, however there might be more to it. Steganography is the art of hiding secrets in arbitrary files, such as images or audio. Steghide is a tool that can hide and find these kind of files. Using this tool we can look for hidden files in the rice-bowl.jpg. There is indeed a hidden text file which we can extract. The content of this file looks like random characters, because there’s still another step. In the title of the challenge, you can see that only B, A, S and E are capitalized, so this hints at Base64. When trying to convert the file to Base64, it is important to notice that the file is not encoded with UTF-8, but instead with the Cyrillic encoding KOI8-R.

with open('steghide_extracted.txt', 'r', encoding='KOI8-R') as f:
    data = f.read()
print(base64.b64encode(data.encode('KOI8-R')))

This will print s0m3t1m35zth1ng5zAr3z3nc0D3d so all that’s left is to replace the z’s with _’s to get the flag.

Flag: rtcp{s0m3t1m35_th1ng5_Ar3_3nc0D3d}


Rice Goddess


Wrath of the Rice Goddess

Points: 4000

Description: So, uh, you see, when you wetuwnyed my uwu back to me, the wice goddess got a bit angwy - nyow she has a giant panda weady to sit on my uwu stowage… can you tawk to it? >w< - Quest: Talk to the giant panda on discord.

Hints:

Attachments:

So at first the pandaspeak_encoder.py was not part of the attachments and people had to figure it out themselves, which resulted in no solves. The organizers then added this Python script so it became easier to solve. The Giant Panda on Discord is a bot that replies something unreadable every time. The goal is therefore to write our own decoder for pandaspeak so we can talk with the Giant Panda. After looking at pandaspeak_encoder.py we can see that it uses Fernet, which is a symmetric encryption algorithm that uses one key. The key is the other attachments, dontbeconcerned.whatsoever, but you might have noticed that it’s reversed Base64, because it starts with an equals sign. If we reverse it, we can use it as the key and encode English to pandaspeak. In order to write a decoder, we have to reverse this encoding process.

from cryptography.fernet import Fernet
class BytesIntEncoder:
    @staticmethod
    def encode(b: bytes) -> int:
        return int.from_bytes(b, byteorder='big')
    @staticmethod
    def decode(i: int) -> bytes:
        return i.to_bytes(((i.bit_length() + 7) // 8), byteorder='big')

with open('pandaspeak.key', 'rb') as f:
    key = f.read()[::-1]
while True:
    f = Fernet(key)
    buffer_dec = input('Message to decode: ').split(' ')
    response_dec = ''
    for segment in buffer_dec:
        response_dec += segment[2:-2]
    decoded = ''
    for c in response_dec:
        decoded += str(ord(c) - 97)
    decoded = BytesIntEncoder.decode(int(decoded))
    decoded0 = f.decrypt(decoded).decode('utf-8')
    print(f'\n{decoded0}\n')

At first I tried to encode ‘I love rice, tea, cats, and pandas’ to pandaspeak and send this to the Giant Panda, but he won’t reply anything interesting. The points is to talk English to him and decode what he says. He will reply with ‘especially pandas’ in pandaspeak, so we have to decode this message and reply the same message in English. After a few more message he will give you the flag.

Flag: rtcp{pand4z_just_w4nt_cudd13z_fr0m_y0u!}


An Offering of Peace

Points: 5000

Description: in narrator voice
The sun was nearing the horizon line - the sky burned red with a fiery spirit. The rice goddess was upon them. Jake and Lulu (I just named them, ok), having appeased the giant panda, thought that they were safe. But It was too soon to rest.
As dawn broke, The Rice Goddess (not the holy one, the normal rice goddess) brought an army of owos, prepared to burn down the uwustorage without hesitation. The giant panda nibbled on the single grain of rice as the owos surrounded our two young’uns. Lulu got up to help defend the uwustorage, but Jake up his hand up to stop her. “You’re too sick to fight this one”. He stepped outside the uwustorage. Jake’s cat meowed. Jake himself snorted. (don’t ask why).
The rice goddess demanded that a sorrel - one that she is very sure is a sorrel - to be made as a sacrifice. She handed them a special uwu to aid them. “This shall be the only uwu thy may use”, she declared. The goddess reclined into a golden throne just outside the storage. Jake and Lulu were not prepared for this. They couldn’t leave the uwustorage, after all. Lulu wondered… how exactly she got herself into this situation - or if she would even make it out alive. A trickle of blue light escaped from her hand, which she quickly covered, without Jake’s notice. He couldn’t know that her sickness was getting worse.
what will happen to Jake and Lulu? It’s up to you to decide
DM the Rice Goddess on discord with your sacrifice.

Hints:

Attachments:

The Rice Goddess is another bot on the RTCP Discord. She will reply with ‘list index out of range’ if you send her anything that’s not an image. She will reply with ‘glares angrily. That’s a velvet, but I’m only 23.28% sure of it’ if you send her the provided UWU.png, and she will reply with ‘I never gave you whatever that is!! TAKE IT BACK EW’ if you send her any other image. So according to the hint, the bot uses Inception v3 which is a convolutional neural network for image classifications, trained on images from ImageNet. This is why the bot says that it’s 23.28% sure that the image is a velvet.

The description says that the Rice Goddess demands a sorrel, which is a type of plant. But we can only use the special uwu that she has given us, the UWU.png. Even though we have to use the same image, the first hint states that she is kind of blind, so if we slightly change the image she might not notice. And indeed, if I change only a few pixels of the original image, she is 22.03% sure that the image is a comic book. The goal is to change the image slightly, such that it looks visually the same, but the neural network will classify it as a sorrel.

I searched on Google for articles on how to trick a neural network such as Inception v3 and I found this article that shows how to trick Inception v3 into thinking a given image is whatever you want. You only have to install Tensorflow and Keras for Python, which are machine learning libraries and include the Inception v3 model. This process can take quite long if you only use your CPU (hence hint number 2) so you might want to install Tensorflow with GPU support. This requires you to install CUDA and cuDNN as well. Make sure you get the compatible versions or it won’t work.

Next, we have to find the ImageNet node ID of a sorrel, which can be found here and the ID is 339. You can use the Python code from the article or write something similar. Change the ID of the code to the sorrel ID and change the cost variable such that it will go up to at least 95% (which is what the Rice Goddess wants).

Depending on your system it will take some time, but in the end you should have the hacked image that looks exactly the same to us, but not to Inception v3. Sacrifice your modified UWU.png to the Rice Goddess, let her conclude it’s a sorrel and she will reward you with the flag.

Flag: rtcp{th3_h01y_r1c3_g0dd355_h^z_b13553d_y0u_23426342}