This is the solution of the challenge “RISC-Y Business” given during the ph0wn 2019 CTF. The goal was to write a shellcode on RISC-V platform to dump the RAM were the flag lies.
Description
Hey, hey, here we are! Did you ever put your hands on a board with a real RISC-V MCU? No? So, this challenge is for you.
The onboard MCU is a GD32VF103CBT6 manufactured by GigaDevice, a well (not)known Chinese factory. The goal of this chip is to invade the IOT market in replacement of the STM32F103CBT6: it is pin-to-pin compatible and the memory quantities, mapping are the SAME!
So, when you’ll check the security of this fancy IOT, will you be able to run code inside and get out all it secrets? We’ll see…
The goal of this challenge is to pw0n the board by writing a shellcode and to get out the “flag” from the RAM.
As we are kind enough at ph0wn, we give you the non-stripped .elf binary running inside the MCU, the SDK to generate code, and a few RISC-V docs to accelerate the job.
How the shellcode is called:
1
2
3
4
5
6
7
8
9
uint8_tshellcode[50];.../* read 50 bytes in shellcode */...(*(void(*)())shellcode)();Theflagiscomputedatboottimeandisavailablehere:uint8_tflag[32]="ph0wn{xXxXxXxXxXxXxXxXxXxXxXxX}\0";
Refer to the 2 photos for connecting to the board and RESET. The USART setup is 115200 8N1.
PLEASE, PLEASE, PLEASE, do not open the case, the boards are fragile, 2 were broken during the development.
Good luck!
Nota: you can download some documentation and toolchain from our FTP server on 10.210.17.34.
%
%. *
@ #
&
.
%(((( #(((%
(((((((# #(((((//
(/((((((( &(((((//(
@%%(((((( ,((((((@@,
@@((((((( #((((#/@
%/(((((((((((((((((((%(
((((((((((((((((((((
((((((((((((((((((((((((((((((((((((((((((((((#
((% (((((((((((((((((((((((((((((((((((((((((
(.... .(%%%#((((((((#(((((((((((#####(*. )
,...... .... ,
(..... ........... ..... ..... )
%................. ........... .
(................................)
&........................... %
,,......................)
...%,..............*)
.........,
Send your shellcode, 50 bytes:
Shellcode received successfully!
Now, the big jump ...
GO
trap
Program has exited with code:0x38000002
The goal was to write a shellcode in RISC-V to extract the flag. Hopefully, the firmware was given and the architecture is supported by radare2. We first found a call to the put_char function:
This part of the code is printing the “GO” string. Thus the goal was to call the put_char function with the flag as a parameter. The flag string was stored at address 0x20000000
1
2
3
4
5
[0x08000d4c]> iz
[Strings]
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0 0x00004000 0x20000000 31 32 .data ascii ph0wn{xXxXxXxXxXxXxXxXxXxXxXxX}
Thanks to the given SDK we could assemble our code with the following command:
During the CTF, we had problem with the relative jump and we extract the flag byte per byte. However later we correct our shellcode and we got the following code :
b' %. * \r\n'
b' @ # \r\n'
b' & \r\n'
b' . \r\n'
b' %(((( #(((% \r\n'
b' (((((((# #(((((// \r\n'
b' (/((((((( &(((((//( \r\n'
b' @%%(((((( ,((((((@@, \r\n'
b' @@((((((( #((((#/@ \r\n'
b' %/(((((((((((((((((((%( \r\n'
b' (((((((((((((((((((( \r\n'
b' ((((((((((((((((((((((((((((((((((((((((((((((# \r\n'
b' ((% ((((((((((((((((((((((((((((((((((((((((( \r\n'
b' (.... .(%%%#((((((((#(((((((((((#####(*. ) \r\n'
b' ,...... .... , \r\n'
b' (..... ........... ..... ..... ) \r\n'
b' %................. ........... . \r\n'
b' (................................) \r\n'
b' &........................... % \r\n'
b' ,,......................) \r\n'
b' ...%,..............*) \r\n'
b' ........., \r\n'
b' \r\n'
b'Send your shellcode, 50 bytes:'
b'\n'
b'\rShellcode received successfully!\n'
b'\rNow, the big jump ...\n'
b'\r'
b'GO\r\n'
b'ph0wn{UVeJustWroteUr1stR5Code!}\x00\xc1\xb7\xa0\x1b\x98\x9c\xd4w\xf7\x16\x84\xa9g\xab\xde\x0e\xf3\xf9}\xe3\xcb)\x10T"\xd3\xb9\xfb\'\xcb\xda\xa3\x00