aboutsummaryrefslogtreecommitdiffstats
path: root/documentation/slides-final
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2021-07-21 19:37:15 +0200
committerLouis Burda <quent.burda@gmail.com>2021-07-21 19:37:15 +0200
commit6a321759f6f75e7e14a29fde7cd0fa359d14215e (patch)
treed3d4e8d1a8a93892ff8dcb9b83d1b0faedfa9bdf /documentation/slides-final
parent6a5e16ed307a1159d836aa2085f92ecb7532b0a4 (diff)
downloadenowars5-service-stldoctor-master.tar.gz
enowars5-service-stldoctor-master.zip
final tweaks to documentations, added intro and final presentation slidesHEADmaster
Diffstat (limited to 'documentation/slides-final')
-rw-r--r--documentation/slides-final/.gitignore1
-rw-r--r--documentation/slides-final/index.html768
-rw-r--r--documentation/slides-final/media/dirlist.pngbin0 -> 2322 bytes
-rw-r--r--documentation/slides-final/media/enowars5-timeout.pngbin0 -> 202709 bytes
-rw-r--r--documentation/slides-final/media/enowars5.pngbin0 -> 22214 bytes
-rw-r--r--documentation/slides-final/media/exploit-1-1.pngbin0 -> 16715 bytes
-rw-r--r--documentation/slides-final/media/exploit-1-2.pngbin0 -> 26940 bytes
-rw-r--r--documentation/slides-final/media/exploit-1-3.pngbin0 -> 52090 bytes
-rw-r--r--documentation/slides-final/media/exploit-1-4.pngbin0 -> 70074 bytes
-rw-r--r--documentation/slides-final/media/exploit-1-5.pngbin0 -> 71647 bytes
-rw-r--r--documentation/slides-final/media/exploit-2-1.pngbin0 -> 46589 bytes
-rw-r--r--documentation/slides-final/media/getdirentries.pngbin0 -> 135007 bytes
-rw-r--r--documentation/slides-final/media/player-meme-hashfunc.pngbin0 -> 221940 bytes
-rw-r--r--documentation/slides-final/media/player-meme-struggling.pngbin0 -> 99623 bytes
-rw-r--r--documentation/slides-final/media/readdir.pngbin0 -> 119892 bytes
-rw-r--r--documentation/slides-final/media/readdir_more.pngbin0 -> 124526 bytes
-rw-r--r--documentation/slides-final/media/search.gifbin0 -> 60562 bytes
-rw-r--r--documentation/slides-final/media/socat.gifbin0 -> 19413 bytes
-rw-r--r--documentation/slides-final/media/stl1.pngbin0 -> 17519 bytes
-rw-r--r--documentation/slides-final/media/stl2.pngbin0 -> 19783 bytes
-rw-r--r--documentation/slides-final/media/stl3.pngbin0 -> 16751 bytes
-rw-r--r--documentation/slides-final/media/stldoc.pngbin0 -> 114257 bytes
-rw-r--r--documentation/slides-final/media/stldoc_dead.pngbin0 -> 686794 bytes
-rw-r--r--documentation/slides-final/media/stldoc_dead_offline.pngbin0 -> 142293 bytes
-rw-r--r--documentation/slides-final/media/stldoc_dead_r17.pngbin0 -> 148922 bytes
-rw-r--r--documentation/slides-final/media/stldoc_dead_r432.pngbin0 -> 267521 bytes
-rw-r--r--documentation/slides-final/media/stldoc_dead_r469.pngbin0 -> 250294 bytes
-rw-r--r--documentation/slides-final/slides.md253
-rw-r--r--documentation/slides-final/stldoctor.pdfbin0 -> 2073788 bytes
29 files changed, 1022 insertions, 0 deletions
diff --git a/documentation/slides-final/.gitignore b/documentation/slides-final/.gitignore
new file mode 100644
index 0000000..e4e7469
--- /dev/null
+++ b/documentation/slides-final/.gitignore
@@ -0,0 +1 @@
+slides
diff --git a/documentation/slides-final/index.html b/documentation/slides-final/index.html
new file mode 100644
index 0000000..b7457ef
--- /dev/null
+++ b/documentation/slides-final/index.html
@@ -0,0 +1,768 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
+ <title>STLDoctor</title>
+ <style type="text/css">
+ body {
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ color: #222;
+ font-size: 100%;
+}
+
+.slide {
+ position: absolute;
+ top: 0; bottom: 0;
+ left: 0; right: 0;
+ background-color: #f7f7f7;
+}
+
+.slide-content {
+ width: 800px;
+ height: 600px;
+ overflow: hidden;
+ margin: 80px auto 0 auto;
+ padding: 30px;
+
+ font-weight: 200;
+ font-size: 200%;
+ line-height: 1.375;
+}
+
+.controls {
+ position: absolute;
+ bottom: 20px;
+ left: 20px;
+}
+
+.arrow {
+ width: 0; height: 0;
+ border: 30px solid #333;
+ float: left;
+ margin-right: 30px;
+
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.prev {
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ border-left-color: transparent;
+
+ border-left-width: 0;
+ border-right-width: 50px;
+}
+
+.next {
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ border-right-color: transparent;
+
+ border-left-width: 50px;
+ border-right-width: 0;
+}
+
+.prev:hover {
+ border-right-color: #888;
+ cursor: pointer;
+}
+
+.next:hover {
+ border-left-color: #888;
+ cursor: pointer;
+}
+
+h1 {
+ font-size: 300%;
+ line-height: 1.2;
+ text-align: center;
+ margin: 170px 0 0;
+}
+
+h2 {
+ font-size: 100%;
+ line-height: 1.2;
+ margin: 5px 0;
+ text-align: center;
+ font-weight: 200;
+}
+
+h3 {
+ font-size: 140%;
+ line-height: 1.2;
+ border-bottom: 1px solid #aaa;
+ margin: 0;
+ padding-bottom: 15px;
+}
+
+ul {
+ padding: 20px 0 0 60px;
+ font-weight: 200;
+ line-height: 1.375;
+}
+
+.author h1 {
+ font-size: 170%;
+ font-weight: 200;
+ text-align: center;
+ margin-bottom: 30px;
+}
+
+.author h3 {
+ font-weight: 100;
+ text-align: center;
+ font-size: 95%;
+ border: none;
+}
+
+a {
+ text-decoration: none;
+ color: #44a4dd;
+}
+
+a:hover {
+ color: #66b5ff;
+}
+
+pre {
+ font-size: 60%;
+ line-height: 1.3;
+}
+
+.progress {
+ position: fixed;
+ top: 0; left: 0; right: 0;
+ height: 3px;
+ z-index: 1;
+}
+
+.progress-bar {
+ width: 0%;
+ height: 3px;
+ background-color: #b4b4b4;
+
+ -webkit-transition: width 0.05s ease-out;
+ -moz-transition: width 0.05s ease-out;
+ -o-transition: width 0.05s ease-out;
+ transition: width 0.05s ease-out;
+}
+
+.hidden {
+ display: none;
+}
+
+@media (max-width: 850px) {
+
+ body {
+ font-size: 70%;
+ }
+
+ .slide-content {
+ width: auto;
+ }
+
+ img {
+ width: 100%;
+ }
+
+ h1 {
+ margin-top: 120px;
+ }
+
+ .prev, .prev:hover {
+ border-right-color: rgba(135, 135, 135, 0.5);
+ }
+
+ .next, .next:hover {
+ border-left-color: rgba(135, 135, 135, 0.5);
+ }
+}
+
+@media (max-width: 480px) {
+ body {
+ font-size: 50%;
+ overflow: hidden;
+ }
+
+ .slide-content {
+ padding: 10px;
+ margin-top: 10px;
+ height: 340px;
+ }
+
+ h1 {
+ margin-top: 50px;
+ }
+
+ ul {
+ padding-left: 25px;
+ }
+}
+
+@media print {
+ * {
+ -webkit-print-color-adjust: exact;
+ }
+
+ @page {
+ size: letter;
+ }
+
+ .hidden {
+ display: inline;
+ }
+
+ html {
+ width: 100%;
+ height: 100%;
+ overflow: visible;
+ }
+
+ body {
+ margin: 0 auto !important;
+ border: 0;
+ padding: 0;
+ float: none !important;
+ overflow: visible;
+ background: none !important;
+ font-size: 52%;
+ }
+
+ .progress, .controls {
+ display: none;
+ }
+
+ .slide {
+ position: static;
+ }
+
+ .slide-content {
+ border: 1px solid #222;
+ margin-top: 0;
+ margin-bottom: 40px;
+ height: 3.5in;
+ overflow: visible;
+ }
+
+ .slide:nth-child(even) {
+ /* 2 slides per page */
+ page-break-before: always;
+ }
+}
+
+/*
+
+github.com style (c) Vasily Polovnyov <vast@whiteants.net>
+
+*/
+
+.hljs {
+ display: block;
+ overflow-x: auto;
+ padding: 0.5em;
+ color: #333;
+ background: #f8f8f8;
+}
+
+.hljs-comment,
+.hljs-quote {
+ color: #998;
+ font-style: italic;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-subst {
+ color: #333;
+ font-weight: bold;
+}
+
+.hljs-number,
+.hljs-literal,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-tag .hljs-attr {
+ color: #008080;
+}
+
+.hljs-string,
+.hljs-doctag {
+ color: #d14;
+}
+
+.hljs-title,
+.hljs-section,
+.hljs-selector-id {
+ color: #900;
+ font-weight: bold;
+}
+
+.hljs-subst {
+ font-weight: normal;
+}
+
+.hljs-type,
+.hljs-class .hljs-title {
+ color: #458;
+ font-weight: bold;
+}
+
+.hljs-tag,
+.hljs-name,
+.hljs-attribute {
+ color: #000080;
+ font-weight: normal;
+}
+
+.hljs-regexp,
+.hljs-link {
+ color: #009926;
+}
+
+.hljs-symbol,
+.hljs-bullet {
+ color: #990073;
+}
+
+.hljs-built_in,
+.hljs-builtin-name {
+ color: #0086b3;
+}
+
+.hljs-meta {
+ color: #999;
+ font-weight: bold;
+}
+
+.hljs-deletion {
+ background: #fdd;
+}
+
+.hljs-addition {
+ background: #dfd;
+}
+
+.hljs-emphasis {
+ font-style: italic;
+}
+
+.hljs-strong {
+ font-weight: bold;
+}
+
+
+ </style>
+</head>
+<body>
+ <div class="progress">
+ <div class="progress-bar"></div>
+ </div>
+
+ <div class="slide" id="slide-1">
+ <section class="slide-content"><style>
+
+.footnote {
+ font-size: 16pt;
+ position: absolute;
+ color: gray;
+ bottom: 0px;
+ right: 0px;
+}
+
+.slide-content {
+ position: relative;
+}
+
+.slide-content > ul >li {
+ padding: 7px 0px;
+}
+
+.slide-content > p > img {
+ width: 100%;
+}
+
+</style></section>
+ </div>
+ <div class="slide hidden" id="slide-2">
+ <section class="slide-content"><!-- Recap of the service and the problems I
+encountered preparing for the CTF and during the CTF -->
+<h1 id="stldoctor-">STLDoctor 💉</h1>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-3">
+ <section class="slide-content"><h3 id="index-">Index 🗄️</h3>
+<ul>
+<li>Service recap</li>
+<li>Optimization</li>
+<li>ENOWARS 5</li>
+<li>Reflection</li>
+</ul>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-4">
+ <section class="slide-content"><h3 id="refreshing-memories-">Refreshing Memories 💾</h3>
+<ul>
+<li>Plaintext service written in C</li>
+<li>Users upload STL files for parsing</li>
+<li>Private and public storage (2 flagstores)</li>
+<li><ol>
+<li>Vuln: Deserialization</li>
+</ol>
+</li>
+<li><ol start="2">
+<li>Vuln: Hash preimage</li>
+</ol>
+</li>
+</ul>
+<p><img style="width:300px !important; height:240px; position:absolute; bottom:80px; right:70px;" src="media/stldoc.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-5">
+ <section class="slide-content"><h3 id="since-last-meeting-">Since Last Meeting ⏩</h3>
+<!-- Of these three, we want to take a closer look
+at the performance improvements necessary -->
+<ul>
+<li>Performance improvements</li>
+<li>Added service fluff</li>
+</ul>
+<p><img id=img1 src="media/stl1.png">
+<img id=img2 src="media/stl2.png">
+<img id=img3 src="media/stl3.png"></p>
+<style>
+ #img1 {
+ position: absolute;
+ left: 2.5%;
+ bottom: 7%;
+ width: 30%;
+ }
+ #img2 {
+ position: absolute;
+ left: 35%;
+ bottom: 7%;
+ width: 30%;
+ }
+ #img3 {
+ position: absolute;
+ left: 67.5%;
+ bottom: 7%;
+ width: 30%;
+ }
+</style></section>
+ </div>
+ <div class="slide hidden" id="slide-6">
+ <section class="slide-content"><h3 id="issues-">Issues 😒</h3>
+<!-- since there were some slow io operations and
+either memory leak issues with pwnlib (witout patch)
+or engine request issues with the patch,
+sooo I decided to refactor to use enochecker3 for asyncio
+
+also noticed that I was checking the same thing multiple times
+in the checker, so tried to condense functionality -->
+<ul>
+<li>Slow search / list operations</li>
+<li>Enochecker memory leak without patch</li>
+<li>Engine error on worker restart with patch</li>
+<li>Logs not showing up in ELK</li>
+</ul>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-7">
+ <section class="slide-content"><h3 id="solutions-">Solutions 💡</h3>
+<ul>
+<li>Index files with locks for directory listing</li>
+<li>Refactored checker for asyncio</li>
+<li>Condensed checker functionality</li>
+<li>Increase docker-compose log size</li>
+</ul>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-8">
+ <section class="slide-content"><h1 id="enowars-5">ENOWARS 5</h1>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-9">
+ <section class="slide-content"><h3 id="oserror-">OSError 💢</h3>
+<ul>
+<li>Checker throws <code>INTERNAL_ERROR</code> on bad connection</li>
+<li>Fixed in c97789ad.. of enochecker3</li>
+</ul>
+<p><img style="" src="media/stldoc_dead_offline.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-10">
+ <section class="slide-content"><h3 id="checker-overload-">Checker Overload 💥</h3>
+<!-- all of a sudden all checker tasks are being aborted.
+Since all tasks were aborted, all workers must be affected
+and a blockage of a single worker could not have been the
+cause..
+During the ctf we found the checker at high load..
+Suspected that OFFLINE/unresponsive teams could be slowing
+down the service since then the timeouts are too large and the
+queue couldnt be emptied fast enough -->
+<ul>
+<li>Checker tasks being aborted for every team</li>
+</ul>
+<p><img style="height: 80%" src="media/stldoc_dead_r432.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-11">
+ <section class="slide-content"><h3 id="checker-overload-">Checker Overload 💥</h3>
+<!-- MEME CREDIT: Liikt -->
+<p><img style="height: 80%" src="media/stldoc_dead.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-12">
+ <section class="slide-content"><h3 id="anomaly-">Anomaly 👽</h3>
+<!-- service didnt timeout except on vulnboxes where everything
+seemed to be running weirdly, so unsure how to debug -->
+<p><img style="" src="media/enowars5-timeout.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-13">
+ <section class="slide-content"><h3 id="feedback-">Feedback 🤔</h3>
+<ul>
+<li><ol>
+<li>flagstore exploited after ~4h (R190)</li>
+</ol>
+</li>
+<li><ol start="2">
+<li>flagstore not exploited</li>
+</ol>
+</li>
+</ul>
+<!-- MEME CREDIT: [KuK] cluosh -->
+<p><img style="position:absolute; right:0px; height:300px; width:450px" src="media/player-meme-struggling.png">
+<img style="position:absolute; left:0px; height:300px; width: 400px;" src="media/player-meme-hashfunc.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-14">
+ <section class="slide-content"><h3 id="conclusion-">Conclusion 🎉</h3>
+<ul>
+<li>Relatively good uptime</li>
+<li>Not too easy / hard</li>
+<li>Users found vulns interesting</li>
+<li>No (known) unintended vuln</li>
+<li>Had a lot of fun</li>
+</ul>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-15">
+ <section class="slide-content"></section>
+ </div>
+ <div class="slide hidden" id="slide-16">
+ <section class="slide-content"><h3 id="slow-io-">Slow IO 🐌</h3>
+<!-- Noticed that running 'ls' on the service upload directory
+takes very long
+implementation in e.g. glibc actually pretty sane (see end slides)
+but bad cache performance / buffer not used / docker overlay fs -->
+<ul>
+<li>Enumerating files in a directory is expensive</li>
+<li>Index file per directory containing file names</li>
+<li>File locks to ensure exclusive writes</li>
+</ul>
+<p><img style="position:absolute; bottom: 30%; left:10%; width: 70% !important;" src="media/dirlist.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-17">
+ <section class="slide-content"><h3 id="investigating-readdir-">Investigating <code>readdir(..)</code> 🔍</h3>
+<!-- What makes readdir slow? actually looks like a sane implementation.
+We buffer an amount of entries and rebuffer when we run out.
+My guess is that we can buffer more with a regular file (also we have the choice).
+Better cache performance?
+Although the read is from one location, is probably just an abstraction
+Source: GLIBC 2.0.2-->
+<p><code>__readdir(..)</code>:</p>
+<p><img style="" src="media/readdir.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-18">
+ <section class="slide-content"><h3 id="investigating-readdir-">Investigating <code>readdir(..)</code> 🔍</h3>
+<p><code>__get_dir_entries(..)</code>:</p>
+<p><img style="" src="media/getdirentries.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-19">
+ <section class="slide-content"><h3 id="checker-overload">Checker Overload</h3>
+<p><img style="" src="media/stldoc_dead_r17.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-20">
+ <section class="slide-content"><h3 id="checker-overload">Checker Overload</h3>
+<p><img style="" src="media/stldoc_dead_r469.png"></p>
+</section>
+ </div>
+ <div class="slide hidden" id="slide-21">
+ <section class="slide-content"><script>
+ // var slide_headers = document.querySelectorAll(".slide-content > h3");
+ // for (var i = 0; i < slide_headers.length; i++) {
+ // var img = document.createElement('img')
+ // img.src = "logo.png";
+ // img.style = "height: 2.4ex; padding-right: 10px; float:right";
+ // slide_headers[i].append(img);
+ // }
+</script></section>
+ </div>
+
+
+
+ <script type="text/javascript">
+ /**
+ * Returns the current page number of the presentation.
+ */
+function currentPosition() {
+ return parseInt(document.querySelector('.slide:not(.hidden)').id.slice(6));
+}
+
+
+/**
+ * Navigates forward n pages
+ * If n is negative, we will navigate in reverse
+ */
+function navigate(n) {
+ var position = currentPosition();
+ var numSlides = document.getElementsByClassName('slide').length;
+
+ /* Positions are 1-indexed, so we need to add and subtract 1 */
+ var nextPosition = (position - 1 + n) % numSlides + 1;
+
+ /* Normalize nextPosition in-case of a negative modulo result */
+ nextPosition = (nextPosition - 1 + numSlides) % numSlides + 1;
+
+ document.getElementById('slide-' + position).classList.add('hidden');
+ document.getElementById('slide-' + nextPosition).classList.remove('hidden');
+
+ updateProgress();
+ updateURL();
+ updateTabIndex();
+}
+
+
+/**
+ * Updates the current URL to include a hashtag of the current page number.
+ */
+function updateURL() {
+ try {
+ window.history.replaceState({} , null, '#' + currentPosition());
+ } catch (e) {
+ window.location.hash = currentPosition();
+ }
+}
+
+
+/**
+ * Sets the progress indicator.
+ */
+function updateProgress() {
+ var progressBar = document.querySelector('.progress-bar');
+
+ if (progressBar !== null) {
+ var numSlides = document.getElementsByClassName('slide').length;
+ var position = currentPosition() - 1;
+ var percent = (numSlides === 1) ? 100 : 100 * position / (numSlides - 1);
+ progressBar.style.width = percent.toString() + '%';
+ }
+}
+
+
+/**
+ * Removes tabindex property from all links on the current slide, sets
+ * tabindex = -1 for all links on other slides. Prevents slides from appearing
+ * out of control.
+ */
+function updateTabIndex() {
+ var allLinks = document.querySelectorAll('.slide a');
+ var position = currentPosition();
+ var currentPageLinks = document.getElementById('slide-' + position).querySelectorAll('a');
+ var i;
+
+ for (i = 0; i < allLinks.length; i++) {
+ allLinks[i].setAttribute('tabindex', -1);
+ }
+
+ for (i = 0; i < currentPageLinks.length; i++) {
+ currentPageLinks[i].removeAttribute('tabindex');
+ }
+}
+
+/**
+ * Determines whether or not we are currently in full screen mode
+ */
+function isFullScreen() {
+ return document.fullscreenElement ||
+ document.mozFullScreenElement ||
+ document.webkitFullscreenElement ||
+ document.msFullscreenElement;
+}
+
+/**
+ * Toggle fullScreen mode on document element.
+ * Works on chrome (>= 15), firefox (>= 9), ie (>= 11), opera(>= 12.1), safari (>= 5).
+ */
+function toggleFullScreen() {
+ /* Convenient renames */
+ var docElem = document.documentElement;
+ var doc = document;
+
+ docElem.requestFullscreen =
+ docElem.requestFullscreen ||
+ docElem.msRequestFullscreen ||
+ docElem.mozRequestFullScreen ||
+ docElem.webkitRequestFullscreen.bind(docElem, Element.ALLOW_KEYBOARD_INPUT);
+
+ doc.exitFullscreen =
+ doc.exitFullscreen ||
+ doc.msExitFullscreen ||
+ doc.mozCancelFullScreen ||
+ doc.webkitExitFullscreen;
+
+ isFullScreen() ? doc.exitFullscreen() : docElem.requestFullscreen();
+}
+
+document.addEventListener('DOMContentLoaded', function () {
+ // Update the tabindex to prevent weird slide transitioning
+ updateTabIndex();
+
+ // If the location hash specifies a page number, go to it.
+ var page = window.location.hash.slice(1);
+ if (page) {
+ navigate(parseInt(page) - 1);
+ }
+
+ document.onkeydown = function (e) {
+ var kc = e.keyCode;
+
+ // left, down, H, J, backspace, PgUp - BACK
+ // up, right, K, L, space, PgDn - FORWARD
+ // enter - FULLSCREEN
+ if (kc === 37 || kc === 40 || kc === 8 || kc === 72 || kc === 74 || kc === 33) {
+ navigate(-1);
+ } else if (kc === 38 || kc === 39 || kc === 32 || kc === 75 || kc === 76 || kc === 34) {
+ navigate(1);
+ } else if (kc === 13) {
+ toggleFullScreen();
+ }
+ };
+
+ if (document.querySelector('.next') && document.querySelector('.prev')) {
+ document.querySelector('.next').onclick = function (e) {
+ e.preventDefault();
+ navigate(1);
+ };
+
+ document.querySelector('.prev').onclick = function (e) {
+ e.preventDefault();
+ navigate(-1);
+ };
+ }
+});
+
+
+ </script>
+</body>
+</html>
diff --git a/documentation/slides-final/media/dirlist.png b/documentation/slides-final/media/dirlist.png
new file mode 100644
index 0000000..68985ad
--- /dev/null
+++ b/documentation/slides-final/media/dirlist.png
Binary files differ
diff --git a/documentation/slides-final/media/enowars5-timeout.png b/documentation/slides-final/media/enowars5-timeout.png
new file mode 100644
index 0000000..2dfecb2
--- /dev/null
+++ b/documentation/slides-final/media/enowars5-timeout.png
Binary files differ
diff --git a/documentation/slides-final/media/enowars5.png b/documentation/slides-final/media/enowars5.png
new file mode 100644
index 0000000..4dbba87
--- /dev/null
+++ b/documentation/slides-final/media/enowars5.png
Binary files differ
diff --git a/documentation/slides-final/media/exploit-1-1.png b/documentation/slides-final/media/exploit-1-1.png
new file mode 100644
index 0000000..b251075
--- /dev/null
+++ b/documentation/slides-final/media/exploit-1-1.png
Binary files differ
diff --git a/documentation/slides-final/media/exploit-1-2.png b/documentation/slides-final/media/exploit-1-2.png
new file mode 100644
index 0000000..e63f7d0
--- /dev/null
+++ b/documentation/slides-final/media/exploit-1-2.png
Binary files differ
diff --git a/documentation/slides-final/media/exploit-1-3.png b/documentation/slides-final/media/exploit-1-3.png
new file mode 100644
index 0000000..4dc961d
--- /dev/null
+++ b/documentation/slides-final/media/exploit-1-3.png
Binary files differ
diff --git a/documentation/slides-final/media/exploit-1-4.png b/documentation/slides-final/media/exploit-1-4.png
new file mode 100644
index 0000000..2d75f2f
--- /dev/null
+++ b/documentation/slides-final/media/exploit-1-4.png
Binary files differ
diff --git a/documentation/slides-final/media/exploit-1-5.png b/documentation/slides-final/media/exploit-1-5.png
new file mode 100644
index 0000000..874529b
--- /dev/null
+++ b/documentation/slides-final/media/exploit-1-5.png
Binary files differ
diff --git a/documentation/slides-final/media/exploit-2-1.png b/documentation/slides-final/media/exploit-2-1.png
new file mode 100644
index 0000000..91b0df7
--- /dev/null
+++ b/documentation/slides-final/media/exploit-2-1.png
Binary files differ
diff --git a/documentation/slides-final/media/getdirentries.png b/documentation/slides-final/media/getdirentries.png
new file mode 100644
index 0000000..e19c3e7
--- /dev/null
+++ b/documentation/slides-final/media/getdirentries.png
Binary files differ
diff --git a/documentation/slides-final/media/player-meme-hashfunc.png b/documentation/slides-final/media/player-meme-hashfunc.png
new file mode 100644
index 0000000..04077ca
--- /dev/null
+++ b/documentation/slides-final/media/player-meme-hashfunc.png
Binary files differ
diff --git a/documentation/slides-final/media/player-meme-struggling.png b/documentation/slides-final/media/player-meme-struggling.png
new file mode 100644
index 0000000..9863892
--- /dev/null
+++ b/documentation/slides-final/media/player-meme-struggling.png
Binary files differ
diff --git a/documentation/slides-final/media/readdir.png b/documentation/slides-final/media/readdir.png
new file mode 100644
index 0000000..a211c1f
--- /dev/null
+++ b/documentation/slides-final/media/readdir.png
Binary files differ
diff --git a/documentation/slides-final/media/readdir_more.png b/documentation/slides-final/media/readdir_more.png
new file mode 100644
index 0000000..c24c582
--- /dev/null
+++ b/documentation/slides-final/media/readdir_more.png
Binary files differ
diff --git a/documentation/slides-final/media/search.gif b/documentation/slides-final/media/search.gif
new file mode 100644
index 0000000..de4ed18
--- /dev/null
+++ b/documentation/slides-final/media/search.gif
Binary files differ
diff --git a/documentation/slides-final/media/socat.gif b/documentation/slides-final/media/socat.gif
new file mode 100644
index 0000000..38f1e93
--- /dev/null
+++ b/documentation/slides-final/media/socat.gif
Binary files differ
diff --git a/documentation/slides-final/media/stl1.png b/documentation/slides-final/media/stl1.png
new file mode 100644
index 0000000..cef284a
--- /dev/null
+++ b/documentation/slides-final/media/stl1.png
Binary files differ
diff --git a/documentation/slides-final/media/stl2.png b/documentation/slides-final/media/stl2.png
new file mode 100644
index 0000000..1201981
--- /dev/null
+++ b/documentation/slides-final/media/stl2.png
Binary files differ
diff --git a/documentation/slides-final/media/stl3.png b/documentation/slides-final/media/stl3.png
new file mode 100644
index 0000000..49045cc
--- /dev/null
+++ b/documentation/slides-final/media/stl3.png
Binary files differ
diff --git a/documentation/slides-final/media/stldoc.png b/documentation/slides-final/media/stldoc.png
new file mode 100644
index 0000000..f276ef7
--- /dev/null
+++ b/documentation/slides-final/media/stldoc.png
Binary files differ
diff --git a/documentation/slides-final/media/stldoc_dead.png b/documentation/slides-final/media/stldoc_dead.png
new file mode 100644
index 0000000..6838fbf
--- /dev/null
+++ b/documentation/slides-final/media/stldoc_dead.png
Binary files differ
diff --git a/documentation/slides-final/media/stldoc_dead_offline.png b/documentation/slides-final/media/stldoc_dead_offline.png
new file mode 100644
index 0000000..8cc3faa
--- /dev/null
+++ b/documentation/slides-final/media/stldoc_dead_offline.png
Binary files differ
diff --git a/documentation/slides-final/media/stldoc_dead_r17.png b/documentation/slides-final/media/stldoc_dead_r17.png
new file mode 100644
index 0000000..0fef751
--- /dev/null
+++ b/documentation/slides-final/media/stldoc_dead_r17.png
Binary files differ
diff --git a/documentation/slides-final/media/stldoc_dead_r432.png b/documentation/slides-final/media/stldoc_dead_r432.png
new file mode 100644
index 0000000..5985a1a
--- /dev/null
+++ b/documentation/slides-final/media/stldoc_dead_r432.png
Binary files differ
diff --git a/documentation/slides-final/media/stldoc_dead_r469.png b/documentation/slides-final/media/stldoc_dead_r469.png
new file mode 100644
index 0000000..d202b69
--- /dev/null
+++ b/documentation/slides-final/media/stldoc_dead_r469.png
Binary files differ
diff --git a/documentation/slides-final/slides.md b/documentation/slides-final/slides.md
new file mode 100644
index 0000000..54b1fa8
--- /dev/null
+++ b/documentation/slides-final/slides.md
@@ -0,0 +1,253 @@
+title: STLDoctor
+output: index.html
+controls: false
+
+--
+
+<style>
+
+.footnote {
+ font-size: 16pt;
+ position: absolute;
+ color: gray;
+ bottom: 0px;
+ right: 0px;
+}
+
+.slide-content {
+ position: relative;
+}
+
+.slide-content > ul >li {
+ padding: 7px 0px;
+}
+
+.slide-content > p > img {
+ width: 100%;
+}
+
+</style>
+
+--
+
+<!-- Recap of the service and the problems I
+encountered preparing for the CTF and during the CTF -->
+
+# STLDoctor 💉
+
+--
+
+### Index 🗄️
+
+- Service recap
+- Optimization
+- ENOWARS 5
+- Reflection
+
+--
+
+### Refreshing Memories 💾
+
+- Plaintext service written in C
+- Users upload STL files for parsing
+- Private and public storage (2 flagstores)
+- 1. Vuln: Deserialization
+- 2. Vuln: Hash preimage
+
+<img style="width:300px !important; height:240px; position:absolute; bottom:80px; right:70px;" src="media/stldoc.png">
+
+--
+
+### Since Last Meeting ⏩
+
+<!-- Of these three, we want to take a closer look
+at the performance improvements necessary -->
+
+- Performance improvements
+- Added service fluff
+
+<img id=img1 src="media/stl1.png">
+<img id=img2 src="media/stl2.png">
+<img id=img3 src="media/stl3.png">
+
+<style>
+ #img1 {
+ position: absolute;
+ left: 2.5%;
+ bottom: 7%;
+ width: 30%;
+ }
+ #img2 {
+ position: absolute;
+ left: 35%;
+ bottom: 7%;
+ width: 30%;
+ }
+ #img3 {
+ position: absolute;
+ left: 67.5%;
+ bottom: 7%;
+ width: 30%;
+ }
+</style>
+
+--
+
+### Issues 😒
+
+<!-- since there were some slow io operations and
+either memory leak issues with pwnlib (witout patch)
+or engine request issues with the patch,
+sooo I decided to refactor to use enochecker3 for asyncio
+
+also noticed that I was checking the same thing multiple times
+in the checker, so tried to condense functionality -->
+
+- Slow search / list operations
+- Enochecker memory leak without patch
+- Engine error on worker restart with patch
+- Logs not showing up in ELK
+
+--
+
+### Solutions 💡
+
+- Index files with locks for directory listing
+- Refactored checker for asyncio
+- Condensed checker functionality
+- Increase docker-compose log size
+
+--
+
+# ENOWARS 5
+
+--
+
+### OSError 💢
+
+- Checker throws `INTERNAL_ERROR` on bad connection
+- Fixed in c97789ad.. of enochecker3
+
+<img style="" src="media/stldoc_dead_offline.png">
+
+--
+
+### Checker Overload 💥
+
+<!-- all of a sudden all checker tasks are being aborted.
+Since all tasks were aborted, all workers must be affected
+and a blockage of a single worker could not have been the
+cause..
+During the ctf we found the checker at high load..
+Suspected that OFFLINE/unresponsive teams could be slowing
+down the service since then the timeouts are too large and the
+queue couldnt be emptied fast enough -->
+
+- Checker tasks being aborted for every team
+
+<img style="height: 80%" src="media/stldoc_dead_r432.png">
+
+--
+
+### Checker Overload 💥
+
+<!-- MEME CREDIT: Liikt -->
+<img style="height: 80%" src="media/stldoc_dead.png">
+
+--
+
+### Anomaly 👽
+
+<!-- service didnt timeout except on vulnboxes where everything
+seemed to be running weirdly, so unsure how to debug -->
+
+<img style="" src="media/enowars5-timeout.png">
+
+--
+
+### Feedback 🤔
+
+- 1. flagstore exploited after ~4h (R190)
+- 2. flagstore not exploited
+
+<!-- MEME CREDIT: [KuK] cluosh -->
+<img style="position:absolute; right:0px; height:300px; width:450px" src="media/player-meme-struggling.png">
+<img style="position:absolute; left:0px; height:300px; width: 400px;" src="media/player-meme-hashfunc.png">
+
+--
+
+### Conclusion 🎉
+
+- Relatively good uptime
+- Not too easy / hard
+- Users found vulns interesting
+- No (known) unintended vuln
+- Had a lot of fun
+
+--
+
+--
+
+### Slow IO 🐌
+
+<!-- Noticed that running 'ls' on the service upload directory
+takes very long
+implementation in e.g. glibc actually pretty sane (see end slides)
+but bad cache performance / buffer not used / docker overlay fs -->
+
+- Enumerating files in a directory is expensive
+- Index file per directory containing file names
+- File locks to ensure exclusive writes
+
+<img style="position:absolute; bottom: 30%; left:10%; width: 70% !important;" src="media/dirlist.png">
+
+--
+
+### Investigating `readdir(..)` 🔍
+
+<!-- What makes readdir slow? actually looks like a sane implementation.
+We buffer an amount of entries and rebuffer when we run out.
+My guess is that we can buffer more with a regular file (also we have the choice).
+Better cache performance?
+Although the read is from one location, is probably just an abstraction
+Source: GLIBC 2.0.2-->
+
+`__readdir(..)`:
+
+<img style="" src="media/readdir.png">
+
+--
+
+### Investigating `readdir(..)` 🔍
+
+`__get_dir_entries(..)`:
+
+<img style="" src="media/getdirentries.png">
+
+--
+
+### Checker Overload
+
+<img style="" src="media/stldoc_dead_r17.png">
+
+--
+
+### Checker Overload
+
+<img style="" src="media/stldoc_dead_r469.png">
+
+--
+
+
+
+
+
+<script>
+ // var slide_headers = document.querySelectorAll(".slide-content > h3");
+ // for (var i = 0; i < slide_headers.length; i++) {
+ // var img = document.createElement('img')
+ // img.src = "logo.png";
+ // img.style = "height: 2.4ex; padding-right: 10px; float:right";
+ // slide_headers[i].append(img);
+ // }
+</script>
diff --git a/documentation/slides-final/stldoctor.pdf b/documentation/slides-final/stldoctor.pdf
new file mode 100644
index 0000000..6667621
--- /dev/null
+++ b/documentation/slides-final/stldoctor.pdf
Binary files differ