Crypto Conspiracy | Part 2 | NCC CTF 2022

5 min readJul 31, 2022

In Part 2, we will cover cryptography challenges from a recent CTF organized by NED Cyber Community.

I won’t go into too much detail about the concepts and will try to explain them with as much simplicity as possible and further provide resources for learning.

1. Warmup

Description: **final_flag = flag1 + flag2 + flag3 + flag4**

The first challenge contains a downloadable text file with its content mentioned below:

flag1 = "TkNDe2NyNHB0MA=="flag2 = "_v5_wh57_t"flag3 = ". --... --... .---- -. --. ..--.- ... - ....- .-."flag4 = "-[----->+<]>++++.----.-[->++<]>.-----.+[-->+<]>++.+.+++++.+.--------.++.++++++.+[--->++<]>+."

As the description above gave us the clue that all above flags in the text file should be decoded first then concatenate together to form the final flag.

Flag 1

Flag 1 is an encoded base64 text. It can be identified by a “==” in the end. I can easily decode it from any online tool like cyberchef.

Flag1 = “NCC{cr4pt0”

You can read further about base64 here.

Flag 2

Flag 2 uses the rot13 algorithm to encode itself. Each character of the original flag replaces itself with the 13th letter after itself in the alphabet. To decode, we can use the same algorithm to undo the changes.

A script on my last post or an online tool like cyberchef can help retrieve the second part of the flag.

Flag2 = “_i5_ju57_g”

Flag 3

Flag 3 is encoded in Morse code. It’s a method to communicate. It uses combination of two different signals(“.” and “-”) to encode a character.

You can learn more about Morse code and its standardized sequence here.

Flag3 = “E771NG_ST4R”

Flag 4

Flag 4 is encoded into a programming language called brainf**k. You can read more about it here.

An online decoder can be used to decode the flag.

Flag4 = “73d_2389139}”

Now concatenating all 4 decoded flags will give us the final flag.

Final-Flag: NCC{cr4pt0_i5_ju57_gE771NG_ST4R73d_2389139}

2. XOR it!

The challenge contains a text file which contains an encryption scheme applied on the flag, which outputs an encrypted flag as bytes.

key = “supersecretkey” #encryption scheme 
encrypted_flag = ‘’.join([chr(ord(flag[i]) ^ ord(key[i])) for i in range(len(flag))])
#encoded flag

The scheme explains that the characters of the flag are mapped with the characters of the key and XORed. The numbers are then converted into their ASCII character and concatenated to form an encrypted flag.

An XOR operation can be undone using itself. In my last post, there is an example and explanation regarding reversing XOR. Further you can read from here.

A few changes in the script will get us the flag.

Executing the script:

Flag: NCC{x0r_x0r_x0r_1358293}

3. John It

As the name indicates, a tool called “John the ripper” will be used. Challenge contains a downloadable ssh private key file named “id_rsa”. The encrypted password in the file is our flag.

A file can be used to convert the key into a hash format john the ripper can use to crack. We can download the file from here.

After creating the hash file, pass it john with a wordlist to crack the hash.

Flag: NCC{dolphin}

4. Double RSA


As the name of the challenge hints that the flag is encrypted twice. It contains a downladable text file containing a cipher value(ct) and an encryption key(N,e).

n = 696935465059419660377260463353260033127610781266161396597245584268481265922459928743910075784748659902782773185447607953852521135952830216187355316734096563232166135531080658717479631077633088053778767241088355411402400311095532992867209263169235738485694855932779331342446201045636331667501748619955540498970349005902784489326236280813117194029984061732340141051416374613611416772237241790885991359051696047110765064062358690486276187958657882312308947622828553108369909409491947507045200692389495276739622385463636383676141896968620503510505406688371450035268745228733803029870398669291398503539415571430752319723864951079614608056348919306559161842593503075867692359640855416138434877280307695663894842968666289906532149843359647521601945778595610610938093355469557373934995093389639306040634137118123605956096901179717299172152152932914138781208622400424527960303298451888571651095436098663550080167226160223843695402313897083910299125627878753200008201923335127473955686079420915032700271789556713843274006433477690999598753307890260593851141204697510511700133531863299982967329980169200711632678134785620560738602555965088195486507925048547703489311042831078785775717254397218772608574738890978330277054475270932622671708238279
e = 5
ct = 213745739657102689819423391121056880788162554215277374970813691167096269953824865445253978579438234311362146350632869912409016448125463836733325340229577146591497732982417702257075622515209929705904929231432282537927808250766569189024536055071024450607823063110085423514483083336199582350048010235372750314642093596734957187354697017558843857310977912411951868183589314165942933945820159386978788524820273196640320143621048361741063278756151996077411391835917149080150689158810504141859859976317705393031162832936350141076001515675761421981682737084052781313175131948233978863923862133868041055709142126263500006202482605845984984407497851590757849258891674510571767544681404137218732270388283408741649793007652886336185119404644476896897903234734916374853422189752920028145549066393526634076034017659487693379696987917452051353959574132121394975131791126729581309885477397185260812569807653011581901845244368770048075780435144595304160036191281957449270567562542885637788416661200250992591469539766946733239241401696063353894261726864145017139543167979157531149457576194293369068723910771162230869831630712999999958503210391770306637738773901

It often happens that m(message) to be sent isn’t large enough than n after exponentiating with e. This makes the whole RSA encryption pointless as m can be retrieved easily by getting the e-th root of the ct.

mᵉ < nm = ᵉ√ct

On the other hand, if m after exponentiating with e is slightly larger than n can be easily broken by enumerating the integer multiple(k) of n, adding ct and then taking the e-th root.

mᵉ > nm = ᵉ√(k*n + ct)

This is called the Direct Root Attack.

You can read more about this attack here.

Now we can simply carve a script that takes both the possibility under consideration:

Executing the script gives us another set of RSA keys. The description above, about encrypting twice was right.

In stage2 we get these keys:


The length of n is very small. That makes guessing the prime factors easy. Factordb can be a help.

p: 17458452867168260911
q: 18114169928441428253

After this, we will generate the private key d and use it to decrypt our cipher text.

Flag: NCC{rSa_t1m3}