Published on

TFCCTF 2023 – MCTEENX

Authors
  • avatar
    Name
    Lumy
    Twitter

MCTEENX (412 points, 31 solves)

I fly in the sky, I got wings on my feet.

Table of Contents

  1. An encrypted ZIP file
  2. Solution

An encrypted ZIP file

The challenge gives us an encrypted zip file. red.zip
We can see a file named "script.sh" within the zip file.

We have to find a way to revover this file

Solution

After attempting a dictionnary based bruteforce attack that could not permit de decrypt the archive, we went in another direction.

The method to resolve this challenge is called "known partial plaintext attack"

Ressource used : github.com/kimci86/bkcrack
anter.dev/posts/plaintext-attack-zipcrypto

As we known that it is a .sh file within the encrypted archive, there is a good chance that the file begins with :

partial_script.sh

#!/bin/bash

Thus, we can recover the 3 keys that can be used to decrypt the archive :

./bkcrack -C red.zip -c script.sh -p partial_script.sh

Then we can used this command line to recover the content of the archive based on the keys previously recovered :

bkcrack -C red.zip  -c script.sh -k c0b1bc78 c3206dfc e7e5bae1 -d decipheredfile.sh

The script.sh generates an image :

#!/bin/bash

echo 'iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAC+yklEQVR4nOydd4DcxPn3PzPS7l5378bGNpgOMb333lsCCb23EAgQQkhIgVRqCB3SSAIhdEhooTj5QejVNphqcO/t6hZJz/uHpF2tVtpyPoPvXj+wvl1pyjOjma+eNjPKcUQUggAoBQLK/QcR/5r7279Y+KpwvwriX0TcMoL3lRSVVZxUufUFyvTrB+VWXZTfu+XXGUgvKJQEysJLH6qfQJ35+iPy46cS8aoukx8Q5TZKiV+/x5/y+pdQ/wZ/B/Ln+8/PX5TerdFtf7g/3G8FfgP5/fIrtD+Yv9B+75+o+sL8F42fwvgobm84fzH/Sirll9Lx47MOgf4vlC+R/Fc5fjzevCrW0ldISsR/QmtpLa2ltbRmk/6qGVhLa2ktraVqaS1graW1tJZ6Da0FrLW0ltZSr6G1gLWW1tJa6jW0FrDW0lpaS72G1gLWWlpLa6nX0FrAWktraS31GloLWGtpLX3pJN5nLdVK5lfNwFpaS/8/kA9P4jgggjYUrI2dr5nWSlhraS19CeRDU+cHH5P+/AsEvVbG6gatXZqzltbSaiLJ/+uvkQSxLdAatF4rX3WD1gLWWlpLq4F8mLIBa9YclFIk1xn1FXPV+2mtSriW1tJqIDudof2e+2k9+FiWH30cuZlzAEhPnUbni6+uVQe7SWsBqwdIRPKf1VX+mlTO/w/U3b7KLljEyit/zcp9DiN9/DHYn0xn4H1/pmHn7eiaMp0lO+xO+tln3Tp6kuH/T+j/O5Ww1uYqf4+qknLC6dxrIuLlKb4X+OWXEPpdmc9wueXKiM5fyndU+VFtiKo3WJZSKp+vcv5yvAcZDPJDTPru1LGqVLBLibthGwpof/xx0hdcivHFTFRdPfaEdWl6+p8kR49CAHvFCqwpU0nssB1GIsHaHbZqpz4LWH6z/I3ogteCk0KKho3kJ2HxhCtMxAIVD7bgZI3Kn8+ltJcmvqxiXgOpIoDQrVcX1etLe2F+onmrjdxynLK8B/mPqit4yZ3vKpSncM/7VthQUKLbEv9b8hsBBttQCxU/i+LnJihEQef1v6PzZz/DzGRIpBpJ1ydpuv8+6nfdCQAnk8bq6iTVf2AJv9U8l9peBn2X+jxgeb9wB3vwjRvcorJwtWg4KskDQnHZ0en9shTepOvGuCqWWmrP//8TrSmTd8UvfkPmR5eRaOgHDjhDBjPoL79H7b67m0CE9j/fS9PO28P6E75KVns99WnAEm87YK2//EEtAlbOxjANtId3jg1Kk0c5pcB2BMPwpALHuw84DmSzOSzLIpfN5qUopcG2bZYtW4Zl5dDawDA0tm0DmoRpopRCa41hGJimiZkwPXXVIZfNYZomdfX1IIJl22iPQRdoFdlsFjNhksvmcBzH40fyYOz+Ix6/Lu+27aC1wnEcHMdBHNBau9KYuN/RLg9aa0wzASI4toM2NGbCdHk1TLQ2MBNmnq9MJkNHRwepVBKtNUop6uvqveBL8n2Xy+YwTIP2jna6utK0tq5EBBIJE9u2cWwHcPmzbZtUqg4rl8OybcQRkqkktmWDAsMwsG0Lx3bo6uoinclg2xaZTBaFImfnSDY3019rxn7jWxgrliMJA2PYcNRtt/HZ2HWQ1jZMBPX2FBrWH8/Kln4YuOXZtk0qmUQcwREHpXV++2vb70NvO3FHBK0UOStHNpvDMAwMw6CtrY2GxgYMw0ArjW1Z3v7QwuZbfI0hQ4aunsH9FVKfBKyCEVxhGIrW1nbmzJlDe3sbM2d+wdy5c8nlLNLpNHPmzMa2HZRy1bXOzk4ymQyGoREhPwndAeyQTqfJ5QIAotwBZVsWWrtSXGdnF52dnXR0dFBXlyKVqsM0Ddrb2zEMd/

