Tuesday, February 7, 2017

AlexCTF 2017 - Crypto


CR1: Ultracoded (50)


Starting out with a very simple one, here's the description:

Fady didn't understand well the difference between encryption and encoding, so instead of encrypting some secret message to pass to his friend, he encoded it!
Hint: Fady's encoding doens't handly any special character

Initially we're given a file (named zero_one) with a bunch of spelled-out bits:

...ZERO ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ONE ONE ZERO ONE ZERO ZERO ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ZERO ZERO ONE ONE ZERO ZERO ONE ONE ONE ZERO ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ONE ONE ZERO ONE ZERO ZERO ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ZERO ZERO ONE ONE ONE ZERO ONE ZERO ONE ZERO ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ONE ONE ZERO ONE ZERO ZERO ONE ZERO ONE ZERO ZERO ZERO ZERO ZERO ONE ZERO ONE ONE ONE ZERO ONE ZERO ONE ZERO ONE ZERO ZERO ONE ZERO ZERO ONE ZERO ONE ZERO ZERO ZERO ZERO ONE ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ZERO ZERO ONE ONE ONE ZERO ONE ZERO ONE ZERO ONE ZERO ZERO ONE ONE ZERO ZERO ZERO ONE ONE ZERO ONE ZERO ZERO ONE ZERO ZERO...

First thing to do in this situation is to use a bit of sed to convert them all to their original form:

$ cat zero_one | sed 's/ //g;s/ZERO/0/g;s/ONE/1/g;'

0100110001101001001100000110011101001100011010010011000001110101010011000110100101000001011101010100100101000011001100000111010101001100011010010011000001100111010011000101001100110100011101000100110001101001010000010111010001001001010000110011010001110101010011000101001100110100011001110100110001010011010000010111010101001100011010010011010001110101010010010100001100110100011101000100110001010011001100000111010001001001010000110011010001110101010011000110100100110100011101010100100101000011001100000111010001001100010100110100000101110101010011000101001100110000011101000100110001010011010000010111010101001100011010010011010001100111010011000101001100110000011101000100100101000011001101000111010101001100011010010011010001110101010010010100001100110100011101010100110001010011010000010111010101001100010100110011000001110101010010010100001100110100011101010100110001101001001100000111010001001001010000110011010001110100010011000110100101000001011101000100110001010011001100000110011101001100011010010011010001110101010011000110100100110100011001110100110001101001010000010111010001001100011010010011000001110101010010010100001100110100011101000100110001101001010000010111010101001100011010010011010001110100010011000101001101000001011101000100100101000011001100000111010001001100010100110100000101110100010010010100001100110000011101010100110001101001001100000110011101001100010100010011110100111101

Next we can find what this turns into with some perl:

$ cat zero_one | sed 's/ //g;s/ZERO/0/g;s/ONE/1/g;' | perl -lpe '$_=pack"B*",$_'

Li0gLi0uLiAuIC0uLi0gLS4tLiAtIC4uLS4gLSAuLi4uIC4tLS0tIC4uLi4uIC0tLSAuLS0tLSAuLi4gLS0tIC4uLi4uIC4uLSAuLS0uIC4uLi0tIC4tLiAtLS0gLi4uLi4gLiAtLi0uIC4tLiAuLi4tLSAtIC0tLSAtIC0uLi0gLQ==

Now we have some Base64 we can decode:

$ cat zero_one | sed 's/ //g;s/ZERO/0/g;s/ONE/1/g;' | perl -lpe '$_=pack"B*",$_' | base64 -D

.- .-.. . -..- -.-. - ..-. - .... .---- ..... --- .---- ... --- ..... ..- .--. ...-- .-. --- ..... . -.-. .-. ...-- - --- - -..- -

Aaaand now we have some Morse code, which ended up being decoded using - http://morsecode.scphillips.com/translator.html
If anyone knows a good command-line tool for this, please leave a comment below! Would love to add that to the one-liner!

Using the online tool, we get this result:

ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT

It wasn't over yet, this wasn't the flag based on their flag format, but it wasn't too difficult to spot the encoding, all O characters were really underscores:

ALEXCTF{TH15_1S_5UP3R_5ECR3T_TXT}





CR2: Many time secrets (100)


Description:

This time Fady learned from his old mistake and decided to use onetime pad as his encryption technique, but he never knew why people call it one time pad!

Not sure who this Fady person is, sounds familiar... Sounds like we need to crack a poorly encrypted message with OTP issues.
Downloading the file they provide, called msg, we see it's a few lines of hex:

