~fluix/fluix.one

ee26685caa003aa502fedcdfd9d3a36cda32d67c — Steven Guikal 1 year, 2 months ago 4794340
Start headings at h2 level
M content/blog/arts-show.md => content/blog/arts-show.md +5 -5
@@ 7,7 7,7 @@ Back in May, a month before the end of school, the school's art department had p

To provide some background, none of us had any formal theater training, and our school isn't very big on theatrical performances, so a lot of this was new and experimental for us. I've had interest in [technical theater](https://en.wikipedia.org/wiki/Stagecraft) for some time now and decided to take some ideas from there, namely the idea of cues. Essentially, a stage manager calls out cues (in our case, numbers) to people responsible for lights, music, etc. who then "take" the cue, performing the necessary transition in lights, music, etc. This makes a single person responsible for the timing of the show, but also makes it far simpler to organize, and even more importantly **change** parts of the show.

# Music
## Music

This might seem like a super simple setup: just drop some files in a folder and double click them to play as necessary. To be honest, that likely would have worked and been *good enough*, but I wanted something that better fit this list of objectives I held in my head:



@@ 18,7 18,7 @@ This might seem like a super simple setup: just drop some files in a folder and 

So that music-in-a-folder approach may be adaptable and reliable (depending on chosen media player), but the UI is certainly not simple. You're nearly guaranteed an extra window opening and a method to navigate between the current and next piece requiring either a mouse or the arrow keys. Also, playing a song and a video at the same time *could* get complicated. *Again, this is probably good enough, but maybe there's a better approach?*

## Linux Show Player
### Linux Show Player

I don't quite recall how I came upon [Linux Show Player](https://www.linux-show-player.org/) — likely while exploring open source cueing or playlist software — but it happened to be exactly what I needed, and not much else: perfect! Here's the main UI:



@@ 32,7 32,7 @@ The other UI buttons pause/resume, stop, interrupt (fade-out, then stop), fade i

After setting it up, the main features proved reliable enough for a live performance, so it was time to see whether Linux Show Player was flexible enough to also handle videos.

# Projections
## Projections

At the time of setting up for the performance, and at the time of writing, Linux Show Player does not yet support video cues[^1], but there were several parts in the performance where videos had to be projected on a screen or the stage, once at the same time as music. Specifically, that's the aforementioned cues #5 and #6, where #6 is a short video to be played for the first part of the dance with music cue #5. 



@@ 55,7 55,7 @@ This type of cue allows executing an arbitrary command so all that's left is fin

My everyday media player actually already fit this description, so I stuck with it.

## mpv
### mpv

[mpv](https://mpv.io/) is an amazing, open source, cross-platform, media player. It plays music and videos in a wide range of formats, all in a super minimal, but oh-so-configurable, player. It also comes with an IPC server to control playback and the ability to stay open after playing a file. Here's the full config used for the show:



@@ 81,7 81,7 @@ MEDIA="..."; printf '{ "command": ["loadfile", "%s"] }\n' $MEDIA|socat - /tmp/mp

With this, the video file specified in `$MEDIA` is loaded and immediately played by mpv which is already running on the second display, all controlled by Linux Show Player.

# Conclusion
## Conclusion

That's really it: two programs which made up our entire music and projection setup for the show. Is this how it's done professionally? Probably not, but it worked for us. My laptop's audio output was connected to a soundboard where I mixed the music and microphones. The projector was connected through HDMI and some long distance HDMI-ethernet-HDMI converter boxes. Lighting was also done with cues and controlled by a friend on the school's [ETC ColorSource 20](https://www.etcconnect.com/Products/Consoles/ColorSource/Features.aspx).


M content/blog/csictf-2020-pwn-intended.md => content/blog/csictf-2020-pwn-intended.md +3 -3
@@ 6,7 6,7 @@ draft: false

My [team](https://ctftime.org/team/127228) and I participated in [csictf](https://ctf.csivit.com/) 2020 and enjoyed it quite a bit. This blog post will be a writeup of the `pwn-intended-0x1`, `pwn-intended-0x2`, and `pwn-intended-0x3` problems. Once again this writeup is released really late, but maybe it'll still be useful to some -- or just a good read.

# pwn-intended-0x1
## pwn-intended-0x1
The writeup for this challenge will be more detailed, in part because I want to understand how the stack is used in assembly. This challenge can be trivially solved by just bashing the keyboard. Hopefully this deeper explanation will provide more insight into the lower level computation. WIth that, let's begin.

For this challenge we are given an executable which asks for some input on startup. Let's decompile it with [`r2ghidra-dec`](https://github.com/radareorg/r2ghidra-dec) -- a [Ghidra](https://ghidra-sre.org/) decompiler integration into [radare](https://www.radare.org/r/).


@@ 79,7 79,7 @@ The flag we get is: `csictf{y0u_ov3rfl0w3d_th@t_c0ff33l1ke@_buff3r}`

[^1]: We can do this because input is taken with `gets()` which, as described in the `gets` manpage (`man 3 gets`) is unsafe because it will continue reading data until reaching a specific character like a newline.

# pwn-intended-0x2
## pwn-intended-0x2
This problem is nearly identical to the last with the only difference being the final comparison. It now checks `var_4h` for the value `0xcafebabe` instead of `0`.
```sh
0x004011ca      817dfcbebafe.  cmp dword [var_4h], 0xcafebabe


@@ 97,7 97,7 @@ p.interactive()

We get the flag: `csictf{c4n_y0u_re4lly_telep0rt?}`

# pwn-intended-0x3
## pwn-intended-0x3
The final problem requires that you call a `flag()` function which reads the flag. Looking at the disassembly, we can see another buffer, this time of size `0x20` (32 in decimal).
```sh
┌ 104: int main (int argc, char **argv, char **envp);

M content/blog/dmoj-ctf-20-binexp.md => content/blog/dmoj-ctf-20-binexp.md +4 -4
@@ 11,7 11,7 @@ This blog post covers the solutions to the binary exploitation problems of [DMOJ

These problems are relatively simple and cover some of the most basic techniques when it comes to binary exploitation so don't be scared to give them a try. All of these techniques can become very useful later down the line and are often used as part of larger, more complex exploits.

# Super Secure Pseudorandom Number Generator
## Super Secure Pseudorandom Number Generator
This problem had a simple menu which allowed the generation of random numbers and guessing of a single random number. If the correct number was guessed, the flag would get printed to `stderr` and you would solve the challenge.

This first section of code can be seen initializing the `rand()` seed with the current time (in seconds) and setting the balance to `999999999`:


@@ 97,7 97,7 @@ int main() {
}
```

# Strings
## Strings
This problem's *solution* is arguably simpler than the last, but requires some knowledge of C and format strings. The entire problem code is below:
```c
#pragma GCC optimize("O0")


@@ 129,7 129,7 @@ This program uses the `read` function to safely read user input, so we can't exp
%s%s%s
```

## Explanation
### Explanation
First off, this problem is both hardware dependent[^a] and glibc dependent. The [DMOJ Judge](https://github.com/dmoj/judge-server) has these kept constant across runs during the contest, but competitors' glibc versions are different and some make the intended solution impossible to test locally. The solution of `%s%s%s` will read the values pointed to by the registers `rdx`, `rcx`, and `r8` in that order. The values they point to are described below:
 - `rdx` points to the input buffer -- in this case `%s%s%s`.
 - `rcx` points to the value filled in by the `syscall` inside of `read` which is hardware dependent.


@@ 137,7 137,7 @@ First off, this problem is both hardware dependent[^a] and glibc dependent. The 

[^a]: This depends on your solution, if you use `%s` to get `rcx` it could point to an invalid memory location. Using something like `%p` to get `rcx` should work.

# Classic Buffer Overflow
## Classic Buffer Overflow
We now come to the final problem which has the solution in its name. The goal of the problem is to run a function called `win` whose pointer is printed on startup. Below is the entire source code of the problem:
```c
#pragma GCC optimize("O0")

M content/blog/ecoo-2021.md => content/blog/ecoo-2021.md +4 -4
@@ 6,7 6,7 @@ draft: false

On May 1st, 2021, the 36th annual Educational Computing Organization of Ontario (ECOO) Programming Contest was held. This contest has been the culmination of over a month of work by Theodore Preduta, [Larry Yuan](https://larry.science/), [Keenan Gugeler](https://dmoj.ca/user/Riolku), Christopher Trevisan, and myself, alongside Valentina Krasteva and David Stermole and the support of [ECOO](https://ecoo.org/) and [ECOO-CS](http://ecoocs.org/). This is my second year involved in the hosting of this event so I figured I would write about the setup and all that went right and wrong.

### Background
## Background

This programming contest was run on a platform called [DMOJ](https://dmoj.ca/), an [AGPL-licensed online judge](https://github.com/DMOJ/), for accepting competitor code and rating its correctness. [A fork](https://github.com/fluix-dev/ecoo-site) was created with various unnecessary functionalities removed. In a broad sense, DMOJ works in the following manner:



@@ 14,7 14,7 @@ This programming contest was run on a platform called [DMOJ](https://dmoj.ca/), 

This year's contest contained [six (6) problems](https://dmoj.ca/problems/?search=ECOO21) ranging in difficulty from complete beginner to the highest level of competitive programming. A big thanks goes to Keenan and Chris for creating these problems and [Andrew Qi Tang](https://andrewqt.github.io/) for testing them before the competition.

### Network
## Network

Nearly 700 people signed up to do the contest and we wanted to make sure that the site ran smoothly. Last year's approach was to use a smaller number (<5) of more powerful site servers behind a loadbalancer to distribute load. This vertical scaling approach worked quite well, but we decided to try a more horizontal-scaling based approach this year with a larger number of less powerful servers. Our entire network was setup on [DigitalOcean Droplets](https://www.digitalocean.com/products/droplets/) with the database and individual sites on 2 core / 2 GB RAM systems and everything else on 1 core / 1 GB RAM. All internal networking was done with DigitalOcean's provided private networking and formed the following topology:



@@ 43,7 43,7 @@ To end off this section, here are some mildly interesting statistics for the run

[^3]: From a quick `grep` of nginx logs — may not be accurate.

### Cheating
## Cheating

Cheating must be considered in any competitive activity, especially those in online environments. This year, all online resources were permitted which we hoped would decrease the usefulness of cheating. However, as this was still an individual contest, cheating by communicating with others was still likely. Luckily, since 2019,[^2] DMOJ has integrated the [Stanford Measure of Software Similarity (MOSS)](https://theory.stanford.edu/~aiken/moss/) API to automatically submit competitor source code and check for plagiarism. This system compares code similarity but has knowledge of language syntax so simple changes to style or variable naming is useless. As an excellent example, let's take these three submissions from three different students at the same school (you know who you are!) which MOSS flagged:



@@ 109,7 109,7 @@ for i in range(0, len(out), 2):

All three of these students, alongside nearly twenty (20) others have been disqualified: a similar amount of cheaters to last year so nothing too surprising. 

### Conclusion
## Conclusion

Overall, just like last year, I really enjoyed running this contest and setting up some of the infrastructure and systems behind it. While it definitely didn't run perfectly, I think we did pretty well and provided a good experience to competitors. Unfortunately, apart from the nginx (and other service) logs, we didn't really collect any kind of system metrics for future analysis. I was planning to setup Prometheus but couldn't do it in time. Next time, I'll definitely make it a priority so we can get some better insight into any kinds of bottlenecks and so I can write a much more detailed writeup!


M content/blog/rev4-ctf.md => content/blog/rev4-ctf.md +4 -4
@@ 7,7 7,7 @@ I recently got together with others to write some challenges for a CTF competiti

This was the first time I have ever written my own problem for a CTF so it was far from perfect but proved to be a nice challenge for competitors. Also, giving credit where credit is due, much of this problem took inspiration from a similar one in the Canadian Communications Security Establishment's Geek Seek CTF.

### The Start
## The Start

Competitors were first given [this file](bunny.pyc) to begin. Guessing from the extension or base64 encoded contents within, this was a clearly a byte-compiled Python file, but which version? Well, initially I had used Python 3.7 for this challenge because it was widely used as the default across Linux distributions and because of the numerous decompilers available. However, in a last minute change, I switched to Python 3.9 which was neither widely installed nor had decompilers available. This switch made the initial part of the challenge, understanding how to run the program harder, but not too difficult with some trial and error. Proceeding with the correct version gave the following output:[^1]



@@ 37,7 37,7 @@ Attempting to enter an incorrect code gives the following output:

Expected.

### So what next?
## So what next?

Understanding what the program actually does! Given that no decompiler for Python 3.9 existed, a few approaches could be tried. Some competitors read the Python bytecode to reconstruct the code, while others cleverly used the `strace` utility to figure out everything necessary that went on. Analysis of the binary itself could also reveal a function named `derive_key` with some nearby strings and variables like `password`, as well as a `real_derive_key` function... in a section of the file after an `ELF` header? What's up with that? For that, let's look at the original source code of the program (with an `exec` call expanded):



@@ 78,7 78,7 @@ Aha! So it seems like this program takes an input and passes it to `derive_key`,

*Creator note: this file was just made by concatenating the Python byte-compiled file and this Shared Object file.*

### Conclusion
## Conclusion

Ultimately, having this new binary, [`libreal.so`](libreal.so) should be enough to solve the challenge, even if one were to completely ignore the Python aspect. Disassembling or decompiling it with a variety of tools (such as Ghidra or Radare2) reveals the following code:



@@ 135,7 135,7 @@ That `lib()` function at the bottom is what actually reveals why the original pa
   (_)-(_)     Here's your flag: CTF{D0n7_w3_4ll_l0v3_50M3_Cy7h0n_fUn}
```

### Reflection
## Reflection

Ultimately, I think this challenge was *decent* for my first one ever. It had many solutions allowing for some great creativity while still proving difficult enough that only a few people succeeded in completing it.