Rating: 5.0

# BIOS

Yo, we hear you like BIOs in your BIOS so enjoy a BIOS of BIOs. Submit the part after "The Flag Is:"

BIOS is a modified SeaBIOS image.

## Solution

The first thing that pops up when inspecting the binary file in a hex editor is the "LARCHIVE" header at the beginning.
Searching through the binary, the header occurs multiple times in the file.
A bit of googeling and we find ourself on the [coreboot CBFS](https://www.coreboot.org/CBFS) wiki page.
Using coreboots [cbfstool tool](https://github.com/coreboot/coreboot/tree/master/util/cbfstool), it is possible to extract all the resources embedded in the binary:

```python
import os
import subprocess

f = open("bios-nautilus.bin", "rb")
data = f.read()
f.close()

parts = data.split(b"LARCHIVE")

for part in parts[1:]:
o = open("dump.bin" , "wb")
o.write(b"LARCHIVE"+part)
o.close()

result = subprocess.check_output("bash -c './coreboot/util/cbfstool/cbfstool dump.bin print'", shell=True)
name = result.split(b"\n")[2].split(b" ")[0].decode("utf-8")
result = subprocess.check_output("bash -c './coreboot/util/cbfstool/cbfstool dump.bin extract -f dump/"+name+" -n "+name+"'", shell=True)
print(name)
```

The following files are contained in the file, most interestingly the `flag.lzma.enc` file.

```
bootsplash.bmp.lzma
font.bmp.lzma
font.dat
fire.pal
names.txt
ENDEAVOR.bmp.lzma
ENDEAVOR.txt
FISH.bmp.lzma
FISH.txt
FUZYLL.bmp.lzma
FUZYLL.txt
HJ.bmp.lzma
HJ.txt
HOJU.bmp.lzma
HOJU.txt
ITSZN.bmp.lzma
ITSZN.txt
JETBOY.bmp.lzma
JETBOY.txt
LIGHTNING.bmp.lzma
LIGHTNING.txt
MIKE_PIZZA.bmp.lzma
MIKE_PIZZA.txt
PERRIBUS.bmp.lzma
PERRIBUS.txt
THING2.bmp.lzma
THING2.txt
THOMASWINDMILL.bmp.lzma
THOMASWINDMILL.txt
VITO.bmp.lzma
VITO.txt
flag.lzma.enc
```

Browsing through the binary after mapping it correctly, and following the strings shows some interesting code:

![](img/bios.png)

The function names can be figured out by looking at how the binary otherwise works and how [certain functions](https://github.com/coreboot/seabios/blob/master/src/romfile.c) are implemented in SeaBIOS.

So if somewhere "nautilus" is entered, we can enter 5 more characters that then are used to decrypt some file, which is then not really used (I think `sub_f60c1` is some kind of free or unregistering function).

With a bit of guessing we know `flag.lzma.enc` should be a lzma archive, and 5 characters (most likely numbers) are bruteforcable:

```python
import lzma

orig = open("flag.lzma.enc", "rb")
dataOrig = orig.read()
orig.close()

def applyRound(key):
tmp1 = (key >> 0xF)&0xffff
tmp2 = (key >> 0xA)&0xffff
tmp3 = (key >> 0x8)&0xffff
tmp4 = (key >> 0x3)&0xffff
return ((key << 1) | ((tmp1 ^ tmp2 ^ tmp3 ^ tmp4) & 1))&0xffffffff

firstBytes = list(dataOrig[0:4])
shouldBe = [0x5d, 0x00, 0x00, 0x80] # header from the other lzma images

# bruteforce key
for a in range(10):
for b in range(10):
for c in range(10):
for d in range(10):
for e in range(10):

# check if the first 4 bytes match with the assumed header after decryption
key = a+b*10+c*100+d*1000+e*10000
failed = False
for i in range(4):
key = applyRound(key)
if(dataOrig[i]^(key&0xff) != shouldBe[i]):
failed = True
break

# if the header matched, fully decrypt and try to decompress using the LZMADecompressor
if not failed:
print(e, d, c, b, a)
dataTry = []
key = a+b*10+c*100+d*1000+e*10000
for q in dataOrig:
key = applyRound(key)
dataTry.append(q^(key&0xff))
dataTry = bytes(dataTry)
try:
dec = lzma.LZMADecompressor()
print("Decompress:", dec.decompress(dataTry, max_length=32))
# Save the decrypted files
f = open("flag."+str(key)+".lzma", "wb")
f.write(dataTry)
f.close()
except Exception as e:
pass
```

Which results in:

```
5 8 6 0 1
5 4 1 2 1
7 6 5 2 1
1 4 4 4 1
4 9 6 4 1
6 7 5 6 1
8 9 9 6 1
6 3 0 8 1
0 5 4 8 1
8 5 4 8 1
8 7 9 1 3
4 8 2 3 3
8 3 4 3 3
0 4 0 7 3
3 9 2 7 3
7 4 4 7 3
9 6 8 7 3
Decompress: b'APERTURE IMAGE FORMAT (c) 1985\n\n'
1 2 3 9 3
9 2 3 9 3
9 9 3 0 5
0 2 0 2 5
3 7 2 2 5
2 4 4 2 5
9 4 8 2 5
9 0 3 4 5
1 9 9 4 5
7 3 0 6 5
4 6 1 8 5
1 0 9 8 5
7 1 0 1 7
3 5 8 1 7
3 1 3 3 7
Decompress: b'APERTURE IMAGE FORMAT (c) 1985\n\n'
0 8 9 3 7
2 6 8 5 7
2 2 3 7 7
4 4 7 7 7
7 9 9 7 7
1 7 8 9 7
6 9 6 0 9
2 4 8 0 9
6 5 1 2 9
0 7 5 2 9
4 2 7 2 9
7 7 9 2 9
6 0 6 4 9
5 6 1 6 9
3 3 7 6 9
2 9 2 8 9
5 1 6 8 9
```

Both `9 6 8 7 3` and `3 1 3 3 7` yield the same output binary, which is in the "APERTURE IMAGE FORMAT".

Getting a [tool for this file format](http://portalwiki.asshatter.org/index.php/Aperture_Image_Format.html) and rendering it shows the flag:

![](img/biosflag.png)

(To get it to work in DOSBOX I also had to replace the `0A 0A 0D` line endings with `0D 0A` in the binary file)

With the flag being `Descent ][ Rules` (weird flag format..).

# not-so-advanced

RE the ROM, figure out the code. Not in the flag{} format

not-so-advanced is a GBA game that requests input and verifies whether it's a valid flag.

## Solution

Looking at the game it requests an input and verifies it whether it is correct:

![](img/game.png)

Loading the binary (Thumb, Load Address: 0x8000000) and looking for the strings shows the main function of it

![](img/gamecode.png)

The verifyFlag functions return value has to be `0x12e1` and from the verifyFlag function we can see that the input has to be 9 characters long.

![](img/gamecode2.png)

With this we can build a z3 model around it:

```python
# Input is a-z or _
for i in range(9):
solver.add(Or(And(flagString[i] >= ord('a'), flagString[i] <= ord('z')), flagString[i] == ord('_')))

v12 = 1
v14 = 0
for i in range(9):
v12 = weirdFun(v12 + ZeroExt(32, flagString[i]), 0xfff1)
v14 = weirdFun(v14 + v12, 0xfff1)

solver.add((v14^v12)&0xffff == 0x12e1)
```

Now the last question is what the `weirdFun` does, but just by guessing some common methods (and matching it with the code) we guessed it might just be `a % b` which was true.

The solver outputs many valid flags (e.g. `nb__dcf_d` (again weird flag format)) that work as a solution.

Original writeup (https://github.com/Pusty/writeups/tree/master/DEFCONCTFQuals2022#bios).