0529242a631234122d2b36697f13272c207f2021283a6b0c7908
2f28202a302029142c653f3c7f2a2636273e3f2d653e25217908
322921780c3a235b3c2c3f207f372e21733a3a2b37263b313012
2f6c363b2b312b1e64651b6537222e37377f2020242b6b2c2d5d
283f652c2b31661426292b653a292c372a2f20212a316b283c09
29232178373c270f682c216532263b2d3632353c2c3c2a293504
613c37373531285b3c2a72273a67212a277f373a243c20203d5d
243a202a633d205b3c2d3765342236653a2c7423202f3f652a18
2239373d6f740a1e3c651f207f2c212a247f3d2e65262430791c
263e203d63232f0f20653f207f332065262c3168313722367918
2f2f372133202f142665212637222220733e383f2426386b

Looking up common techniques for cracking OTP we can find the Many Time Pad Attack / the Crib Dragging technique - http://crypto.stackexchange.com/questions/59/taking-advantage-of-one-time-pad-key-reuse

There's a very nice python library for crib dragging here - https://github.com/SpiderLabs/cribdrag

This allows us to easily read in msg file and start the process of discovery. First we need the messages on one line:

$ cat msg | tr -d '\n'; echo

0529242a631234122d2b36697f13272c207f2021283a6b0c79082f28202a302029142c653f3c7f2a2636273e3f2d653e25217908322921780c3a235b3c2c3f207f372e21733a3a2b37263b3130122f6c363b2b312b1e64651b6537222e37377f2020242b6b2c2d5d283f652c2b31661426292b653a292c372a2f20212a316b283c0929232178373c270f682c216532263b2d3632353c2c3c2a293504613c37373531285b3c2a72273a67212a277f373a243c20203d5d243a202a633d205b3c2d3765342236653a2c7423202f3f652a182239373d6f740a1e3c651f207f2c212a247f3d2e65262430791c263e203d63232f0f20653f207f332065262c31683137223679182f2f372133202f142665212637222220733e383f2426386b

Then we pass this in as the first argument to the cribdrag.py tool, initially we have a blank canvas:

./cribdrag/cribdrag.py 0529242a631234122d2b36697f13272c207f2021283a6b0c79082f28202a302029142c653f3c7f2a2636273e3f2d653e25217908322921780c3a235b3c2c3f207f372e21733a3a2b37263b3130122f6c363b2b312b1e64651b6537222e37377f2020242b6b2c2d5d283f652c2b31661426292b653a292c372a2f20212a316b283c0929232178373c270f682c216532263b2d3632353c2c3c2a293504613c37373531285b3c2a72273a67212a277f373a243c20203d5d243a202a633d205b3c2d3765342236653a2c7423202f3f652a182239373d6f740a1e3c651f207f2c212a247f3d2e65262430791c263e203d63232f0f20653f207f332065262c31683137223679182f2f372133202f142665212637222220733e383f2426386b

Your message is currently:
0       ________________________________________
40      ________________________________________
80      ________________________________________
120     ________________________________________
160     ________________________________________
200     ________________________________________
240     ________________________________________
280     ____
Your key is currently:
0       ________________________________________
40      ________________________________________
80      ________________________________________
120     ________________________________________
160     ________________________________________
200     ________________________________________
240     ________________________________________
280     ____
Please enter your crib:

Now we know that the flag will be in the format ALEXCTF{...}, so we can start with that:

