Rating: 5.0

This is some kind of coreboot rom for x86. If we connect to the tcp service, we can first select a bit we'd like to flip from 1 to 0 and then the rom is executed with qemu.

We can also debug locally with qemu:

```
qemu-system-x86_64 -bios ./rom -s -S -monitor stdio
```

and then press `c` in the qemu monitor to continue. We can use `stop` in the qemu monitor to stop emulation, when the `force 3 seconds delay :)` message shows up in the serial output. We can also attach with gdb now and take a look around.

```
(gdb) target remote localhost:1234
```

On the serial console there is some output of the coreboot rom. It contains an interesing line, that looks like a description of mapped memory:

```
Writing coreboot table at 0x00fd7000
[...]
2. 00000000000c0000-00000000000c0fff: FLUX_FLAG
[...]
```

Indeed we can confirm in gdb that this is the location of the flag. The remote service will probably run with an unredacted flag.

```
(gdb) x/s 0xc0000
0xc0000: "flag{", 'x' <repeats 31 times>, "}"
```

The last couple of output lines of the log message is the following:

```
Loading segment from ROM address 0xfffe8b94
Entry Point 0x00100000
Loading Segment: addr: 0x0000000000100000 memsz: 0x000000000000d4c0 filesz: 0x00000000000070d0
Post relocation: addr: 0x0000000000100000 memsz: 0x000000000000d4c0 filesz: 0x00000000000070d0
it's not compressed!
Clearing Segment: addr: 0x00000000001070d0 memsz: 0x00000000000063f0
dest 00100000, end 0010d4c0, bouncebuffer ffffffff
```

So we can see that the code that does the flag validation is loaded at the address `0x100000`.

```
(qemu) x/10i 0x100000
0x00100000: eb 22 jmp 0x100024
0x00100002: 66 90 nop
0x00100004: 02 b0 ad 1b 03 00 addb 0x31bad(%eax), %dh
0x0010000a: 01 00 addl %eax, 0(%eax)
0x0010000c: fb sti
0x0010000d: 4f decl %edi
0x0010000e: 51 pushl %ecx
0x0010000f: e4 04 inb $4, %al
0x00100011: 00 10 addb %dl, 0(%eax)
0x00100013: 00 00 addb %al, 0(%eax)
```

I then searched for the bytes of these instructions in the rom blob to locate the code. At offset `0x28bb0` in the file, the code loaded at `0x100000` starts. I reversed this with binary ninja and gdb. Reversing with r2 works as well. You can map the relevant section with:

```
S 0x28bb0 0x100000 0x70d0 0xd4c0 main rwx
s 0x100000
e asm.bits=32
```

Searching for the `MISSED!` string I went backward to locate some check for the flag. At vaddr `0x10009e` is the function which does some check and then either prints the flag or the `MISSED!` string. This is the relevant code here:

```
| 0x00100136 84c0 test al, al
| ,=< 0x00100138 7512 jne 0x10014c ;[5]
| | 0x0010013a 83ec0c sub esp, 0xc
| | 0x0010013d 680d501000 push str.MISSED_0 ; 0x10500d ; "MISSED!"
| | 0x00100142 e85c3b0000 call write_serial ;[1] ; ssize_t write(int fd, void *ptr, size_t nbytes)
| | 0x00100147 83c410 add esp, 0x10
| ,==< 0x0010014a eb0e jmp 0x10015a ;[6]
| |`-> 0x0010014c 83ec0c sub esp, 0xc
| | 0x0010014f ff75ec push dword [local_14h]
| | 0x00100152 e84c3b0000 call write_serial ;[1] ; ssize_t write(int fd, void *ptr, size_t nbytes)
| | 0x00100157 83c410 add esp, 0x10
| | ; CODE XREF from fcn.0010009e (0x10014a)
| `--> 0x0010015a e801000000 call halt ;[2]
```

So my first attempt was to flip the `jne` instruction, from
```
0x00100138 7512 jne 0x10014c
```

to

```
0x00100138 7412 je 0x10014c
```

We don't see the `MISSED!` string anymore, but also no flag. :(

OK. We can do a bit more reversing and find out whether there is something fishy. I tried to find out where the flag was loaded and compared. In the same function the flag address is loaded by xoring two constants. The address of the flag is loaded at vaddr `0x1000c6` by xoring two words from the rom (at `0x106bb0`, `0x106bc4`). The result is the address `0xc8000`.

