write-ups and what not

Time Challenge


Opening the challenge brings you to:

time home

which reads the following:

I think someone stole the eggs here.
They were pretty messy. Leaving these crumbs everywhere.
I gathered them for you to compare adventurer. Go forth. Hydaelyn awaits for you valiant success
in uncovering the secrets of these "eggs" that have spawned on the Second Umbral Moon of our time.

Urianger's Notes:

These cryptic messages seem to have some similarities. Perhaps the same key was used?
Although it is naught but a guess of mine, pray do help in figuring it out.

Message 1: 83d7f7966225c71b556cfd1fa28aa1cb364903c74bfad82400a5b8326ebf110cf610Q
Message 2: 8380cb903366dd4b7822ba48a9dacf8b6b4b6aa81df1f14b46afd4736ae9111ee2


We are given two ciphertexts with lengths 68 and 66 (as hex characters) respectively. Since it has different lengths, I dropped the assumption that it was encrypted using a block cipher which also removes substitution-permutation. Also with the limited given, it doesn’t seem to involve assymetric cryptography and based on the randomness of each character byte, it doesn’t look like a direct substitution either.

What was said, however, was that the same key was perhaps used to encrypt both ciphertexts and the arbitrary lengths led me to believe that the plaintext was hidden using a repeated XOR key or maybe a One Time Pad which coincides well with the challenge theme.

Other things:

  • There is a Q character at the end of Message1 but I found it quite irrelevant.

  • I couldn’t find a cipher that ends with a Q.

  • Counting it with the ciphertext brings the length to an odd number so I dropped it.


If this is ineed a One Time Pad and the key was reused for both ciphertexts, then it may be decrypted via a Crib Dragging attack.

Crib Dragging

It is where you decrypt a ciphertext by XORing a known portion of the plaintext then shifting it right until another likely plaintext string is revealed.

With One Time Pads,The ciphertext (\(Ciphertext_n\)) is produced by XORing (\(\oplus\)) the plaintext (\(Message_n\)) and the key (\(K\)) where the key and plaintext has the same length.

  1. \(Ciphertext_1 = Message_1 \oplus K\)

  2. \(Ciphertext_2 = Message_2 \oplus K\)

How does this help with the attack?

Consider this:

  1. \(Ciphertext_1 \oplus Ciphertext_2\)

By substituting values, we get:

  1. \((Message_1 \oplus K) \oplus (Message_2 \oplus K)\)

And since the key (\(K\)) is reused for both messages:

  1. \((Message_1 \oplus K) \oplus (Message_2 \oplus K) = Message_1 \oplus Message_2\)

So if:

  1. \(Ciphertext_1 \oplus Ciphertext_2 = (Message_1 \oplus K) \oplus (Message_2 \oplus K)\)


  1. \(Ciphertext_1 \oplus Ciphertext_2 = Message_1 \oplus Message_2\)

Which also means that:

  1. \((Ciphertext_1 \oplus Ciphertext_2) \oplus Message_1 = Message_2\)

Which is the general idea of the crib dragging attack.


Finding the value of \(Ciphertext_1 \oplus Ciphertext_2\):

XOR 8380cb903366dd4b7822ba48a9dacf8b6b4b6aa81df1f14b46afd4736ae9111ee2

Now, we guess a portion of the plaintext then encode it in hex. It is advisable to use simple words first but to each their own:

easter => 656173746572

Then, XOR it with the value from \(Ciphertext_1 \oplus Ciphertext_2\):

XOR 656173746572 (easter)
    65364f723431 (e6Or41)

But the value returned is gibberish, so then we shift the XOR to the right:

XOR       656173746572 (easter)
          6330306e355f (c00n5_)

Shifting three bytes to the right returns c00n5_ which looks like a portion of the flag. Now, trying the flag format, rc_easter{ which fits well with the shift returns:

XOR 72635f6561737465727b (rc_easter{)
    7234636330306e355f35 (r4cc00n5_5)

We get the word, r4cc00n5, in 1337 speak followed by what seems to be a word that starts with 5 (letter S). According to the challenge, eggs were stolen and the image references to an evil plotting raccoon meme which made me try to guess the string one word at a time along the lines of the raccoons stole the eggs

XOR 7234636330306e355f3574306c335f346c6c5f30665f793075725f336767352121 (r4cc00n5_5t0l3_4ll_0f_y0ur_3gg5!!)
    72635f6561737465727b336767633174316e365f3054505f337833726331353335 (rc_easter{3ggc1t1n6_0TP_3x3rc1535)

To my surprise, the flag was revealed.

Since Message1 is longer by 1 character than Message2, that missing character must be } to complete the flag.

FLAG : rc_easter{3ggc1t1n6_0TP_3x3rc1535}