Please enter your crib: ALEXCTF{
*** 0: "Dear Fri"
1: "hho;Q`TV"
2: "ef&JwFkP"
3: "k/WlQymM"
4: ""^qJnp"
5: "SxWuhb/"
6: "u^hsu=9h"
7: "Sann*+U\"
...

Many examples were dropped (276), and a few of them were intelligible. The first one looked like a good candidate, starting with 0, we identify it as a 'message'.

Enter the correct position, 'none' for no match, or 'end' to quit: 0
Is this crib part of the message or key? Please enter 'message' or 'key': message
Your message is currently:
0       ALEXCTF{________________________________
40      ________________________________________
80      ________________________________________
120     ________________________________________
160     ________________________________________
200     ________________________________________
240     ________________________________________
280     ____
Your key is currently:
0       Dear Fri________________________________
40      ________________________________________
80      ________________________________________
120     ________________________________________
160     ________________________________________
200     ________________________________________
240     ________________________________________
280     ____
Please enter your crib:

"Dear Friend," makes the most sense in the clue we have, so going with that we can find more information:

Please enter your crib: Dear Friend,
0: "ALEXCTF{HERE"

This time 0 is the key, next we can guess underscore is after 'HERE' in the flag from the normal flag format. Continuing this process onwards will fill in the full flag:

Please enter your crib: ALEXCTF{HERE_
*** 260: "ncryption sch"
Enter the correct position, 'none' for no match, or 'end' to quit: 260
Is this crib part of the message or key? Please enter 'message' or 'key': message
Please enter your crib: encryption scheme
259: "}ALEXCTF{HERE_GOE"
Enter the correct position, 'none' for no match, or 'end' to quit: 259
Is this crib part of the message or key? Please enter 'message' or 'key': key
Please enter your crib: }ALEXCTF{HERE_GOES_
*** 207: "ecure, Let Me know "
Enter the correct position, 'none' for no match, or 'end' to quit: 207
Is this crib part of the message or key? Please enter 'message' or 'key': message
Please enter your crib: }ALEXCTF{HERE_GOES_
*** 233: "agree with me to us"
Enter the correct position, 'none' for no match, or 'end' to quit: 233
Is this crib part of the message or key? Please enter 'message' or 'key': message
Please enter your crib: agree with me to use this encryption scheme
233: "}ALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOE"


Enter the correct position, 'none' for no match, or 'end' to quit: 233
Is this crib part of the message or key? Please enter 'message' or 'key': key
Your message is currently:
0       ALEXCTF{HERE____________________________
40      ________________________________________
80      ________________________________________
120     ________________________________________
160     ________________________________________
200     _______}ALEXCTF{HERE_GOES________}ALEXCT
240     F{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOE____
280     ____
Your key is currently:
0       Dear Friend,____________________________
40      ________________________________________
80      ________________________________________
120     ________________________________________
160     ________________________________________
200     _______ecure, Let Me know _______agree w
240     ith me to use this encryption scheme____
280     ____
Please enter your crib:

...

Enter the correct position, 'none' for no match, or 'end' to quit: none
No changes made.
Your message is currently:
0       ALEXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_G
40      OES_THE_KEY}ALEXCTF{HERE_GOES_THE_KEY}AL
80      EXCTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOE
120     S_THE_KEY}ALEXCTF{HERE_GOES_THE_KEY}ALEX
160     CTF{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_
200     THE_KEY}ALEXCTF{HERE_GOES_THE_KEY}ALEXCT
240     F{HERE_GOES_THE_KEY}ALEXCTF{HERE_GOES_TH
280     E_KEY
Your key is currently:
0       Dear Friend, This time I understood my m
40      istake and used One time pad encryption
80      scheme, I heard that it is the only encr
120     yption method that is mathematically pro
160     ven to be not cracked ever if the key is
200      kept secure, Let Me know if you agree w
240     ith me to use this encryption scheme alw
280     ays 

Flag:

ALEXCTF{HERE_GOES_THE_KEY}




CR4: Poor RSA (200)


Description:

This time Fady decided to go for modern cryptography implementations, He is fascinated with choosing his own prime numbers, so he picked up RSA once more. Yet he was unlucky again!

poor_rsa.tar.gz

This was a challenge where a little crypto education would've helped. Started this one off by looking up previous write-ups for RSA based challenges on a CTF. This one turned out to be great! - https://0x90r00t.com/2015/09/20/ekoparty-pre-ctf-2015-cry100-rsa-2070-write-up/

Extracting the tar.gz gave us two files, a encrypted flag and a public key:

-rw-r--r--@  1 user  staff    69B Dec 11 01:08 flag.b64
-rw-r--r--@  1 user  staff   162B Dec 11 00:59 key.pub

Walking through that writeup made this process very simple, starting off by identifying how many bits are used on the public key:

Modulus (399 bit):
    52:a9:9e:24:9e:e7:cf:3c:0c:bf:96:3a:00:96:61:
    77:2b:c9:cd:f6:e1:e3:fb:fc:6e:44:a0:7a:5e:0f:
    89:44:57:a9:f8:1c:3a:e1:32:ac:56:83:d3:5b:28:
    ba:5c:32:42:43
Exponent: 65537 (0x10001)

Looks like we also got an odd amount of bits (no pun intended).
Now we need to format the hex values to get the integer product:

openssl rsa -noout -text -inform PEM -in key.pub -pubin | grep -Evi 'mod|exp' | tr -d ':\n '

Then to get the int value, pass it into python:

$ openssl rsa -noout -text -inform PEM -in key.pub -pubin | grep -Evi 'mod|exp' | tr -d ':\n ' | xargs python -c 'import sys; print int(sys.argv[1], 16)'

833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019

Now we can query factordb for this value: http://www.factordb.com/index.php?query=833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019

We end up seeing there is a match!


This turns out to be:
863653476616376575308866344984576466644942572246900013156919 * 965445304326998194798282228842484732438457170595999523426901

Now that we have p & q, we can generate the private key using RSATool - https://github.com/ius/rsatool

$ python ./rsatool/rsatool.py -p 863653476616376575308866344984576466644942572246900013156919 -q 965445304326998194798282228842484732438457170595999523426901 -o ./priv.key

Finally we just need to decrypt the flag using openssl:

$ openssl rsautl -decrypt -in flag.raw -inkey priv.key

This drops the Flag:

ALEXCTF{SMALL_PRIMES_ARE_BAD}