FCSC 2022
The challenge starts here: https://france-cybersecurity-challenge.fr/
We need to find the flag on the website.
The source code gave:
- https://france-cybersecurity-challenge.fr/teasing
- an image called “stegano.png”
Steganography
interesting links for this part:
The png image is interesting:
Do you see the small white dots on the top of the letters “CE CYBERSECU”?
After editing with Gimp we got:
Now let’s follow the checklist:
check type
file stegano.png
stegano.png: PNG image data, 2048 x 1968, 8-bit/color RGB, non-interlaced
Nothing interesting here
check strings
strings -n 17 -t x stegano.png
43 https://www.youtube.com/watch?v=dQw4w9WgXcQ
oh oh !
Or… No. Nothing interesting…
check exif. Nothing interesting in the exif
binwalk
binwalk -Me stegano.png
We got 2 files: an empty
7B
and7B.zlib
. These are png data. Nothing special here.
Now, let’s focus on the image.
With a bit of manual work, we can decode the content:
So next step is here: https://france-cybersecurity-challenge.fr/bpbcmrplfgzmztgggpbc. On this page, we got an executable for TI-83+.
TI-83+ program analysis
file fcsc.8xp
fcsc.8xp: TI-83+ Graphing Calculator (assembly program)
Wow! This brings back memories!
Documentation will be useful: http://lpg.ticalc.org/prj_tilem/doc/user_manual.pdf. Also a small Z-80 tuto
Interesting stuff found with TilEm:
- in memory, program starts at 9D76
- the conditional jump that lead to the piece of code displaying the flag is at address 9D95
- when hacking some CALL to execute this code we get:
So the flag is dynamic….
Guess it’s time to go with more powerful tools like Ghidra to understand what’s going on.
8xp analysis
After some Google search, we found that a 8xp file is structured like this:
Packet
|
| Header
| | 0 8 **TI83F*
| | 8 3 $1A $0A $00
| | 11 42 Comment - padded with zeros or spaces.
| | 53 2 Length of data section. Should be equal to filesize - 57
| End Header
|
| Data
| | 55 2 Always has a value of $0B or $0D? (prefer $0B?)
| | 57 2 Length of Variable Data Section
| | 59 1 Variable type ID ($05 for programs)
| | 60 8 Variable name (padded with zeros)
| | 68 1 Version (??), usually $00. (Present if byte 55 == $0D)
| | 69 1 Archive flag. $80 archived, $00 if not. (Present if byte 55 == $0D)
| | 70 2 Length of Variable Data Section (repeat of bytes @ 57)
| |
| | Variable Data
| | | 72 2 Length of Actual Data - 2
| | | 74 n Actual Data
| | End Variable Data
| |
| End Data
|
| 74 + n 2 Checksum (sum of Data section)
|
End Packet
with a small python script we can extract the code.
import struct
xp8_file = "~/workspace/CTF/FCSC_2022/fcsc.8xp"
with open(xp8_file, "rb") as f:
# Header
print("Header:", f.read(11))
print("Comment:", f.read(42))
data_section_length = f.read(2)
print("Length of the Data Section", data_section_length, int.from_bytes(data_section_length, "little")+57)
# Data
print("Random Stuff", f.read(1).hex(), f.read(1).hex())
print("Length of Variable Data Section", int.from_bytes(f.read(2), "little"))
print("Variable type ID", f.read(1).hex())
print("Variable name", f.read(8))
print("Version", f.read(1))
print("Archive flag", f.read(1))
print("Length of Variable Data Section", int.from_bytes(f.read(2), "little"))
data_length = int.from_bytes(f.read(2), "little")
print("Length of Length of Actual Data - 2:", data_length)
f.read(2) # remove 2 useless bytes
data = f.read(data_length)
edited_xp8_file = "~/workspace/CTF/FCSC_2022/fcsc_edited.8xp"
with open(edited_xp8_file, "wb") as f:
f.write(data)
Now we can load it in Ghidra, specifying that this is Z80 asm with a Base Address of 9D95.
The analysis took… a lot of time. The important parts are:
- functions at address 9DE0 and 9DA2 are validating the 32 input characters
- for each correct char, the function at address 9F78 is called
- Setting a breakpoint for instance at address 9F78 and looking at the first address in the stack will be a way to know which characters are correct.
After testing inputs full of 0, 1, … 9, A, B, … F we can find the flag:
FCSC{4B8CB9E0ADB7F2B3BA4E6CB7156F1243}
Other things learned
- we can enter wifi password in wireshark https://wiki.wireshark.org/HowToDecrypt802.11
- Custom header
curl -vvv -H "X-FCSC-2022: Can I get a flag, please?" https://header.france-cybersecurity-challenge.fr/
- https://www.dcode.fr/vigenere-cipher