...

Using zsteg, we can see an interessting hex string :

root@e4aa87e50967:/data# zsteg -a red.png
b1,r,lsb,xy         .. text: "BGwFnCo#fFbfbcc"
b1,rgb,lsb,xy       .. text: "030a111418142c783b39380d397c0d25293324231c66220d367d3c23133c6713343e343b3931"
b2,r,msb,xy         .. text: "}}]}}u}}}u}"
b3,abgr,msb,xy      .. file: MPEG ADTS, layer I, v2, 256 kbps, Monaural
b5,abgr,lsb,xy      .. file: MPEG ADTS, layer II, v1, 384 kbps, Monaural
b6,b,msb,xy         .. file: MPEG ADTS, layer I, v2, Monaural
b6,bgr,msb,xy       .. file: MPEG ADTS, layer I, v2, 112 kbps, Monaural
b7,b,lsb,xy         .. file: , 48 kHz, Monaural
b7,bgr,lsb,xy       .. file: , 48 kHz, Monaural
b8,g,msb,xy         .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,rgb,msb,xy       .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,rgba,msb,xy      .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,abgr,msb,xy      .. file: ddis/ddif
b6,abgr,msb,xy,prime.. file: MPEG ADTS, layer I, v2, 112 kbps, Monaural
b7,abgr,lsb,xy,prime.. file: , 48 kHz, Monaural
b8,r,msb,xy,prime   .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,rgb,lsb,xy,prime .. file: AIX core file 64-bit
b8,rgb,msb,xy,prime .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,bgr,msb,xy,prime .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,rgba,msb,xy,prime.. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,abgr,lsb,xy,prime.. file: AIX core file 64-bit
b3,abgr,msb,yx      .. file: MPEG ADTS, layer I, v2, Monaural
b5,abgr,lsb,yx      .. file: MPEG ADTS, layer II, v1, 384 kbps, Monaural
b6,bgr,msb,yx       .. file: MPEG ADTS, layer I, v2, Monaural
b7,bgr,lsb,yx       .. file: , 48 kHz, Monaural
b8,rgb,msb,yx       .. file: RDI Acoustic Doppler Current Profiler (ADCP)
b8,abgr,msb,yx      .. file: ddis/ddif
b1,r,lsb,Xy         .. text: "ldfdf&lOl'f."
b1,r,msb,Xy         .. text: "fdwffff06&f&fd6"
b1,bgr,msb,Xy       .. text: "3#6C3S6C33"
b2,r,msb,Xy         .. text: "}}}}}}}}U_}_}]}}}]}}u}}_]"
b2,g,msb,Xy         .. text: "__Uw__Ww_W]w"
b2,bgr,msb,Xy       .. text: "___]}__u___w}__u_____W_"

Since we have no information about the encryption method of this hex string, we tried a XOR plaintext attack:

from pwn import *

cipherhex = "030a111418142c783b39380d397c0d25293324231c66220d367d3c23133c6713343e343b3931"
cipherbytes = bytes.fromhex(cipherhex)

plaintext = b"TFCCTF{"

print(xor(cipherbytes, plaintext)[:len(plaintext)])
└─$ python red_solve.py
[*] Checking for new versions of pwntools
    To disable this functionality, set the contents of /home/kali/.cache/.pwntools-cache-3.11/update to 'never' (old way).
    Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
        [update]
        interval=never
[*] A newer version of pwntools is available on pypi (4.9.0 --> 4.10.0).
    Update with: $ pip install -U pwntools
b'WLRWLRW'

This gave us b'WLRWLRW' and we can clearly see a repetition of the key WLR.

We use this key to decrypt:

from pwn import *

cipherhex = "030a111418142c783b39380d397c0d25293324231c66220d367d3c23133c6713343e343b3931"
cipherbytes = bytes.fromhex(cipherhex)
key = b"WLR"

plaintext = xor(cipherbytes, key)
print(plaintext)
└─$ python red_solve.py
b'TFCCTF{4int_n0_reasoN1n_a1nt_n0_fixin}'

And we get the flag

Flag : TFCCTF{4int_n0_reasoN1n_a1nt_n0_fixin}