```
0x001000c6 8b15b06b1000 mov edx, dword [0x106bb0] ; [0x106bb0:4]=0xef56bf92
0x001000cc a1c46b1000 mov eax, dword [0x106bc4] ; [0x106bc4:4]=0xef5a3f92
0x001000d1 31d0 xor eax, edx
```

```
(gdb) print/x 0xef56bf92 ^ 0xef5a3f92
$1 = 0xc8000
```

This is a bit wrong, as the flag is loaded at `0xc0000`. There is just one-bit-xor difference between `0xc8000` and `0xc0000`:

```
0b11001000000000000000
^
0b11000000000000000000
==
0b00001000000000000000
```

We can flip a bit in the first of the two constant words which are xored such that the new loaded address
is `0xc0000` (aka the beginning of the `FLUX_FLAG` memory area). Then we get the flag :)

```
Enter target byte [0 - 262143]: 194401
]> 10111111 <[
Enter target bit: [0 - 7]: 7
}X> ---------------------------------------{0}
]> 00111111 <[

coreboot-4.8-1707-g33cd6d5-dirty Sun Oct 14 23:58:10 UTC 2018 ramstage starting...
Enumerating buses...
CPU_CLUSTER: 0 enabled
DOMAIN: 0000 enabled
QEMU: firmware config interface detected
QEMU: max_cpus is 1
CPU: APIC: 00 enabled
scan_bus: scanning of bus CPU_CLUSTER: 0 took 0 usecs
PCI: pci_scan_bus for bus 00
PCI: 00:00.0 [8086/1237] enabled
PCI: 00:01.0 [8086/7000] enabled
PCI: 00:01.1 [8086/7010] enabled
PCI: 00:01.3 [8086/7113] enabled
PCI: 00:02.0 [1234/1111] enabled
PCI: 00:03.0 [8086/100e] enabled
scan_bus: scanning of bus PCI: 00:01.0 took 0 usecs
scan_bus: scanning of bus PCI: 00:01.3 took 0 usecs
scan_bus: scanning of bus DOMAIN: 0000 took 0 usecs
scan_bus: scanning of bus Root Device took 0 usecs
done
found VGA at PCI: 00:02.0
Setting up VGA for PCI: 00:02.0
Setting PCI_BRIDGE_CTL_VGA for bridge DOMAIN: 0000
Setting PCI_BRIDGE_CTL_VGA for bridge Root Device
Allocating resources...
Reading resources...
QEMU: 11 files in fw_cfg
QEMU: bootorder [size=0]
QEMU: etc/acpi/rsdp [size=36]
QEMU: etc/acpi/tables [size=131072]
QEMU: etc/boot-fail-wait [size=4]
QEMU: etc/e820 [size=20]
QEMU: etc/smbios/smbios-anchor [size=31]
QEMU: etc/smbios/smbios-tables [size=320]
QEMU: etc/system-states [size=6]
QEMU: etc/table-loader [size=4096]
QEMU: etc/tpm/log [size=0]
QEMU: genroms/kvmvapic.bin [size=9216]
QEMU: e820/ram: 0x00000000 +0x01000000
QEMU: reserve ioports 0x0510-0x0511 [firmware-config]
QEMU: reserve ioports 0x5658-0x5658 [vmware-port]
QEMU: reserve ioports 0xae00-0xae0f [pci-hotplug]
QEMU: reserve ioports 0xaf00-0xaf1f [cpu-hotplug]
QEMU: reserve ioports 0xafe0-0xafe3 [piix4-gpe0]
Done reading resources.
Setting resources...
PCI: 00:01.1 20 <- [0x0000005840 - 0x000000584f] size 0x00000010 gran 0x04 io
PCI: 00:02.0 10 <- [0x00fd000000 - 0x00fdffffff] size 0x01000000 gran 0x18 prefmem
PCI: 00:02.0 18 <- [0x00fe070000 - 0x00fe070fff] size 0x00001000 gran 0x0c mem
PCI: 00:02.0 30 <- [0x00fe060000 - 0x00fe06ffff] size 0x00010000 gran 0x10 romem
PCI: 00:03.0 10 <- [0x00fe040000 - 0x00fe05ffff] size 0x00020000 gran 0x11 mem
PCI: 00:03.0 14 <- [0x0000005800 - 0x000000583f] size 0x00000040 gran 0x06 io
PCI: 00:03.0 30 <- [0x00fe000000 - 0x00fe03ffff] size 0x00040000 gran 0x12 romem
Done setting resources.
Done allocating resources.
Enabling resources...
PCI: 00:00.0 cmd <- 00
PCI: 00:01.0 cmd <- 00
PCI: 00:01.1 cmd <- 01
PCI: 00:01.3 cmd <- 00
PCI: 00:02.0 cmd <- 03
PCI: 00:03.0 cmd <- 03
done.
Initializing devices...
Root Device init ...
CPU_CLUSTER: 0 init ...
Initializing CPU #0
CPU: vendor Intel device 663
CPU: family 06, model 06, stepping 03
Setting up local APIC... apic_id: 0x00 done.
CPU #0 initialized
PCI: 00:00.0 init ...
Assigning IRQ 10 to 0:1.3
Assigning IRQ 11 to 0:3.0
PCI: 00:01.0 init ...
RTC Init
PCI: 00:01.1 init ...
IDE: Primary IDE interface: on
IDE: Secondary IDE interface: on
IDE: Access to legacy IDE ports: off
PCI: 00:02.0 init ...
PCI: 00:03.0 init ...
Devices initialized
Finalize devices...
Devices finalized
QEMU: found ACPI tables in fw_cfg.
QEMU: loading "etc/acpi/rsdp" to 0xfb3000 (len 36)
QEMU: loading "etc/acpi/tables" to 0xfb3040 (len 131072)
QEMU: loaded ACPI tables from fw_cfg.
ACPI tables: 131136 bytes.
smbios_write_tables: 00fb2000
DOMAIN: 0000 (QEMU Northbridge i440fx)
QEMU: found smbios tables in fw_cfg (len 320).
QEMU: coreboot type0 table found at 0xfb2020.
QEMU: loading smbios tables to 0xfb2065
SMBIOS tables: 421 bytes.
Writing table forward entry at 0x00000500
Wrote coreboot table at: 00000500, 0x10 bytes, checksum 8ee1
Writing coreboot table at 0x00fd7000
0. 0000000000000000-0000000000000fff: CONFIGURATION TABLES
1. 0000000000001000-000000000009ffff: RAM
2. 00000000000c0000-00000000000c0fff: FLUX_FLAG
3. 00000000000c1000-0000000000fb1fff: RAM
4. 0000000000fb2000-0000000000fdffff: CONFIGURATION TABLES
5. 0000000000fe0000-0000000000ffdfff: RAMSTAGE
6. 0000000000ffe000-0000000000ffffff: CONFIGURATION TABLES
7. 00000000ff800000-00000000ffffffff: RESERVED
ERROR: Unsupported tag 65544
CBFS: 'Master Header Locator' located CBFS at [10200:3ffc0)
FMAP: Found "FLASH" version 1.1 at 10000.
FMAP: base = fffc0000 size = 40000 #areas = 3
Wrote coreboot table at: 00fd7000, 0x210 bytes, checksum ee79
coreboot table: 552 bytes.
IMD ROOT 0. 00fff000 00001000
IMD SMALL 1. 00ffe000 00001000
RAMSTAGE 2. 00fdf000 0001f000
COREBOOT 3. 00fd7000 00008000
ACPI 4. 00fb3000 00024000
SMBIOS 5. 00fb2000 00000800
IMD small region:
IMD ROOT 0. 00ffec00 00000400
CAR GLOBALS 1. 00ffe9c0 00000240
COREBOOTFWD 2. 00ffe980 00000028
CBFS: 'Master Header Locator' located CBFS at [10200:3ffc0)
CBFS: Locating 'fallback/payload'
CBFS: Found @ offset 18940 size 7108
Loading segment from ROM address 0xfffe8b78
code (compression=0)
New segment dstaddr 0x100000 memsize 0xd4c0 srcaddr 0xfffe8bb0 filesize 0x70d0
Loading segment from ROM address 0xfffe8b94
Entry Point 0x00100000
Loading Segment: addr: 0x0000000000100000 memsz: 0x000000000000d4c0 filesz: 0x00000000000070d0
Post relocation: addr: 0x0000000000100000 memsz: 0x000000000000d4c0 filesz: 0x00000000000070d0
it's not compressed!
Clearing Segment: addr: 0x00000000001070d0 memsz: 0x00000000000063f0
dest 00100000, end 0010d4c0, bouncebuffer ffffffff
force 3 seconds delay :)
Jumping to boot code at 00100000(00fd7000)
FLAG if hit confirmed:
flag{only_cb_can_run_this_simple_elf}
qemu-system-i386: terminating on signal 15 from pid 25089 (python3)
```

sylvOct. 20, 2018, 11:02 a.m.

I like your approach.
well done :)