Rating: 0

* **Category:** reversing
* **Points:** 200
* **Description:**

> ## Part 3:
> The final boss!
> Time to pull together your knowledge of Bash, Python, and stupidly-low-level
> assembly!!
> This time you have to write some assembly that we're going to run.. You'll see
> the output of your code through VNC for 60 seconds.
> Objective: Print the flag.
> What to know:
> Strings need to be alternating between the character you want to print and
> '0x1f'.
> To print a string you need to write those alternating bytes to the frame
> buffer (starting at 0x00b8000...just do it). Increment your pointer to move
> through this buffer.
> If you're having difficulty figuring out where the flag is stored in memory,
> this code snippet might help you out:
> ```
> get_ip:
> call next_line
> next_line:
> pop rax
> ret
> ```
> That'll put the address of pop rax into rax.
> Call serves as an alias for push rip (the instruction pointer - where we are
> in code) followed by `jmp ______` where whatever is next to the call fills in
> the blank.
> And in case this comes up, you shouldn't need to know where you are loaded in
> memory if you use that above snippet...
> Happy Reversing!!
> ```sh
> nc rev.chal.csaw.io 9004
> ```
> -Elyk
> [Makefile](https://ctf.csaw.io/files/b236e0cc11cba5b5fd134436a0c8c811/Makefile)
> [part-3-server.py](https://ctf.csaw.io/files/d3e7a84ffb4eeca992c9f458bf4c11ec/part-3-server.py)
> [tacOS-base.bin](https://ctf.csaw.io/files/acbf4fe9f0233ce3ed34c55fee34649e/tacOS-base.bin)

## Writeup

This is a challenge in multiple stages, each one having its own flag.
(Note: the original link contains all three stages)

The general theme is low-level x86 code and how it behaves after boot.
The difficulty is quite low, but it was fun.

### Stage 3

For Stage 3 we get a host and port again, this time we can send them a
hex-encoded binary that gets appended to the Stage 2 payload to be executed
after the flag is rendered, we then get a port on which we can observe the
binary over VNC.

The flag seems to be appended after our code, so I just wrote some asm that
hexdumps the bytes of our binary and everything after that in an infinite loop:

call next
pop rbp

mov edi, 0xb8000

mov rsi, byte [rbp]
inc rbp
call draw_byte
jmp loop

/* rdi: framebuffer */
/* rsi: byte */
/* == CLOBBERS == */
/* rsi, rbx, rax */

mov rbx, rsi

shr rsi, 4
call draw_nibble

mov rsi, rbx
call draw_nibble


/* rdi: framebuffer */
/* rsi: nibble */
/* == CLOBBERS == */
/* rax */

mov rax, rsi
and al, 0x0f
cmp al, 0x09
ja is_char

add al, 0x30
jmp output

add al, 0x41 - 0x0a

mov ah, 0x1f

mov word [rdi], ax
add rdi, 2


Sending this to the port and connecting via VNC reveals this:

![qemu stage 3 flag](https://losfuzzys.github.io/images/posts/2018-09-20-csawctfquals-tour-of-x86-stage3.png)

Writing this down and decoding this with this:

import binascii


yields the flag: