There’s this cool new forward compatible ISA. I created an online emulator so that you can try it out!
Category: pwn
Solver: t0b1
Flag: GPNCTF{Ar3_y0u_Re4dy_for_th3_re4l_Chal1eng3?_ee9d22353e82}
Writeup
In this challenge, we are provided with a Dockerfile
, an app.py
, a forw
binary and an instruction_list.csv
.
It is primarily a warm-up challenge to play with the ForwardCom ecosystem.
Overview
We first look at the Dockerfile
to find out more about the setup of the challenge:
- It downloads
https://github.com/ForwardCom/bintools/archive/779c06891cba05a97a214a23b7a63aeff25d983a.tar.gz
and builds the binaries viamake -f forw.make
. This is where theforw
binary andinstruction_list.csv
seem to come from. - It places the flag at
/flag
, so we need to read that. - It runs the
app.py
script withflask
, so this is what we can interact with.
Because the app.py
is what we interact with, we check this one out next.
It provides an upload form and executes the upload_file
function once we submit a file:
@app.route("/upload", methods=["POST"])
def upload_file():
if "file" not in request.files:
return redirect(url_for("upload_form"))
file = request.files["file"]
file.save("/tmp/binary.ex")
data = subprocess.check_output(["/app/forw", "-emu", "/tmp/binary.ex"])
return data[-500:]
It saves the program to /tmp/binary.ex
and uses it to run /app/forw -emu /tmp/binary.ex
.
So what is that forw
binary doing? Enter ForwardCom.
ForwardCom ISA
According to the official website https://www.forwardcom.info/, ForwardCom is an experimental instruction set architecture (ISA) and wants to be more efficient than existing systems such as x86 and ARM.
There is the ForwardCom Manual which describes the ISA in detail. Amongst many other things it defines how the actual CPU instructions are designed and how the syntax of the assembly language looks like.
The bintools
repository provides all the tools necessary to work with the ISA, most importantly for us an assembler, a linker, and an emulator.
Similar to that you can’t run ARM binaries on x86, you can’t run ForwardCom binaries natively, which is what the emulator is for.
The emulator is being executed when you pass the -emu
flag to the forw
executable, so that is how the file we upload is interpreted: It is a ForwardCom executable.
Building a ForwardCom executable
Since we can upload ForwardCom executables which are executed via the emulator, we’ll need to write one that prints us the flag from /flag
.
How do we start? Luckily for us, the designers of ForwardCom provide us with a range of code-examples to get a feeling for the assembly language.
Additionally, they even provide a set of libraries including a libc.li
which contains some of the C standard library functions.
Looking through the available functions we find three which we can use to get the flag:
fopen
to open a filefread
to read from a fileputs
to print a string
Following the code examples we can built a small program which executes these three functions and should print the flag:
%buffersize = 0x40
const section read ip
flag: int8 "/flag",0
mode: int8 "r",0
const end
bss section datap uninitialized
int8 buf[buffersize]
bss end
code section execute
extern _puts: function
extern _fopen: function
extern _fread: function
_main function public
// fopen(flag, mode)
int64 r0 = address([flag])
int64 r1 = address([mode])
call _fopen
// fread(buf, 1, 0x40, flag_file)
int64 r3 = r0
int64 r2 = buffersize
int64 r1 = 1
int64 r0 = address([buf])
call _fread
// puts(buf)
int r0 = address([buf])
call _puts
_main end
code end
Given this code in solve.as
, we can use the forw
binary to assemble it into an object file:
./forw -ass solve.as
Then, we need to link it with the libc library (which we use the functions of) to produce the final executable. Since the challenge doesn’t come with the libraries included, we’ll clone them locally first.
git clone https://github.com/ForwardCom/libraries.git
The repository already contains a compiled version of the libc library libc.li
so we can easily link that with our object file to produce the desired executable:
./forw -link solve.ex solve.ob libraries/libc.li
Finally, upload the solve.ex
executable and get the flag :)