---
description: >-
  Shell(a.k.a sh) is a text-based interface where users can type commands to
  interact with the operating system. I'm trying to implement a shell using ISA,
  I call it ISH.
---

# ISH (1) (pwn)

This is an interesting pwn challenge because we are given a custom instruction set (known as the Bauhinia ISA). We need to understand the given instruction set and the provided assembly, before finding vulnerabilities in the code. Below is the assembly code of the vulnerable binary.

{% file src="https://243380073-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBIa0PcXGYuP6chd3J1Ry%2Fuploads%2F4eJAfOhQ5lmoDezcIb0Y%2FISH_ori.txt?alt=media&token=cf4ce116-a978-4af6-90be-c52f4a252cad" %}

The challenge description also tells us that we will get the flag just by executing the `flag1` binary in the remote host. The instruction set documentation can be found [here](https://hackmd.io/@blackb6a/bauhinia-isa) and the ISA interpreter source code can be found [here](https://github.com/blackb6a/ISA-Engine).

To summarise, the program has several commands:

1. `help` - Shows a list of available commands
2. `ls` - Lists all available files
3. `curl` - Retrieves a file from online
4. `head` - Reads the first 500 bytes from a file to stdout.
5. `game` - Executes a binary called `game`.

Let's first look through the syscalls invoked when `curl` is used:

<pre><code><strong>MOV R8, 0;
</strong>SYSCALL; &#x3C;- read 0x64 bytes into buffer as the input to curl after https:// at address 0xffffff08
...
MOV R8, 6;
SYSCALL; &#x3C;- actually downloads the file as `downloaded_file`
</code></pre>

1. We use a read syscall with R8 set to 0, and with R1 set to `0xffffff08` and R2 set to `0x64`. This means we read up to `0x64` bytes into `0xffffff08`. On inspecting the memory we observer that at `0xffffff00` is the string `https://`, which prefixes the URL we provide.
2. Then, we use a download syscall with R8 set to 6, with R2 set to `0xffffff00` and R1 set to `0xfffffef0`. R2 is the start of the URL we just entered, and R1 is a pointer to the string "downloaded\_file". This causes the file to be downloaded with the name "downloaded\_file".

Now we inspect the syscalls when `game` is called:

```
MOV R8, 5;
SYSCALL; <- execute ./game
```

We use the exec syscall wherein R8 is set to 5. In the exec syscall, R1 should point to the filename to be executed. Notice that R1 is `0xffffff64`, which is a pointer to the string "game".

Here we notice a problem: In the `curl` command, `0x64` bytes are written to `0xffffff08`. In the `game` command, the string "game" is at `0xffffff64`. This means that if our URL sent is too long (exceeds `0x5c` bytes), we overflow the `game` string and can overwrite up to 8 bytes.

Therefore the solution is to call the `curl` command, then input some valid URL. Then, add null bytes (`0x00`) until we reach `0xffffff64`. Then, overwrite the `game` string with the string `flag1`. After sending this payload, when we use the `game` command, the `flag1` binary will be executed.

Below is an example of how I generated the hex payload to `curl` using Python:

```
pl = b'file.io/bV6LUgd9sMWH'.hex()
pl += (0x5c - len(pl) // 2) * '00'
pl += b'flag1'.hex()
```
